mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Merge branch 'devel' into concepts
This commit is contained in:
37
.mailmap
37
.mailmap
@@ -10,35 +10,35 @@
|
||||
|
||||
GITHUB: aldeed <eric@dairystatedesigns.com>
|
||||
GITHUB: AlexeyMK <alexey@alexeymk.com>
|
||||
GITHUB: apendua <apendua@gmail.com>
|
||||
GITHUB: Cangit <fredricendrerud@gmail.com>
|
||||
GITHUB: DenisGorbachev <Denis.Gorbachev@faster-than-wind.ru>
|
||||
GITHUB: EOT <eot@gmx.at>
|
||||
GITHUB: FooBarWidget <honglilai@gmail.com>
|
||||
GITHUB: Maxhodges <Max@whiterabbitpress.com>
|
||||
GITHUB: OyoKooN <nathan@sxnlabs.com>
|
||||
GITHUB: RobertLowe <robert@iblargz.com>
|
||||
GITHUB: ansman <nicklas@ansman.se>
|
||||
GITHUB: apendua <apendua@gmail.com>
|
||||
GITHUB: awwx <andrew.wilcox@gmail.com>
|
||||
GITHUB: babenzele <tim.p.phillips@gmail.com>
|
||||
GITHUB: Cangit <fredricendrerud@gmail.com>
|
||||
GITHUB: cmather <mather.chris@gmail.com>
|
||||
GITHUB: codeinthehole <david.winterbottom@gmail.com>
|
||||
GITHUB: cryptoquick <faustianightmare@gmail.com>
|
||||
GITHUB: dandv <ddascalescu+github@gmail.com>
|
||||
GITHUB: davegonzalez <gonzalez.dalex@gmail.com>
|
||||
GITHUB: DenisGorbachev <Denis.Gorbachev@faster-than-wind.ru>
|
||||
GITHUB: ducdigital <duc@ducdigital.com>
|
||||
GITHUB: duckspeaker <gallo.j@gmail.com>
|
||||
GITHUB: emgee3 <hello@gravitronic.com>
|
||||
GITHUB: EOT <eot@gmx.at>
|
||||
GITHUB: felixrabe <felix@rabe.io>
|
||||
GITHUB: FooBarWidget <honglilai@gmail.com>
|
||||
GITHUB: FredericoC <frederico.carvalho@3stack.com.au>
|
||||
GITHUB: Gaelan <gbs@canishe.com>
|
||||
GITHUB: icellan <icellan@icellan.com>
|
||||
GITHUB: ImtiazMajeed <imtiazmaj@gmail.com>
|
||||
GITHUB: jacott <geoffjacobsen@gmail.com>
|
||||
GITHUB: jfhamlin <jfhamlin@gmail.com>
|
||||
GITHUB: jbruni <contato@jbruni.com.br>
|
||||
GITHUB: justinsb <justin@fathomdb.com>
|
||||
GITHUB: jfhamlin <jfhamlin@gmail.com>
|
||||
GITHUB: jperl <perl.jonathan@gmail.com>
|
||||
GITHUB: kentonv <temporal@gmail.com>
|
||||
GITHUB: marcandre <github@marc-andre.ca>
|
||||
GITHUB: mart-jansink <m.jansink@gmail.com>
|
||||
GITHUB: Maxhodges <Max@whiterabbitpress.com>
|
||||
GITHUB: MaximDubrovin <maxxdubrovin@gmail.com>
|
||||
GITHUB: meawoppl <meawoppl@gmail.com>
|
||||
GITHUB: meonkeys <haircut@gmail.com>
|
||||
@@ -49,14 +49,22 @@ GITHUB: mizzao <mizzao@gmail.com>
|
||||
GITHUB: mquandalle <maxime.quandalle@gmail.com>
|
||||
GITHUB: nathan-muir <ndmuir@gmail.com>
|
||||
GITHUB: Neftedollar <oildollar@gmail.com>
|
||||
GITHUB: OyoKooN <nathan@sxnlabs.com>
|
||||
GITHUB: paulswartz <paulswartz@gmail.com>
|
||||
GITHUB: Pent <jon@empire5design.com>
|
||||
GITHUB: prapicault <pascal@rapicault.net>
|
||||
GITHUB: prapicault <pascal@rapicorp.com>
|
||||
GITHUB: pscanf <paolo.scanferla@mondora.com>
|
||||
GITHUB: queso <joshua.owens@gmail.com>
|
||||
GITHUB: rcy <rcyeske@gmail.com>
|
||||
GITHUB: RichardLitt <richard.littauer@gmail.com>
|
||||
GITHUB: rdickert <robert.dickert@gmail.com>
|
||||
GITHUB: rgould <rwgould@gmail.com>
|
||||
GITHUB: RichardLitt <richard.littauer@gmail.com>
|
||||
GITHUB: richguan <guan.rich@gmail.com>
|
||||
GITHUB: rick-golden-healthagen <rick.golden@healthagen.com>
|
||||
GITHUB: rissem <rissem@gmail.com>
|
||||
GITHUB: RobertLowe <robert@iblargz.com>
|
||||
GITHUB: rosh93 <rosh93@gmail.com>
|
||||
GITHUB: ryw <ry@rywalker.com>
|
||||
GITHUB: rzymek <rzymek@gmail.com>
|
||||
GITHUB: sdarnell <stephen@darnell.plus.com>
|
||||
@@ -64,6 +72,7 @@ GITHUB: subhog <hubert@orlikarnia.com>
|
||||
GITHUB: tbjers <torgny@xorcode.com>
|
||||
GITHUB: thatneat <thatneat@users.noreply.github.com>
|
||||
GITHUB: timhaines <tmhaines@gmail.com>
|
||||
GITHUB: timoabend <timo.abend@liquidmotions.de>
|
||||
GITHUB: tmeasday <tom@thesnail.org>
|
||||
GITHUB: twhy <tom.wanghaiyi@gmail.com>
|
||||
GITHUB: waitingkuo <waitingkuo0527@gmail.com>
|
||||
@@ -73,8 +82,8 @@ GITHUB: zol <zol@percolatestudio.com>
|
||||
|
||||
METEOR: arbesfeld <arbesfeld@gmail.com>
|
||||
METEOR: avital <avital@thewe.net>
|
||||
METEOR: ben <ben@meteor.com>
|
||||
METEOR: ben <bn@cs.stanford.edu>
|
||||
METEOR: benjamn <ben@meteor.com>
|
||||
METEOR: benjamn <bn@cs.stanford.edu>
|
||||
METEOR: debergalis <matt@meteor.com>
|
||||
METEOR: dgreensp <dgreenspan@alum.mit.edu>
|
||||
METEOR: ekatek <ekate@meteor.com>
|
||||
@@ -83,9 +92,11 @@ METEOR: estark37 <estark37@gmail.com>
|
||||
METEOR: glasser <glasser@meteor.com>
|
||||
METEOR: glasser <glasser@davidglasser.net>
|
||||
METEOR: gschmidt <geoff@geoffschmidt.com>
|
||||
METEOR: justinsb <justin@fathomdb.com>
|
||||
METEOR: karayu <lele.yu@gmail.com>
|
||||
METEOR: mariapacana <maria.pacana@gmail.com>
|
||||
METEOR: n1mmy <nim@meteor.com>
|
||||
METEOR: sixolet <naomi@meteor.com>
|
||||
METEOR: Slava <slava@meteor.com>
|
||||
METEOR: Slava <imslavko@gmail.com>
|
||||
METEOR: stubailo <sashko@mit.edu>
|
||||
|
||||
120
History.md
120
History.md
@@ -1,26 +1,126 @@
|
||||
## v.NEXT
|
||||
|
||||
## v0.9.4
|
||||
|
||||
### New Features
|
||||
|
||||
* The new `meteor debug` command and `--debug-port` command line option
|
||||
to `meteor run` allow you to easily use node-inspector to debug your
|
||||
server-side code. Add a `debugger` statement to your code to create a
|
||||
breakpoint.
|
||||
|
||||
* Add new a `meteor run --test` command that runs
|
||||
[Velocity](https://github.com/meteor-velocity/velocity) tests in your
|
||||
app .
|
||||
|
||||
* Add new callbacks `Accounts.onResetPasswordLink`,
|
||||
`Accounts.onEnrollmentLink`, and `Accounts.onEmailVerificationLink`
|
||||
that make it easier to build custom user interfaces on top of the
|
||||
accounts system. These callbacks should be registered before
|
||||
`Meteor.startup` fires, and will be called if the URL matches a link
|
||||
in an email sent by `Accounts.resetPassword`, etc. See
|
||||
https://docs.meteor.com/#Accounts-onResetPasswordLink.
|
||||
|
||||
* A new configuration file for mobile apps,
|
||||
`<APP>/mobile-config.js`. This allows you to set app metadata, icons,
|
||||
splash screens, preferences, and PhoneGap/Cordova plugin settings
|
||||
without needing a `cordova_build_override` directory. See
|
||||
https://docs.meteor.com/#mobileconfigjs.
|
||||
|
||||
|
||||
### API Changes
|
||||
|
||||
* Rename `{{> UI.dynamic}}` to `{{> Template.dynamic}}`, and likewise
|
||||
with `UI.contentBlock` and `UI.elseBlock`.
|
||||
with `UI.contentBlock` and `UI.elseBlock`. The UI namespace is no
|
||||
longer used anywhere except for backwards compatibility.
|
||||
|
||||
* Deprecate the `Template.someTemplate.myHelper = ...` syntax in favor
|
||||
of `Template.someTemplate.helpers(...)`. Using the older syntax still
|
||||
works, but prints a deprecation warning to the console.
|
||||
|
||||
* `Package.registerBuildPlugin` its associated functions have been added
|
||||
to the public API, cleaned up, and documented. The new function is
|
||||
identical to the earlier _transitional_registerBuildPlugin except for
|
||||
minor backwards- compatible API changes. See
|
||||
https://docs.meteor.com/#Package-registerBuildPlugin
|
||||
|
||||
* Rename the `showdown` package to `markdown`.
|
||||
|
||||
* Deprecate the `amplify`, `backbone`, `bootstrap`, and `d3` integration
|
||||
packages in favor of community alternatives. These packages will no
|
||||
longer be maintained by MDG.
|
||||
|
||||
* Rename the `showdown` package to `markdown`.
|
||||
|
||||
* Deprecate the `Template.someTemplate.myHelper = ...` syntax in favor
|
||||
of `Template.someTemplate.helpers(...)`. Using the older syntax still
|
||||
works, but it prints a deprecation warning to the console.
|
||||
### Tool Changes
|
||||
|
||||
* Improved output from `meteor build` to make it easier to publish
|
||||
mobile apps to the App Store and Play Store. See the wiki pages for
|
||||
instructions on how to publish your
|
||||
[iOS](https://github.com/meteor/meteor/wiki/How-to-submit-your-iOS-app-to-App-Store)
|
||||
and
|
||||
[Android](https://github.com/meteor/meteor/wiki/How-to-submit-your-Android-app-to-Play-Store)
|
||||
apps.
|
||||
|
||||
* Packages can now be marked as debug-mode only by adding `debugOnly:
|
||||
true` to `Package.describe`. Debug-only packages are not included in
|
||||
the app when it is bundled for production (`meteor build` or `meteor
|
||||
run --production`). This allows package authors to build packages
|
||||
specifically for testing and debugging without increasing the size of
|
||||
the resulting app bundle or causing apps to ship with debug
|
||||
functionality built in.
|
||||
|
||||
* Rework the process for installing mobile development SDKs. There is
|
||||
now a `meteor install-sdk` command that automatically install what
|
||||
software it can and points to documentation for the parts that
|
||||
require manual installation.
|
||||
|
||||
* The `.meteor/cordova-platforms` file has been renamed to
|
||||
`.meteor/platforms` and now includes the default `server` and
|
||||
`browser` platforms. The default platforms can't currently be removed
|
||||
from a project, though this will be possible in the future. The old
|
||||
file will be automatically migrated to the new one when the app is run
|
||||
with Meteor 0.9.4 or above.
|
||||
|
||||
* The `unipackage.json` file inside downloaded packages has been renamed
|
||||
to `isopack.json` and has an improved forwards-compatible format. To
|
||||
maintain backwards compatibility with previous releases, packages will
|
||||
be built with both files.
|
||||
|
||||
* The local package metadata cache now uses SQLite, which is much faster
|
||||
than the previous implementation. This improves `meteor` command line
|
||||
tool startup time.
|
||||
|
||||
* The constraint solver used by the client to find compatible versions
|
||||
of packages is now much faster.
|
||||
|
||||
* The `--port` option to `meteor run` now requires a numeric port
|
||||
(e.g. `meteor run --port example.com` is no longer valid).
|
||||
|
||||
* The `--mobile-port` option `meteor run` has been reworked. The option
|
||||
is now `--mobile-server` in `meteor run` and `--server` in `meteor
|
||||
build`. `--server` is required for `meteor build` in apps with mobile
|
||||
platforms installed. `--mobile-server` defaults to an automatically
|
||||
detected IP address on port 3000, and `--server` requires a hostname
|
||||
but defaults to port 80 if a port is not specified.
|
||||
|
||||
* Operations that take longer than a few seconds (e.g. downloading
|
||||
packages, installing the Android SDK, etc) now show a progress bar.
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix behavior of ROOT_URL with path ending in `/`.
|
||||
|
||||
* Fix source maps when using a ROOT_URL with a path. #2627
|
||||
|
||||
* --port now requires a port (e.g. `meteor run --port example.com` is
|
||||
not valid). XXX --mobile-port deprecated in favor of --mobile-server
|
||||
option for 'meteor run' and '--server' for 'meteor build'. --server
|
||||
is required for meteor build. describe defaults for --mobile-server.
|
||||
* Change the mechanism that the Meteor tool uses to clean up app server
|
||||
processes. The new mechanism is more resilient to slow app bundles and
|
||||
other CPU-intensive tasks. #2536, #2588.
|
||||
|
||||
|
||||
Patches by Github users cryptoquick, Gaelan, jperl, meonkeys, mitar,
|
||||
mquandalle, prapicault, pscanf, richguan, rick-golden-healthagen,
|
||||
rissem, rosh93, rzymek, and timoabend
|
||||
|
||||
|
||||
## v0.9.3.1
|
||||
@@ -29,8 +129,6 @@
|
||||
|
||||
* Allow more than one dash in package versions. #2715
|
||||
|
||||
* Fix `meteor update` on an app built from a checkout version
|
||||
of Meteor.
|
||||
|
||||
## v0.9.3
|
||||
|
||||
|
||||
123
LICENSE.txt
123
LICENSE.txt
@@ -884,6 +884,7 @@ Modifications made by the following entities are licensed as above:
|
||||
accepts: https://github.com/jshttp/accepts
|
||||
merge-descriptors: https://github.com/component/merge-descriptors
|
||||
type-is: https://github.com/jshttp/type-is
|
||||
mime-types: https://github.com/jshttp/mime-types
|
||||
----------
|
||||
|
||||
Copyright (c) 2013 Jonathan Ong me@jongleberry.com
|
||||
@@ -947,6 +948,35 @@ utils-merge: https://github.com/jaredhanson/utils-merge
|
||||
Copyright (c) 2013 Jared Hanson
|
||||
|
||||
|
||||
----------
|
||||
bl: https://github.com/rvagg/bl
|
||||
----------
|
||||
|
||||
Copyright (c) 2014 bl contributors
|
||||
bl contributors listed at https://github.com/rvagg/bl#contributors
|
||||
|
||||
|
||||
----------
|
||||
lodash-node: https://github.com/lodash/lodash-node
|
||||
----------
|
||||
|
||||
Copyright 2012-2014 The Dojo Foundation <http://dojofoundation.org/>
|
||||
Based on Underscore.js 1.6.0, copyright 2009-2014 Jeremy Ashkenas,
|
||||
DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
|
||||
|
||||
|
||||
----------
|
||||
netroute: https://github.com/indutny/node-netroute
|
||||
----------
|
||||
|
||||
Copyright Fedor Indutny, 2012.
|
||||
|
||||
|
||||
----------
|
||||
stringstream: https://github.com/mhart/StringStream
|
||||
----------
|
||||
|
||||
Copyright 2012 Michael Hart (michael.hart.au@gmail.com)
|
||||
|
||||
|
||||
==============
|
||||
@@ -1229,6 +1259,99 @@ Copyright (C) 2013 David Nolen and contributors
|
||||
BSD Licenses
|
||||
============
|
||||
|
||||
----------
|
||||
tar-pack: https://github.com/ForbesLindesay/tar-pack
|
||||
----------
|
||||
|
||||
Copyright (c) 2014, Forbes Lindesay
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
----------
|
||||
sqlite3: https://github.com/mapbox/node-sqlite3
|
||||
----------
|
||||
|
||||
Copyright (c) MapBox
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
- Neither the name "MapBox" nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
----------
|
||||
node-pre-gyp: https://github.com/mapbox/node-pre-gyp
|
||||
----------
|
||||
|
||||
Copyright (c), Mapbox
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of node-pre-gyp nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
----------
|
||||
uglify-js: https://github.com/mishoo/UglifyJS2
|
||||
----------
|
||||
|
||||
@@ -4,3 +4,4 @@
|
||||
|
||||
notices-for-0.9.0
|
||||
notices-for-0.9.1
|
||||
0.9.4-platform-file
|
||||
|
||||
@@ -7,9 +7,11 @@ standard-app-packages
|
||||
jquery
|
||||
underscore
|
||||
showdown
|
||||
code-prettify
|
||||
jquery-waypoints
|
||||
less
|
||||
spiderable
|
||||
appcache
|
||||
reload-safetybelt
|
||||
simple:markdown-templating
|
||||
simple:highlight.js
|
||||
|
||||
|
||||
2
docs/.meteor/platforms
Normal file
2
docs/.meteor/platforms
Normal file
@@ -0,0 +1,2 @@
|
||||
server
|
||||
browser
|
||||
@@ -1 +1 @@
|
||||
METEOR@0.9.3.1
|
||||
METEOR@0.9.4
|
||||
|
||||
@@ -1,58 +1,60 @@
|
||||
appcache@1.0.1
|
||||
application-configuration@1.0.2
|
||||
autoupdate@1.1.1
|
||||
base64@1.0.0
|
||||
binary-heap@1.0.0
|
||||
blaze-tools@1.0.0
|
||||
blaze@2.0.1
|
||||
boilerplate-generator@1.0.0
|
||||
callback-hook@1.0.0
|
||||
check@1.0.1
|
||||
code-prettify@1.0.0
|
||||
coffeescript@1.0.3
|
||||
ctl-helper@1.0.3
|
||||
ctl@1.0.1
|
||||
ddp@1.0.9
|
||||
deps@1.0.4
|
||||
ejson@1.0.3
|
||||
fastclick@1.0.0
|
||||
follower-livedata@1.0.1
|
||||
geojson-utils@1.0.0
|
||||
html-tools@1.0.1
|
||||
htmljs@1.0.1
|
||||
http@1.0.6
|
||||
id-map@1.0.0
|
||||
jquery-waypoints@1.0.0
|
||||
jquery@1.0.0
|
||||
json@1.0.0
|
||||
less@1.0.9
|
||||
livedata@1.0.10
|
||||
logging@1.0.3
|
||||
meteor-platform@1.1.1
|
||||
meteor@1.1.1
|
||||
minifiers@1.1.0
|
||||
minimongo@1.0.3
|
||||
mobile-status-bar@1.0.0
|
||||
mongo@1.0.6
|
||||
observe-sequence@1.0.2
|
||||
ordered-dict@1.0.0
|
||||
random@1.0.0
|
||||
reactive-dict@1.0.3
|
||||
reactive-var@1.0.2
|
||||
reload-safetybelt@1.0.0
|
||||
reload@1.1.0
|
||||
retry@1.0.0
|
||||
routepolicy@1.0.1
|
||||
session@1.0.2
|
||||
showdown@1.0.1
|
||||
spacebars-compiler@1.0.2
|
||||
spacebars@1.0.2
|
||||
spiderable@1.0.3
|
||||
standard-app-packages@1.0.2
|
||||
templating@1.0.7
|
||||
tracker@1.0.2
|
||||
ui@1.0.3
|
||||
underscore@1.0.0
|
||||
url@1.0.0
|
||||
webapp-hashing@1.0.0
|
||||
webapp@1.1.2
|
||||
appcache@1.0.2
|
||||
application-configuration@1.0.3
|
||||
autoupdate@1.1.2
|
||||
base64@1.0.1
|
||||
binary-heap@1.0.1
|
||||
blaze-tools@1.0.1
|
||||
blaze@2.0.2
|
||||
boilerplate-generator@1.0.1
|
||||
callback-hook@1.0.1
|
||||
check@1.0.2
|
||||
coffeescript@1.0.4
|
||||
ctl-helper@1.0.4
|
||||
ctl@1.0.2
|
||||
ddp@1.0.10
|
||||
deps@1.0.5
|
||||
ejson@1.0.4
|
||||
fastclick@1.0.1
|
||||
follower-livedata@1.0.2
|
||||
geojson-utils@1.0.1
|
||||
html-tools@1.0.2
|
||||
htmljs@1.0.2
|
||||
http@1.0.7
|
||||
id-map@1.0.1
|
||||
jquery-waypoints@1.0.1
|
||||
jquery@1.0.1
|
||||
json@1.0.1
|
||||
less@1.0.10
|
||||
livedata@1.0.11
|
||||
logging@1.0.4
|
||||
markdown@1.0.2
|
||||
meteor-platform@1.1.2
|
||||
meteor@1.1.2
|
||||
minifiers@1.1.1
|
||||
minimongo@1.0.4
|
||||
mobile-status-bar@1.0.1
|
||||
mongo@1.0.7
|
||||
observe-sequence@1.0.3
|
||||
ordered-dict@1.0.1
|
||||
random@1.0.1
|
||||
reactive-dict@1.0.4
|
||||
reactive-var@1.0.3
|
||||
reload-safetybelt@1.0.1
|
||||
reload@1.1.1
|
||||
retry@1.0.1
|
||||
routepolicy@1.0.2
|
||||
session@1.0.3
|
||||
showdown@1.0.2
|
||||
simple:highlight.js@1.0.1
|
||||
simple:markdown-templating@1.2.5
|
||||
spacebars-compiler@1.0.3
|
||||
spacebars@1.0.3
|
||||
spiderable@1.0.4
|
||||
standard-app-packages@1.0.3
|
||||
templating@1.0.8
|
||||
tracker@1.0.3
|
||||
ui@1.0.4
|
||||
underscore@1.0.1
|
||||
url@1.0.1
|
||||
webapp-hashing@1.0.1
|
||||
webapp@1.1.3
|
||||
|
||||
3669
docs/client/api.html
3669
docs/client/api.html
File diff suppressed because it is too large
Load Diff
31
docs/client/api.md
Normal file
31
docs/client/api.md
Normal file
@@ -0,0 +1,31 @@
|
||||
{{#template name="api"}}
|
||||
|
||||
<h1 id="api">The Meteor API</h1>
|
||||
|
||||
Your JavaScript code can run in two environments: the *client* (browser), and
|
||||
the *server* (a [Node.js](http://nodejs.org/) container on a server). For each
|
||||
function in this API reference, we'll indicate if the function is available just
|
||||
on the client, just on the server, or *Anywhere*.
|
||||
|
||||
{{> api_core}}
|
||||
{{> api_pubsub}}
|
||||
{{> api_methods}}
|
||||
{{> api_check}}
|
||||
{{> api_connections}}
|
||||
{{> api_collections}}
|
||||
{{> api_session}}
|
||||
{{> api_accounts}}
|
||||
{{> api_passwords}}
|
||||
{{> api_templates}}
|
||||
{{> api_blaze}}
|
||||
{{> api_timers}}
|
||||
{{> api_tracker}}
|
||||
{{> api_reactive_var}}
|
||||
{{> api_ejson}}
|
||||
{{> api_http}}
|
||||
{{> api_email}}
|
||||
{{> api_assets}}
|
||||
{{> api_packagejs}}
|
||||
{{> api_mobile_config}}
|
||||
|
||||
{{/template}}
|
||||
384
docs/client/api/accounts.md
Normal file
384
docs/client/api/accounts.md
Normal file
@@ -0,0 +1,384 @@
|
||||
{{#template name="api_accounts"}}
|
||||
|
||||
<h2 id="accounts_api"><span>Accounts</span></h2>
|
||||
|
||||
The Meteor Accounts system builds on top of the `userId` support in
|
||||
[`publish`](#publish_userId) and [`methods`](#method_userId). The core
|
||||
packages add the concept of user documents stored in the database, and
|
||||
additional packages add [secure password
|
||||
authentication](#accounts_passwords), [integration with third party
|
||||
login services](#meteor_loginwithexternalservice), and a [pre-built user
|
||||
interface](#accountsui).
|
||||
|
||||
The basic Accounts system is in the `accounts-base` package, but
|
||||
applications typically include this automatically by adding one of the
|
||||
login provider packages: `accounts-password`, `accounts-facebook`,
|
||||
`accounts-github`, `accounts-google`, `accounts-meetup`,
|
||||
`accounts-twitter`, or `accounts-weibo`.
|
||||
|
||||
|
||||
{{> autoApiBox "Meteor.user"}}
|
||||
|
||||
Retrieves the user record for the current user from
|
||||
the [`Meteor.users`](#meteor_users) collection.
|
||||
|
||||
On the client, this will be the subset of the fields in the document that
|
||||
are published from the server (other fields won't be available on the
|
||||
client). By default the server publishes `username`, `emails`, and
|
||||
`profile`. See [`Meteor.users`](#meteor_users) for more on
|
||||
the fields used in user documents.
|
||||
|
||||
{{> autoApiBox "Meteor.userId"}}
|
||||
|
||||
{{> autoApiBox "Meteor.users"}}
|
||||
|
||||
This collection contains one document per registered user. Here's an example
|
||||
user document:
|
||||
|
||||
{
|
||||
_id: "bbca5d6a-2156-41c4-89da-0329e8c99a4f", // Meteor.userId()
|
||||
username: "cool_kid_13", // unique name
|
||||
emails: [
|
||||
// each email address can only belong to one user.
|
||||
{ address: "cool@example.com", verified: true },
|
||||
{ address: "another@different.com", verified: false }
|
||||
],
|
||||
createdAt: Wed Aug 21 2013 15:16:52 GMT-0700 (PDT),
|
||||
profile: {
|
||||
// The profile is writable by the user by default.
|
||||
name: "Joe Schmoe"
|
||||
},
|
||||
services: {
|
||||
facebook: {
|
||||
id: "709050", // facebook id
|
||||
accessToken: "AAACCgdX7G2...AbV9AZDZD"
|
||||
},
|
||||
resume: {
|
||||
loginTokens: [
|
||||
{ token: "97e8c205-c7e4-47c9-9bea-8e2ccc0694cd",
|
||||
when: 1349761684048 }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
A user document can contain any data you want to store about a user. Meteor
|
||||
treats the following fields specially:
|
||||
|
||||
- `username`: a unique String identifying the user.
|
||||
- `emails`: an Array of Objects with keys `address` and `verified`;
|
||||
an email address may belong to at most one user. `verified` is
|
||||
a Boolean which is true if the user has [verified the
|
||||
address](#accounts_verifyemail) with a token sent over email.
|
||||
- `createdAt`: the Date at which the user document was created.
|
||||
- `profile`: an Object which (by default) the user can create
|
||||
and update with any data.
|
||||
- `services`: an Object containing data used by particular
|
||||
login services. For example, its `reset` field contains
|
||||
tokens used by [forgot password](#accounts_forgotpassword) links,
|
||||
and its `resume` field contains tokens used to keep you
|
||||
logged in between sessions.
|
||||
|
||||
Like all [Mongo.Collection](#collections)s, you can access all
|
||||
documents on the server, but only those specifically published by the server are
|
||||
available on the client.
|
||||
|
||||
By default, the current user's `username`, `emails` and `profile` are
|
||||
published to the client. You can publish additional fields for the
|
||||
current user with:
|
||||
|
||||
// server
|
||||
Meteor.publish("userData", function () {
|
||||
if (this.userId) {
|
||||
return Meteor.users.find({_id: this.userId},
|
||||
{fields: {'other': 1, 'things': 1}});
|
||||
} else {
|
||||
this.ready();
|
||||
}
|
||||
});
|
||||
|
||||
// client
|
||||
Meteor.subscribe("userData");
|
||||
|
||||
If the autopublish package is installed, information about all users
|
||||
on the system is published to all clients. This includes `username`,
|
||||
`profile`, and any fields in `services` that are meant to be public
|
||||
(eg `services.facebook.id`,
|
||||
`services.twitter.screenName`). Additionally, when using autopublish
|
||||
more information is published for the currently logged in user,
|
||||
including access tokens. This allows making API calls directly from
|
||||
the client for services that allow this.
|
||||
|
||||
Users are by default allowed to specify their own `profile` field with
|
||||
[`Accounts.createUser`](#accounts_createuser) and modify it with
|
||||
`Meteor.users.update`. To allow users to edit additional fields, use
|
||||
[`Meteor.users.allow`](#allow). To forbid users from making any modifications to
|
||||
their user document:
|
||||
|
||||
Meteor.users.deny({update: function () { return true; }});
|
||||
|
||||
|
||||
{{> autoApiBox "Meteor.loggingIn"}}
|
||||
|
||||
For example, [the `accounts-ui` package](#accountsui) uses this to display an
|
||||
animation while the login request is being processed.
|
||||
|
||||
{{> autoApiBox "Meteor.logout"}}
|
||||
|
||||
{{> autoApiBox "Meteor.logoutOtherClients"}}
|
||||
|
||||
For example, when called in a user's browser, connections in that browser
|
||||
remain logged in, but any other browsers or DDP clients logged in as that user
|
||||
will be logged out.
|
||||
|
||||
{{> autoApiBox "Meteor.loginWithPassword"}}
|
||||
|
||||
This function is provided by the `accounts-password` package. See the
|
||||
[Passwords](#accounts_passwords) section below.
|
||||
|
||||
|
||||
{{> autoApiBox "Meteor.loginWith<ExternalService>"}}
|
||||
|
||||
Available functions are:
|
||||
|
||||
* `Meteor.loginWithMeteorDeveloperAccount`
|
||||
* `Meteor.loginWithFacebook`
|
||||
* `Meteor.loginWithGithub`
|
||||
* `Meteor.loginWithGoogle`
|
||||
* `Meteor.loginWithMeetup`
|
||||
* `Meteor.loginWithTwitter`
|
||||
* `Meteor.loginWithWeibo`
|
||||
|
||||
These functions initiate the login process with an external
|
||||
service (eg: Facebook, Google, etc), using OAuth. When called they open a new pop-up
|
||||
window that loads the provider's login page. Once the user has logged in
|
||||
with the provider, the pop-up window is closed and the Meteor client
|
||||
logs in to the Meteor server with the information provided by the external
|
||||
service.
|
||||
|
||||
<a id="requestpermissions" name="requestpermissions"></a>
|
||||
|
||||
In addition to identifying the user to your application, some services
|
||||
have APIs that allow you to take action on behalf of the user. To
|
||||
request specific permissions from the user, pass the
|
||||
`requestPermissions` option the login function. This will cause the user
|
||||
to be presented with an additional page in the pop-up dialog to permit
|
||||
access to their data. The user's `accessToken` — with permissions
|
||||
to access the service's API — is stored in the `services` field of
|
||||
the user document. The supported values for `requestPermissions` differ
|
||||
for each login service and are documented on their respective developer
|
||||
sites:
|
||||
|
||||
- Facebook: <http://developers.facebook.com/docs/authentication/permissions/>
|
||||
- GitHub: <http://developer.github.com/v3/oauth/#scopes>
|
||||
- Google: <https://developers.google.com/accounts/docs/OAuth2Login#scopeparameter>
|
||||
- Meetup: <http://www.meetup.com/meetup_api/auth/#oauth2-scopes>
|
||||
- Twitter, Weibo, Meteor developer accounts: `requestPermissions` currently not supported
|
||||
|
||||
External login services typically require registering and configuring
|
||||
your application before use. The easiest way to do this is with the
|
||||
[`accounts-ui` package](#accountsui) which presents a step-by-step guide
|
||||
to configuring each service. However, the data can be also be entered
|
||||
manually in the `ServiceConfiguration.configurations` collection, which
|
||||
is exported by the `service-configuration` package. For example, after
|
||||
running `meteor add service-configuration` in your app:
|
||||
|
||||
// first, remove configuration entry in case service is already configured
|
||||
ServiceConfiguration.configurations.remove({
|
||||
service: "weibo"
|
||||
});
|
||||
ServiceConfiguration.configurations.insert({
|
||||
service: "weibo",
|
||||
clientId: "1292962797",
|
||||
loginStyle: "popup",
|
||||
secret: "75a730b58f5691de5522789070c319bc"
|
||||
});
|
||||
|
||||
|
||||
Each external service has its own login provider package and login function. For
|
||||
example, to support GitHub login, run `$ meteor add accounts-github` and use the
|
||||
`Meteor.loginWithGithub` function:
|
||||
|
||||
Meteor.loginWithGithub({
|
||||
requestPermissions: ['user', 'public_repo']
|
||||
}, function (err) {
|
||||
if (err)
|
||||
Session.set('errorMessage', err.reason || 'Unknown error');
|
||||
});
|
||||
|
||||
Login service configuration is sent from the server to the client over DDP when
|
||||
your app starts up; you may not call the login function until the configuration
|
||||
is loaded. The function `Accounts.loginServicesConfigured()` is a reactive data
|
||||
source that will return true once the login service is configured; you should
|
||||
not make login buttons visible or active until it is true.
|
||||
|
||||
{{> autoApiBox "currentUser"}}
|
||||
|
||||
{{> autoApiBox "loggingIn"}}
|
||||
|
||||
{{> autoApiBox "Accounts.config"}}
|
||||
{{> autoApiBox "Accounts.ui.config"}}
|
||||
|
||||
Example:
|
||||
|
||||
Accounts.ui.config({
|
||||
requestPermissions: {
|
||||
facebook: ['user_likes'],
|
||||
github: ['user', 'repo']
|
||||
},
|
||||
requestOfflineToken: {
|
||||
google: true
|
||||
},
|
||||
passwordSignupFields: 'USERNAME_AND_OPTIONAL_EMAIL'
|
||||
});
|
||||
|
||||
{{> autoApiBox "Accounts.validateNewUser"}}
|
||||
|
||||
This can be called multiple times. If any of the functions return `false` or
|
||||
throw an error, the new user creation is aborted. To set a specific error
|
||||
message (which will be displayed by [`accounts-ui`](#accountsui)), throw a new
|
||||
[`Meteor.Error`](#meteor_error).
|
||||
|
||||
Example:
|
||||
|
||||
// Validate username, sending a specific error message on failure.
|
||||
Accounts.validateNewUser(function (user) {
|
||||
if (user.username && user.username.length >= 3)
|
||||
return true;
|
||||
throw new Meteor.Error(403, "Username must have at least 3 characters");
|
||||
});
|
||||
// Validate username, without a specific error message.
|
||||
Accounts.validateNewUser(function (user) {
|
||||
return user.username !== "root";
|
||||
});
|
||||
|
||||
If the user is being created as part of a login attempt from a client (eg,
|
||||
calling [`Accounts.createUser`](#accounts_createuser) from the client, or
|
||||
[logging in for the first time with an external
|
||||
service](#meteor_loginwithexternalservice)), these callbacks are called *before*
|
||||
the [`Accounts.validateLoginAttempt`](#accounts_validateloginattempt)
|
||||
callbacks. If these callbacks succeed but those fail, the user will still be
|
||||
created but the connection will not be logged in as that user.
|
||||
|
||||
{{> autoApiBox "Accounts.onCreateUser"}}
|
||||
|
||||
Use this when you need to do more than simply accept or reject new user
|
||||
creation. With this function you can programatically control the
|
||||
contents of new user documents.
|
||||
|
||||
The function you pass will be called with two arguments: `options` and
|
||||
`user`. The `options` argument comes
|
||||
from [`Accounts.createUser`](#accounts_createuser) for
|
||||
password-based users or from an external service login flow. `options` may come
|
||||
from an untrusted client so make sure to validate any values you read from
|
||||
it. The `user` argument is created on the server and contains a
|
||||
proposed user object with all the automatically generated fields
|
||||
required for the user to log in.
|
||||
|
||||
The function should return the user document (either the one passed in or a
|
||||
newly-created object) with whatever modifications are desired. The returned
|
||||
document is inserted directly into the [`Meteor.users`](#meteor_users) collection.
|
||||
|
||||
The default create user function simply copies `options.profile` into
|
||||
the new user document. Calling `onCreateUser` overrides the default
|
||||
hook. This can only be called once.
|
||||
|
||||
Example:
|
||||
|
||||
<!-- XXX replace d6 with _.random once we have underscore 1.4.2 -->
|
||||
|
||||
// Support for playing D&D: Roll 3d6 for dexterity
|
||||
Accounts.onCreateUser(function(options, user) {
|
||||
var d6 = function () { return Math.floor(Random.fraction() * 6) + 1; };
|
||||
user.dexterity = d6() + d6() + d6();
|
||||
// We still want the default hook's 'profile' behavior.
|
||||
if (options.profile)
|
||||
user.profile = options.profile;
|
||||
return user;
|
||||
});
|
||||
|
||||
|
||||
{{> autoApiBox "Accounts.validateLoginAttempt"}}
|
||||
|
||||
Call `validateLoginAttempt` with a callback to be called on login
|
||||
attempts. It returns an object with a single method, `stop`. Calling
|
||||
`stop()` unregisters the callback.
|
||||
|
||||
When a login attempt is made, the registered validate login callbacks
|
||||
are called with a single argument, the attempt info object:
|
||||
|
||||
<dl class="objdesc">
|
||||
{{#dtdd name="type" type="String"}}
|
||||
The service name, such as "password" or "twitter".
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="allowed" type="Boolean"}}
|
||||
Whether this login is allowed and will be successful (if not aborted
|
||||
by any of the validateLoginAttempt callbacks). False if the login
|
||||
will not succeed (for example, an invalid password or the login was
|
||||
aborted by a previous validateLoginAttempt callback).
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="error" type="Exception"}}
|
||||
When `allowed` is false, the exception describing why the login
|
||||
failed. It will be a `Meteor.Error` for failures reported to the
|
||||
user (such as invalid password), and can be a another kind of
|
||||
exception for internal errors.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="user" type="Object"}}
|
||||
When it is known which user was attempting to login, the Meteor user
|
||||
object. This will always be present for successful logins.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="connection" type="Object"}}
|
||||
The `connection` object the request came in on. See
|
||||
[`Meteor.onConnection`](#meteor_onconnection) for details.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="methodName" type="String"}}
|
||||
The name of the Meteor method being used to login.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="methodArguments" type="Array"}}
|
||||
An array of the arguments passed to the login method.
|
||||
{{/dtdd}}
|
||||
</dl>
|
||||
|
||||
A validate login callback must return a truthy value for the login to
|
||||
proceed. If the callback returns a falsy value or throws an
|
||||
exception, the login is aborted. Throwing a `Meteor.Error` will
|
||||
report the error reason to the user.
|
||||
|
||||
All registered validate login callbacks are called, even if one of the callbacks
|
||||
aborts the login. The later callbacks will see the `allowed` field set to
|
||||
`false` since the login will now not be successful. This allows later callbacks
|
||||
to override an error from a previous callback; for example, you could override
|
||||
the "Incorrect password" error with a different message.
|
||||
|
||||
Validate login callbacks that aren't explicitly trying to override a previous
|
||||
error generally have no need to run if the attempt has already been determined
|
||||
to fail, and should start with
|
||||
|
||||
if (!attempt.allowed)
|
||||
return false;
|
||||
|
||||
|
||||
{{> autoApiBox "Accounts.onLogin"}}
|
||||
|
||||
See description of [Accounts.onLoginFailure](#accounts_onloginfailure)
|
||||
for details.
|
||||
|
||||
{{> autoApiBox "Accounts.onLoginFailure"}}
|
||||
|
||||
Either the `onLogin` or the `onLoginFailure` callbacks will be called
|
||||
for each login attempt. The `onLogin` callbacks are called after the
|
||||
user has been successfully logged in. The `onLoginFailure` callbacks are
|
||||
called after a login attempt is denied.
|
||||
|
||||
These functions return an object with a single method, `stop`. Calling
|
||||
`stop()` unregisters the callback.
|
||||
|
||||
The callbacks are called with a single argument, the same attempt info
|
||||
object as [`validateLoginAttempt`](#accounts_validateloginattempt).
|
||||
{{/template}}
|
||||
20
docs/client/api/assets.md
Normal file
20
docs/client/api/assets.md
Normal file
@@ -0,0 +1,20 @@
|
||||
{{#template name="api_assets"}}
|
||||
|
||||
<h2 id="assets"><span>Assets</span></h2>
|
||||
|
||||
`Assets` allows server code in a Meteor application to access static server
|
||||
assets, which are located in the `private` subdirectory of an application's
|
||||
tree. Assets are not processed as source files and are copied directly
|
||||
into your application's bundle.
|
||||
|
||||
{{> autoApiBox "Assets.getText"}}
|
||||
{{> autoApiBox "Assets.getBinary"}}
|
||||
|
||||
Static server assets are included by placing them in the application's `private`
|
||||
subdirectory. For example, if an application's `private` subdirectory includes a
|
||||
directory called `nested` with a file called `data.txt` inside it, then server
|
||||
code can read `data.txt` by running:
|
||||
|
||||
var data = Assets.getText('nested/data.txt');
|
||||
|
||||
{{/template}}
|
||||
307
docs/client/api/blaze.md
Normal file
307
docs/client/api/blaze.md
Normal file
@@ -0,0 +1,307 @@
|
||||
{{#template name="api_blaze"}}
|
||||
|
||||
<h2 id="blaze"><span>Blaze</span></h2>
|
||||
|
||||
Blaze is the package that makes reactive templates possible.
|
||||
You can use the Blaze API directly in order to render templates programmatically
|
||||
and manipulate "Views," the building blocks of reactive templates.
|
||||
|
||||
{{> autoApiBox "Blaze.render"}}
|
||||
|
||||
When you render a template, the
|
||||
template's [`created`](#template_created) callback is invoked
|
||||
immediately, before evaluating the content of the template.
|
||||
The [`rendered`](#template_rendered) callback is
|
||||
invoked after the View is rendered and inserted into the DOM.
|
||||
|
||||
The rendered template
|
||||
will update reactively in response to data changes until the View is
|
||||
removed using [`Blaze.remove`](#blaze_remove) or the View's
|
||||
parent element is removed by Meteor or jQuery.
|
||||
|
||||
{{#warning}}
|
||||
If the View is removed by some other mechanism
|
||||
besides Meteor or jQuery (which Meteor integrates with by default),
|
||||
the View may continue to update indefinitely. Most users will not need to
|
||||
manually render templates and insert them into the DOM, but if you do,
|
||||
be mindful to always call [`Blaze.remove`](#blaze_remove) when the View is
|
||||
no longer needed.
|
||||
{{/warning}}
|
||||
|
||||
{{> autoApiBox "Blaze.renderWithData"}}
|
||||
|
||||
`Blaze.renderWithData(Template.myTemplate, data)` is essentially the same as
|
||||
`Blaze.render(Blaze.With(data, function () { return Template.myTemplate; }))`.
|
||||
|
||||
{{> autoApiBox "Blaze.remove"}}
|
||||
|
||||
Use `Blaze.remove` to remove a template or View previously inserted with
|
||||
`Blaze.render`, in such a way that any behaviors attached to the DOM by
|
||||
Meteor are cleaned up. The rendered template or View is now considered
|
||||
["destroyed"](#template_destroyed), along with all nested templates and
|
||||
Views. In addition, any data assigned via
|
||||
jQuery to the DOM nodes is removed, as if the nodes were passed to
|
||||
jQuery's `$(...).remove()`.
|
||||
|
||||
As mentioned in [`Blaze.render`](#blaze_render), it is important to "remove"
|
||||
all content rendered via `Blaze.render` using `Blaze.remove`, unless the
|
||||
parent node of `renderedView` is removed by a Meteor reactive
|
||||
update or with jQuery.
|
||||
|
||||
`Blaze.remove` can be used even if the DOM nodes in question have already
|
||||
been removed from the document, to tell Blaze to stop tracking and
|
||||
updating these nodes.
|
||||
|
||||
{{> autoApiBox "Blaze.getData"}}
|
||||
|
||||
{{> autoApiBox "Blaze.toHTML"}}
|
||||
|
||||
Rendering a template to HTML loses all fine-grained reactivity. The
|
||||
normal way to render a template is to either include it from another
|
||||
template (`{{dstache}}> myTemplate}}`) or render and insert it
|
||||
programmatically using `Blaze.render`. Only occasionally
|
||||
is generating HTML useful.
|
||||
|
||||
Because `Blaze.toHTML` returns a string, it is not able to update the DOM
|
||||
in response to reactive data changes. Instead, any reactive data
|
||||
changes will invalidate the current Computation if there is one
|
||||
(for example, an autorun that is the caller of `Blaze.toHTML`).
|
||||
|
||||
{{> autoApiBox "Blaze.toHTMLWithData"}}
|
||||
|
||||
{{> autoApiBox "Blaze.View"}}
|
||||
|
||||
Behind every template or part of a template — a template tag, say, like `{{dstache}}foo}}` or `{{dstache}}#if}}` — is
|
||||
a View object, which is a reactively updating region of DOM.
|
||||
|
||||
Most applications do not need to be aware of these Views, but they offer a
|
||||
way to understand and customize Meteor's rendering behavior for more
|
||||
advanced applications and packages.
|
||||
|
||||
You can obtain a View object by calling [`Blaze.render`](#blaze_render) on a
|
||||
template, or by accessing [`template.view`](#template_view) on a template
|
||||
instance.
|
||||
|
||||
At the heart of a View is an [autorun](#tracker_autorun) that calls the View's
|
||||
`renderFunction`, uses the result to create DOM nodes, and replaces the
|
||||
contents of the View with these new DOM nodes. A View's content may consist
|
||||
of any number of consecutive DOM nodes (though if it is zero, a placeholder
|
||||
node such as a comment or an empty text node is automatically supplied). Any
|
||||
reactive dependency established by `renderFunction` causes a full recalculation
|
||||
of the View's contents when the dependency is invalidated. Templates, however,
|
||||
are compiled in such a way that they do not have top-level dependencies and so
|
||||
will only ever render once, while their parts may re-render many times.
|
||||
|
||||
When a `Blaze.View` is constructed by calling the constructor, no hooks
|
||||
are fired and no rendering is performed. In particular, the View is
|
||||
not yet considered to be "created." Only when the View is actually
|
||||
used, by a call to `Blaze.render` or `Blaze.toHTML` or by inclusion in
|
||||
another View, is it "created," right before it is rendered for the
|
||||
first time. When a View is created, its `.parentView` is set if
|
||||
appropriate, and then the `onViewCreated` hook is fired. The term
|
||||
"unrendered View" means a newly constructed View that has not been
|
||||
"created" or rendered.
|
||||
|
||||
The "current View" is kept in [`Blaze.currentView`](#blaze_currentview) and
|
||||
is set during View rendering, callbacks, autoruns, and template event
|
||||
handlers. It affects calls such as [`Template.currentData()`](#template_currentdata).
|
||||
|
||||
The following properties and methods are available on Blaze.View:
|
||||
|
||||
<dl class="objdesc">
|
||||
{{#dtdd name="name" type="String" id="view_name"}}
|
||||
The name of this type of View. View names may be used to identify
|
||||
particular kinds of Views in code, but more often they simply aid in
|
||||
debugging and comprehensibility of the View tree. Views generated
|
||||
by Meteor have names like "Template.foo" and "if".
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="parentView" type="View or null" id="view_parentview"}}
|
||||
The enclosing View that caused this View to be rendered, if any.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="isCreated" type="Boolean" id="view_iscreated"}}
|
||||
True if this View has been called on to be rendered by `Blaze.render`
|
||||
or `Blaze.toHTML` or another View. Once it becomes true, never
|
||||
becomes false again. A "created" View's `.parentView` has been
|
||||
set to its final value. `isCreated` is set to true before
|
||||
`onViewCreated` hooks are called.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="isRendered" type="Boolean" id="view_isrendered"}}
|
||||
True if this View has been rendered to DOM by `Blaze.render` or
|
||||
by the rendering of an enclosing View. Conversion to HTML by
|
||||
`Blaze.toHTML` doesn't count. Once true, never becomes false.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="isDestroyed" type="Boolean" id="view_isdestroyed"}}
|
||||
True if this View has been destroyed, such as by `Blaze.remove()` or
|
||||
by a reactive update that removes it. A destroyed View's autoruns
|
||||
have been stopped, and its DOM nodes have generally been cleaned
|
||||
of all Meteor reactivity and possibly dismantled.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="renderCount" type="Integer" id="view_rendercount"}}
|
||||
The number of times the View has been rendered, including the
|
||||
current time is the View is in the process of being rendered
|
||||
or re-rendered.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="autorun(runFunc)" id="view_autorun"}}
|
||||
Like [`Tracker.autorun`](#tracker_autorun), except that the autorun is
|
||||
automatically stopped when the View is destroyed, and the
|
||||
[current View](#blaze_currentview) is always set when running `runFunc`.
|
||||
There is no relationship to the View's internal autorun or render
|
||||
cycle. In `runFunc`, the View is bound to `this`.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="onViewCreated(func)" id="view_onviewcreated"}}
|
||||
If the View hasn't been created yet, calls `func` when the View
|
||||
is created. In `func`, the View is bound to `this`.
|
||||
|
||||
This hook is the basis for the [`created`](#template_created)
|
||||
template callback.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="onViewReady(func)" id="view_onviewready"}}
|
||||
Calls `func` when the View is rendered and inserted into the DOM,
|
||||
after waiting for the end of
|
||||
[flush time](#tracker_afterflush). Does not fire if the View
|
||||
is destroyed at any point before it would fire.
|
||||
May fire multiple times (if the View re-renders).
|
||||
In `func`, the View is bound to `this`.
|
||||
|
||||
This hook is the basis for the [`rendered`](#template_rendered)
|
||||
template callback.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="onViewDestroyed(func)" id="view_onviewdestroyed"}}
|
||||
If the View hasn't been destroyed yet, calls `func` when the
|
||||
View is destroyed. A View may be destroyed without ever becoming
|
||||
"ready." In `func`, the View is bound to `this`.
|
||||
|
||||
This hook is the basis for the [`destroyed`](#template_destroyed)
|
||||
template callback.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="firstNode()" type="DOM node" id="view_firstnode"}}
|
||||
The first node of the View's rendered content. Note that this may
|
||||
be a text node. Requires that the View be rendered.
|
||||
If the View rendered to zero DOM nodes, it may be a placeholder
|
||||
node (comment or text node). The DOM extent of a View consists
|
||||
of the nodes between `view.firstNode()` and `view.lastNode()`,
|
||||
inclusive.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="lastNode()" type="DOM node" id="view_lastnode"}}
|
||||
The last node of the View's rendered content.
|
||||
|
||||
See [`firstNode()`](#view_firstnode).
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="template" type="Template" id="view_template"}}
|
||||
For Views created by invoking templates, the original Template
|
||||
object. For example, `Blaze.render(Template.foo).template === Template.foo`.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="templateInstance()" type="Template instance"
|
||||
id="view_templateinstance"}} For Views created by invoking templates,
|
||||
returns the [template instance](#template_inst) object for this
|
||||
particular View. For example, in a [`created`](#template_created)
|
||||
callback, `this.view.templateInstance() === this`.
|
||||
|
||||
Template instance objects have fields like `data`, `firstNode`, and
|
||||
`lastNode` which are not reactive and which are also not automatically
|
||||
kept up to date. Calling `templateInstance()` causes these fields to
|
||||
be updated.
|
||||
|
||||
{{/dtdd}}
|
||||
|
||||
</dl>
|
||||
|
||||
{{> autoApiBox "Blaze.currentView"}}
|
||||
|
||||
The "current view" is used by [`Template.currentData()`](#template_currentdata) and
|
||||
[`Template.instance()`](#template_instance) to determine
|
||||
the contextually relevant data context and template instance.
|
||||
|
||||
{{> autoApiBox "Blaze.getView"}}
|
||||
|
||||
If you don't specify an `element`, there must be a current View or an
|
||||
error will be thrown. This is in contrast to
|
||||
[`Blaze.currentView`](#blaze_currentview).
|
||||
|
||||
{{> autoApiBox "Blaze.With"}}
|
||||
|
||||
Returns an unrendered View object you can pass to `Blaze.render`.
|
||||
|
||||
Unlike `{{dstache}}#with}}` (as used in templates), `Blaze.With` has no "else" case, and
|
||||
a falsy value for the data context will not prevent the content from
|
||||
rendering.
|
||||
|
||||
{{> autoApiBox "Blaze.If"}}
|
||||
|
||||
Returns an unrendered View object you can pass to `Blaze.render`.
|
||||
|
||||
Matches the behavior of `{{dstache}}#if}}` in templates.
|
||||
|
||||
{{> autoApiBox "Blaze.Unless"}}
|
||||
|
||||
Returns an unrendered View object you can pass to `Blaze.render`.
|
||||
|
||||
Matches the behavior of `{{dstache}}#unless}}` in templates.
|
||||
|
||||
{{> autoApiBox "Blaze.Each"}}
|
||||
|
||||
Returns an unrendered View object you can pass to `Blaze.render`.
|
||||
|
||||
Matches the behavior of `{{dstache}}#each}}` in templates.
|
||||
|
||||
{{> autoApiBox "Blaze.Template"}}
|
||||
|
||||
Templates defined by the template compiler, such as `Template.myTemplate`,
|
||||
are objects of type `Blaze.Template` (aliased as `Template`).
|
||||
|
||||
In addition to methods like `events` and `helpers`, documented as part of
|
||||
the [Template API](#templates_api), the following fields and methods are
|
||||
present on template objects:
|
||||
|
||||
<dl class="objdesc">
|
||||
|
||||
{{#dtdd name="viewName" type="String" id="template_viewname"}}
|
||||
Same as the constructor argument.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="renderFunction" type="Function" id="template_renderfunction"}}
|
||||
Same as the constructor argument.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="constructView()" id="template_constructview"}}
|
||||
Constructs and returns an unrendered View object. This method is invoked
|
||||
by Meteor whenever the template is used, such as by `Blaze.render` or by
|
||||
`{{dstache}}> foo}}` where `foo` resolves to a Template object.
|
||||
|
||||
`constructView()` constructs a View using `viewName` and `renderFunction`
|
||||
as constructor arguments, and then configures it as a template
|
||||
View, setting up `view.template`, `view.templateInstance()`, event maps, and so on.
|
||||
{{/dtdd}}
|
||||
|
||||
</dl>
|
||||
|
||||
{{> autoApiBox "Blaze.isTemplate"}}
|
||||
|
||||
{{> apiBoxTitle name="Renderable Content" id="renderable_content"}}
|
||||
|
||||
A value is *renderable content* if it is one of the following:
|
||||
|
||||
* A [template object](#templates_api) like `Template.myTemplate`
|
||||
* An unrendered [View](#blaze_view) object, like the return value of `Blaze.With`
|
||||
* `null` or `undefined`
|
||||
|
||||
{{#note}}
|
||||
Internally, renderable content includes objects representing HTML tags
|
||||
as well, but these objects are not yet part of the officially-supported,
|
||||
public API.
|
||||
{{/note}}
|
||||
|
||||
{{/template}}
|
||||
138
docs/client/api/check.md
Normal file
138
docs/client/api/check.md
Normal file
@@ -0,0 +1,138 @@
|
||||
{{#template name="api_check"}}
|
||||
|
||||
<h2 id="check_package"><span>Check</span></h2>
|
||||
|
||||
The `check` package includes pattern checking functions useful for checking
|
||||
the types and structure of variables and an [extensible
|
||||
library of patterns](#matchpatterns) to specify which types you are expecting.
|
||||
|
||||
{{> autoApiBox "check"}}
|
||||
|
||||
Meteor methods and publish functions take arbitrary [EJSON](#ejson) types as
|
||||
arguments, but most arguments are expected to be of a particular type. `check`
|
||||
is a lightweight function for checking that arguments and other
|
||||
values are of the expected type. For example:
|
||||
|
||||
Meteor.publish("chats-in-room", function (roomId) {
|
||||
// Make sure roomId is a string, not an arbitrary mongo selector object.
|
||||
check(roomId, String);
|
||||
return Chats.find({room: roomId});
|
||||
});
|
||||
|
||||
Meteor.methods({addChat: function (roomId, message) {
|
||||
check(roomId, String);
|
||||
check(message, {
|
||||
text: String,
|
||||
timestamp: Date,
|
||||
// Optional, but if present must be an array of strings.
|
||||
tags: Match.Optional([String])
|
||||
});
|
||||
|
||||
// ... do something with the message ...
|
||||
}});
|
||||
|
||||
If the match fails, `check` throws a `Match.Error` describing how it failed. If
|
||||
this error gets sent over the wire to the client, it will appear only as
|
||||
`Meteor.Error(400, "Match Failed")`. The failure details will be written to the
|
||||
server logs but not revealed to the client.
|
||||
|
||||
{{> autoApiBox "Match.test"}}
|
||||
|
||||
`Match.test` can be used to identify if a variable has a certain structure.
|
||||
|
||||
```js
|
||||
// will return true for {foo: 1, bar: "hello"} or similar
|
||||
Match.test(value, {foo: Match.Integer, bar: String});
|
||||
|
||||
// will return true if value is a string
|
||||
Match.test(value, String);
|
||||
|
||||
// will return true if value is a String or an array of Numbers
|
||||
Match.test(value, Match.OneOf(String, [Number]));
|
||||
```
|
||||
|
||||
This can be useful if you have a function that accepts several different kinds
|
||||
of objects, and you want to determine which was passed in.
|
||||
|
||||
{{> apiBoxTitle name="Match Patterns" id="matchpatterns"}}
|
||||
|
||||
The following patterns can be used as pattern arguments to
|
||||
[`check`](#check) and `Match.test`:
|
||||
|
||||
|
||||
<dl>
|
||||
{{#dtdd "<code>Match.Any</code>"}}
|
||||
Matches any value.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "<code>String</code>, <code>Number</code>, <code>Boolean</code>, <code>undefined</code>, <code>null</code>"}}
|
||||
Matches a primitive of the given type.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "<code>Match.Integer</code>"}}
|
||||
Matches a signed 32-bit integer. Doesn't match `Infinity`, `-Infinity`, or `NaN`.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "<code>[<em>pattern</em>]</code>"}}
|
||||
A one-element array matches an array of elements, each of which match
|
||||
*pattern*. For example, `[Number]` matches a (possibly empty) array of numbers;
|
||||
`[Match.Any]` matches any array.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "<code>{<em>key1</em>: <em>pattern1</em>, <em>key2</em>: <em>pattern2</em>, ...}</code>"}}
|
||||
Matches an Object with the given keys, with values matching the given patterns.
|
||||
If any *pattern* is a `Match.Optional`, that key does not need to exist
|
||||
in the object. The value may not contain any keys not listed in the pattern.
|
||||
The value must be a plain Object with no special prototype.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "<code>Match.ObjectIncluding({<em>key1</em>: <em>pattern1</em>, <em>key2</em>: <em>pattern2</em>, ...})</code>"}}
|
||||
Matches an Object with the given keys; the value may also have other keys
|
||||
with arbitrary values.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "<code>Object</code>"}}
|
||||
Matches any plain Object with any keys; equivalent to
|
||||
`Match.ObjectIncluding({})`.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "<code>Match.Optional(<em>pattern</em>)</code>"}} Matches either
|
||||
`undefined` or something that matches pattern. If used in an object this matches
|
||||
only if the key is not set as opposed to the value being set to `undefined`.
|
||||
|
||||
// In an object
|
||||
var pat = { name: Match.Optional(String) };
|
||||
check({ name: "something" }, pat) // OK
|
||||
check({}, pat) // OK
|
||||
check({ name: undefined }, pat) // Throws an exception
|
||||
|
||||
// Outside an object
|
||||
check(undefined, Match.Optional(String)); // OK
|
||||
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "<code>Match.OneOf(<em>pattern1</em>, <em>pattern2</em>, ...)</code>"}}
|
||||
Matches any value that matches at least one of the provided patterns.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "Any constructor function (eg, <code>Date</code>)"}}
|
||||
Matches any element that is an instance of that type.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "<code>Match.Where(<em>condition</em>)</code>"}}
|
||||
Calls the function *condition* with the value as the argument. If *condition*
|
||||
returns true, this matches. If *condition* throws a `Match.Error` or returns
|
||||
false, this fails. If *condition* throws any other error, that error is thrown
|
||||
from the call to `check` or `Match.test`. Examples:
|
||||
|
||||
check(buffer, Match.Where(EJSON.isBinary));
|
||||
|
||||
NonEmptyString = Match.Where(function (x) {
|
||||
check(x, String);
|
||||
return x.length > 0;
|
||||
});
|
||||
check(arg, NonEmptyString);
|
||||
{{/dtdd}}
|
||||
</dl>
|
||||
|
||||
{{/template}}
|
||||
827
docs/client/api/collections.md
Normal file
827
docs/client/api/collections.md
Normal file
@@ -0,0 +1,827 @@
|
||||
{{#template name="api_collections"}}
|
||||
|
||||
|
||||
<h2 id="collections"><span>Collections</span></h2>
|
||||
|
||||
Meteor stores data in *collections*. To get started, declare a
|
||||
collection with `new Mongo.Collection`.
|
||||
|
||||
{{> autoApiBox "Mongo.Collection"}}
|
||||
|
||||
Calling this function is analogous to declaring a model in a traditional ORM
|
||||
(Object-Relation Mapper)-centric framework. It sets up a *collection* (a storage
|
||||
space for records, or "documents") that can be used to store a particular type
|
||||
of information, like users, posts, scores, todo items, or whatever matters to
|
||||
your application. Each document is a EJSON object. It includes an `_id`
|
||||
property whose value is unique in the collection, which Meteor will set when you
|
||||
first create the document.
|
||||
|
||||
// common code on client and server declares a DDP-managed mongo
|
||||
// collection.
|
||||
Chatrooms = new Mongo.Collection("chatrooms");
|
||||
Messages = new Mongo.Collection("messages");
|
||||
|
||||
The function returns an object with methods to [`insert`](#insert)
|
||||
documents in the collection, [`update`](#update) their properties, and
|
||||
[`remove`](#remove) them, and to [`find`](#find) the documents in the
|
||||
collection that match arbitrary criteria. The way these methods work is
|
||||
compatible with the popular Mongo database API. The same database API
|
||||
works on both the client and the server (see below).
|
||||
|
||||
// return array of my messages
|
||||
var myMessages = Messages.find({userId: Session.get('myUserId')}).fetch();
|
||||
|
||||
// create a new message
|
||||
Messages.insert({text: "Hello, world!"});
|
||||
|
||||
// mark my first message as "important"
|
||||
Messages.update(myMessages[0]._id, {$set: {important: true}});
|
||||
|
||||
If you pass a `name` when you create the collection, then you are
|
||||
declaring a persistent collection — one that is stored on the
|
||||
server and seen by all users. Client code and server code can both
|
||||
access the same collection using the same API.
|
||||
|
||||
Specifically, when you pass a `name`, here's what happens:
|
||||
|
||||
* On the server (if you do not specify a `connection`), a collection with that
|
||||
name is created on a backend Mongo server. When you call methods on that
|
||||
collection on the server, they translate directly into normal Mongo operations
|
||||
(after checking that they match your [access control rules](#allow)).
|
||||
|
||||
* On the client (and on the server if you specify a `connection`), a Minimongo
|
||||
instance is created. Minimongo is essentially an in-memory, non-persistent
|
||||
implementation of Mongo in pure JavaScript. It serves as a local cache that
|
||||
stores just the subset of the database that this client is working with. Queries
|
||||
([`find`](#find)) on these collections are served directly out of this cache,
|
||||
without talking to the server.
|
||||
|
||||
* When you write to the database on the client ([`insert`](#insert),
|
||||
[`update`](#update), [`remove`](#remove)), the command is executed locally
|
||||
immediately, and, simultaneously, it's sent to the server and executed
|
||||
there too. This happens via [stubs](#meteor_methods), because writes are
|
||||
implemented as methods.
|
||||
|
||||
{{#note}}
|
||||
When, on the server, you write to a collection which has a specified
|
||||
`connection` to another server, it sends the corresponding method to the other
|
||||
server and receives the changed values back from it over DDP. Unlike on the
|
||||
client, it does not execute the write locally first.
|
||||
{{/note}}
|
||||
|
||||
If you pass `null` as the `name`, then you're creating a local
|
||||
collection. It's not synchronized anywhere; it's just a local scratchpad
|
||||
that supports Mongo-style [`find`](#find), [`insert`](#insert),
|
||||
[`update`](#update), and [`remove`](#remove) operations. (On both the
|
||||
client and the server, this scratchpad is implemented using Minimongo.)
|
||||
|
||||
By default, Meteor automatically publishes every document in your
|
||||
collection to each connected client. To turn this behavior off, remove
|
||||
the `autopublish` package:
|
||||
|
||||
$ meteor remove autopublish
|
||||
|
||||
and instead call [`Meteor.publish`](#meteor_publish) to specify which parts of
|
||||
your collection should be published to which users.
|
||||
|
||||
// Create a collection called Posts and put a document in it. The
|
||||
// document will be immediately visible in the local copy of the
|
||||
// collection. It will be written to the server-side database
|
||||
// a fraction of a second later, and a fraction of a second
|
||||
// after that, it will be synchronized down to any other clients
|
||||
// that are subscribed to a query that includes it (see
|
||||
// Meteor.subscribe and autopublish)
|
||||
Posts = new Mongo.Collection("posts");
|
||||
Posts.insert({title: "Hello world", body: "First post"});
|
||||
|
||||
// Changes are visible immediately -- no waiting for a round trip to
|
||||
// the server.
|
||||
assert(Posts.find().count() === 1);
|
||||
|
||||
// Create a temporary, local collection. It works just like any other
|
||||
// collection, but it doesn't send changes to the server, and it
|
||||
// can't receive any data from subscriptions.
|
||||
Scratchpad = new Mongo.Collection;
|
||||
for (var i = 0; i < 10; i++)
|
||||
Scratchpad.insert({number: i * 2});
|
||||
assert(Scratchpad.find({number: {$lt: 9}}).count() === 5);
|
||||
|
||||
Generally, you'll assign `Mongo.Collection` objects in your app to global
|
||||
variables. You can only create one `Mongo.Collection` object for each
|
||||
underlying Mongo collection.
|
||||
|
||||
If you specify a `transform` option to the `Collection` or any of its retrieval
|
||||
methods, documents are passed through the `transform` function before being
|
||||
returned or passed to callbacks. This allows you to add methods or otherwise
|
||||
modify the contents of your collection from their database representation. You
|
||||
can also specify `transform` on a particular `find`, `findOne`, `allow`, or
|
||||
`deny` call. Transform functions must return an object and they may not change
|
||||
the value of the document's `_id` field (though it's OK to leave it out).
|
||||
|
||||
// An Animal class that takes a document in its constructor
|
||||
Animal = function (doc) {
|
||||
_.extend(this, doc);
|
||||
};
|
||||
_.extend(Animal.prototype, {
|
||||
makeNoise: function () {
|
||||
console.log(this.sound);
|
||||
}
|
||||
});
|
||||
|
||||
// Define a Collection that uses Animal as its document
|
||||
Animals = new Mongo.Collection("Animals", {
|
||||
transform: function (doc) { return new Animal(doc); }
|
||||
});
|
||||
|
||||
// Create an Animal and call its makeNoise method
|
||||
Animals.insert({name: "raptor", sound: "roar"});
|
||||
Animals.findOne({name: "raptor"}).makeNoise(); // prints "roar"
|
||||
|
||||
`transform` functions are not called reactively. If you want to add a
|
||||
dynamically changing attribute to an object, do it with a function that computes
|
||||
the value at the time it's called, not by computing the attribute at `transform`
|
||||
time.
|
||||
|
||||
{{#warning}}
|
||||
In this release, Minimongo has some limitations:
|
||||
|
||||
* `$pull` in modifiers can only accept certain kinds
|
||||
of selectors.
|
||||
* `findAndModify`, aggregate functions, and
|
||||
map/reduce aren't supported.
|
||||
|
||||
All of these will be addressed in a future release. For full
|
||||
Minimongo release notes, see packages/minimongo/NOTES
|
||||
in the repository.
|
||||
{{/warning}}
|
||||
|
||||
{{#warning}}
|
||||
Minimongo doesn't currently have indexes. It's rare for this to be an
|
||||
issue, since it's unusual for a client to have enough data that an
|
||||
index is worthwhile.
|
||||
{{/warning}}
|
||||
|
||||
{{> autoApiBox "Mongo.Collection#find"}}
|
||||
|
||||
`find` returns a cursor. It does not immediately access the database or return
|
||||
documents. Cursors provide `fetch` to return all matching documents, `map` and
|
||||
`forEach` to iterate over all matching documents, and `observe` and
|
||||
`observeChanges` to register callbacks when the set of matching documents
|
||||
changes.
|
||||
|
||||
{{#warning}}
|
||||
Collection cursors are not query snapshots. If the database changes
|
||||
between calling `Collection.find` and fetching the
|
||||
results of the cursor, or while fetching results from the cursor,
|
||||
those changes may or may not appear in the result set.
|
||||
{{/warning}}
|
||||
|
||||
Cursors are a reactive data source. On the client, the first time you retrieve a
|
||||
cursor's documents with `fetch`, `map`, or `forEach` inside a
|
||||
reactive computation (eg, a template or
|
||||
[`autorun`](#tracker_autorun)), Meteor will register a
|
||||
dependency on the underlying data. Any change to the collection that
|
||||
changes the documents in a cursor will trigger a recomputation. To
|
||||
disable this behavior, pass `{reactive: false}` as an option to
|
||||
`find`.
|
||||
|
||||
Note that when `fields` are specified, only changes to the included
|
||||
fields will trigger callbacks in `observe`, `observeChanges` and
|
||||
invalidations in reactive computations using this cursor. Careful use
|
||||
of `fields` allows for more fine-grained reactivity for computations
|
||||
that don't depend on an entire document.
|
||||
|
||||
{{> autoApiBox "Mongo.Collection#findOne"}}
|
||||
|
||||
Equivalent to `find(selector, options).fetch()[0]` with
|
||||
`options.limit = 1`.
|
||||
|
||||
{{> autoApiBox "Mongo.Collection#insert"}}
|
||||
|
||||
Add a document to the collection. A document is just an object, and
|
||||
its fields can contain any combination of EJSON-compatible datatypes
|
||||
(arrays, objects, numbers, strings, `null`, true, and false).
|
||||
|
||||
`insert` will generate a unique ID for the object you pass, insert it
|
||||
in the database, and return the ID. When `insert` is called from
|
||||
untrusted client code, it will be allowed only if passes any
|
||||
applicable [`allow`](#allow) and [`deny`](#deny) rules.
|
||||
|
||||
On the server, if you don't provide a callback, then `insert` blocks
|
||||
until the database acknowledges the write, or throws an exception if
|
||||
something went wrong. If you do provide a callback, `insert` still
|
||||
returns the ID immediately. Once the insert completes (or fails), the
|
||||
callback is called with error and result arguments. In an error case,
|
||||
`result` is undefined. If the insert is successful, `error` is
|
||||
undefined and `result` is the new document ID.
|
||||
|
||||
On the client, `insert` never blocks. If you do not provide a callback
|
||||
and the insert fails on the server, then Meteor will log a warning to
|
||||
the console. If you provide a callback, Meteor will call that function
|
||||
with `error` and `result` arguments. In an error case, `result` is
|
||||
undefined. If the insert is successful, `error` is undefined and
|
||||
`result` is the new document ID.
|
||||
|
||||
Example:
|
||||
|
||||
var groceriesId = Lists.insert({name: "Groceries"});
|
||||
Items.insert({list: groceriesId, name: "Watercress"});
|
||||
Items.insert({list: groceriesId, name: "Persimmons"});
|
||||
|
||||
{{> autoApiBox "Mongo.Collection#update"}}
|
||||
|
||||
Modify documents that match `selector` according to `modifier` (see
|
||||
[modifier documentation](#modifiers)).
|
||||
|
||||
The behavior of `update` differs depending on whether it is called by
|
||||
trusted or untrusted code. Trusted code includes server code and
|
||||
method code. Untrusted code includes client-side code such as event
|
||||
handlers and a browser's JavaScript console.
|
||||
|
||||
- Trusted code can modify multiple documents at once by setting
|
||||
`multi` to true, and can use an arbitrary [Mongo
|
||||
selector](#selectors) to find the documents to modify. It bypasses
|
||||
any access control rules set up by [`allow`](#allow) and
|
||||
[`deny`](#deny). The number of affected documents will be returned
|
||||
from the `update` call if you don't pass a callback.
|
||||
|
||||
- Untrusted code can only modify a single document at once, specified
|
||||
by its `_id`. The modification is allowed only after checking any
|
||||
applicable [`allow`](#allow) and [`deny`](#deny) rules. The number
|
||||
of affected documents will be returned to the callback. Untrusted
|
||||
code cannot perform upserts, except in insecure mode.
|
||||
|
||||
On the server, if you don't provide a callback, then `update` blocks
|
||||
until the database acknowledges the write, or throws an exception if
|
||||
something went wrong. If you do provide a callback, `update` returns
|
||||
immediately. Once the update completes, the callback is called with a
|
||||
single error argument in the case of failure, or a second argument
|
||||
indicating the number of affected documents if the update was successful.
|
||||
|
||||
On the client, `update` never blocks. If you do not provide a callback
|
||||
and the update fails on the server, then Meteor will log a warning to
|
||||
the console. If you provide a callback, Meteor will call that function
|
||||
with an error argument if there was an error, or a second argument
|
||||
indicating the number of affected documents if the update was successful.
|
||||
|
||||
Client example:
|
||||
|
||||
// When the givePoints button in the admin dashboard is pressed,
|
||||
// give 5 points to the current player. The new score will be
|
||||
// immediately visible on everyone's screens.
|
||||
Template.adminDashboard.events({
|
||||
'click .givePoints': function () {
|
||||
Players.update(Session.get("currentPlayer"), {$inc: {score: 5}});
|
||||
}
|
||||
});
|
||||
|
||||
Server example:
|
||||
|
||||
// Give the "Winner" badge to each user with a score greater than
|
||||
// 10. If they are logged in and their badge list is visible on the
|
||||
// screen, it will update automatically as they watch.
|
||||
Meteor.methods({
|
||||
declareWinners: function () {
|
||||
Players.update({score: {$gt: 10}},
|
||||
{$addToSet: {badges: "Winner"}},
|
||||
{multi: true});
|
||||
}
|
||||
});
|
||||
|
||||
You can use `update` to perform a Mongo upsert by setting the `upsert`
|
||||
option to true. You can also use the [`upsert`](#upsert) method to perform an
|
||||
upsert that returns the _id of the document that was inserted (if there was one)
|
||||
in addition to the number of affected documents.
|
||||
|
||||
{{> autoApiBox "Mongo.Collection#upsert"}}
|
||||
|
||||
Modify documents that match `selector` according to `modifier`, or insert
|
||||
a document if no documents were modified. `upsert` is the same as calling
|
||||
`update` with the `upsert` option set to true, except that the return
|
||||
value of `upsert` is an object that contain the keys `numberAffected`
|
||||
and `insertedId`. (`update` returns only the number of affected documents.)
|
||||
|
||||
{{> autoApiBox "Mongo.Collection#remove"}}
|
||||
|
||||
Find all of the documents that match `selector` and delete them from
|
||||
the collection.
|
||||
|
||||
The behavior of `remove` differs depending on whether it is called by
|
||||
trusted or untrusted code. Trusted code includes server code and
|
||||
method code. Untrusted code includes client-side code such as event
|
||||
handlers and a browser's JavaScript console.
|
||||
|
||||
- Trusted code can use an arbitrary [Mongo selector](#selectors) to
|
||||
find the documents to remove, and can remove more than one document
|
||||
at once by passing a selector that matches multiple documents. It
|
||||
bypasses any access control rules set up by [`allow`](#allow) and
|
||||
[`deny`](#deny). The number of removed documents will be returned
|
||||
from `remove` if you don't pass a callback.
|
||||
|
||||
As a safety measure, if `selector` is omitted (or is `undefined`),
|
||||
no documents will be removed. Set `selector` to `{}` if you really
|
||||
want to remove all documents from your collection.
|
||||
|
||||
- Untrusted code can only remove a single document at a time,
|
||||
specified by its `_id`. The document is removed only after checking
|
||||
any applicable [`allow`](#allow) and [`deny`](#deny) rules. The
|
||||
number of removed documents will be returned to the callback.
|
||||
|
||||
On the server, if you don't provide a callback, then `remove` blocks
|
||||
until the database acknowledges the write and then returns the number
|
||||
of removed documents, or throws an exception if
|
||||
something went wrong. If you do provide a callback, `remove` returns
|
||||
immediately. Once the remove completes, the callback is called with a
|
||||
single error argument in the case of failure, or a second argument
|
||||
indicating the number of removed documents if the remove was successful.
|
||||
|
||||
On the client, `remove` never blocks. If you do not provide a callback
|
||||
and the remove fails on the server, then Meteor will log a warning to the
|
||||
console. If you provide a callback, Meteor will call that function with an
|
||||
error argument if there was an error, or a second argument indicating the number
|
||||
of removed documents if the remove was successful.
|
||||
|
||||
Client example:
|
||||
|
||||
// When the remove button is clicked on a chat message, delete
|
||||
// that message.
|
||||
Template.chat.events({
|
||||
'click .remove': function () {
|
||||
Messages.remove(this._id);
|
||||
}
|
||||
});
|
||||
|
||||
Server example:
|
||||
|
||||
// When the server starts, clear the log, and delete all players
|
||||
// with a karma of less than -2.
|
||||
Meteor.startup(function () {
|
||||
if (Meteor.isServer) {
|
||||
Logs.remove({});
|
||||
Players.remove({karma: {$lt: -2}});
|
||||
}
|
||||
});
|
||||
|
||||
{{> autoApiBox "Mongo.Collection#allow"}}
|
||||
|
||||
When a client calls `insert`, `update`, or `remove` on a collection, the
|
||||
collection's `allow` and [`deny`](#deny) callbacks are called
|
||||
on the server to determine if the write should be allowed. If at least
|
||||
one `allow` callback allows the write, and no `deny` callbacks deny the
|
||||
write, then the write is allowed to proceed.
|
||||
|
||||
These checks are run only when a client tries to write to the database
|
||||
directly, for example by calling `update` from inside an event
|
||||
handler. Server code is trusted and isn't subject to `allow` and `deny`
|
||||
restrictions. That includes methods that are called with `Meteor.call`
|
||||
— they are expected to do their own access checking rather than
|
||||
relying on `allow` and `deny`.
|
||||
|
||||
You can call `allow` as many times as you like, and each call can
|
||||
include any combination of `insert`, `update`, and `remove`
|
||||
functions. The functions should return `true` if they think the
|
||||
operation should be allowed. Otherwise they should return `false`, or
|
||||
nothing at all (`undefined`). In that case Meteor will continue
|
||||
searching through any other `allow` rules on the collection.
|
||||
|
||||
The available callbacks are:
|
||||
|
||||
<dl class="callbacks">
|
||||
{{#dtdd "insert(userId, doc)"}}
|
||||
The user `userId` wants to insert the document `doc` into the
|
||||
collection. Return `true` if this should be allowed.
|
||||
|
||||
`doc` will contain the `_id` field if one was explicitly set by the client, or
|
||||
if there is an active `transform`. You can use this to prevent users from
|
||||
specifying arbitrary `_id` fields.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "update(userId, doc, fieldNames, modifier)"}}
|
||||
|
||||
The user `userId` wants to update a document `doc`. (`doc` is the
|
||||
current version of the document from the database, without the
|
||||
proposed update.) Return `true` to permit the change.
|
||||
|
||||
`fieldNames` is an array of the (top-level) fields in `doc` that the
|
||||
client wants to modify, for example
|
||||
`['name',` `'score']`.
|
||||
|
||||
`modifier` is the raw Mongo modifier that
|
||||
the client wants to execute; for example,
|
||||
`{$set: {'name.first': "Alice"}, $inc: {score: 1}}`.
|
||||
|
||||
Only Mongo modifiers are supported (operations like `$set` and `$push`).
|
||||
If the user tries to replace the entire document rather than use
|
||||
$-modifiers, the request will be denied without checking the `allow`
|
||||
functions.
|
||||
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "remove(userId, doc)"}}
|
||||
|
||||
The user `userId` wants to remove `doc` from the database. Return
|
||||
`true` to permit this.
|
||||
|
||||
{{/dtdd}}
|
||||
|
||||
</dl>
|
||||
|
||||
When calling `update` or `remove` Meteor will by default fetch the
|
||||
entire document `doc` from the database. If you have large documents
|
||||
you may wish to fetch only the fields that are actually used by your
|
||||
functions. Accomplish this by setting `fetch` to an array of field
|
||||
names to retrieve.
|
||||
|
||||
Example:
|
||||
|
||||
// Create a collection where users can only modify documents that
|
||||
// they own. Ownership is tracked by an 'owner' field on each
|
||||
// document. All documents must be owned by the user that created
|
||||
// them and ownership can't be changed. Only a document's owner
|
||||
// is allowed to delete it, and the 'locked' attribute can be
|
||||
// set on a document to prevent its accidental deletion.
|
||||
|
||||
Posts = new Mongo.Collection("posts");
|
||||
|
||||
Posts.allow({
|
||||
insert: function (userId, doc) {
|
||||
// the user must be logged in, and the document must be owned by the user
|
||||
return (userId && doc.owner === userId);
|
||||
},
|
||||
update: function (userId, doc, fields, modifier) {
|
||||
// can only change your own documents
|
||||
return doc.owner === userId;
|
||||
},
|
||||
remove: function (userId, doc) {
|
||||
// can only remove your own documents
|
||||
return doc.owner === userId;
|
||||
},
|
||||
fetch: ['owner']
|
||||
});
|
||||
|
||||
Posts.deny({
|
||||
update: function (userId, docs, fields, modifier) {
|
||||
// can't change owners
|
||||
return _.contains(fields, 'owner');
|
||||
},
|
||||
remove: function (userId, doc) {
|
||||
// can't remove locked documents
|
||||
return doc.locked;
|
||||
},
|
||||
fetch: ['locked'] // no need to fetch 'owner'
|
||||
});
|
||||
|
||||
If you never set up any `allow` rules on a collection then all client
|
||||
writes to the collection will be denied, and it will only be possible to
|
||||
write to the collection from server-side code. In this case you will
|
||||
have to create a method for each possible write that clients are allowed
|
||||
to do. You'll then call these methods with `Meteor.call` rather than
|
||||
having the clients call `insert`, `update`, and `remove` directly on the
|
||||
collection.
|
||||
|
||||
Meteor also has a special "insecure mode" for quickly prototyping new
|
||||
applications. In insecure mode, if you haven't set up any `allow` or `deny`
|
||||
rules on a collection, then all users have full write access to the
|
||||
collection. This is the only effect of insecure mode. If you call `allow` or
|
||||
`deny` at all on a collection, even `Posts.allow({})`, then access is checked
|
||||
just like normal on that collection. __New Meteor projects start in insecure
|
||||
mode by default.__ To turn it off just run `$ meteor remove insecure`.
|
||||
|
||||
{{> autoApiBox "Mongo.Collection#deny"}}
|
||||
|
||||
This works just like [`allow`](#allow), except it lets you
|
||||
make sure that certain writes are definitely denied, even if there is an
|
||||
`allow` rule that says that they should be permitted.
|
||||
|
||||
When a client tries to write to a collection, the Meteor server first
|
||||
checks the collection's `deny` rules. If none of them return true then
|
||||
it checks the collection's `allow` rules. Meteor allows the write only
|
||||
if no `deny` rules return `true` and at least one `allow` rule returns
|
||||
`true`.
|
||||
|
||||
<h2 id="mongo_cursor"><span>Cursors</span></h2>
|
||||
|
||||
To create a cursor, use [`find`](#find). To access the documents in a
|
||||
cursor, use [`forEach`](#foreach), [`map`](#map), or [`fetch`](#fetch).
|
||||
|
||||
{{> autoApiBox "Mongo.Cursor#forEach"}}
|
||||
|
||||
This interface is compatible with [Array.forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach).
|
||||
|
||||
When called from a reactive computation, `forEach` registers dependencies on
|
||||
the matching documents.
|
||||
|
||||
Examples:
|
||||
|
||||
// Print the titles of the five top-scoring posts
|
||||
var topPosts = Posts.find({}, {sort: {score: -1}, limit: 5});
|
||||
var count = 0;
|
||||
topPosts.forEach(function (post) {
|
||||
console.log("Title of post " + count + ": " + post.title);
|
||||
count += 1;
|
||||
});
|
||||
|
||||
{{> autoApiBox "Mongo.Cursor#map"}}
|
||||
|
||||
This interface is compatible with [Array.map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map).
|
||||
|
||||
When called from a reactive computation, `map` registers dependencies on
|
||||
the matching documents.
|
||||
|
||||
<!-- The following is not yet implemented, but users shouldn't assume
|
||||
sequential execution anyway because that will break. -->
|
||||
On the server, if `callback` yields, other calls to `callback` may occur while
|
||||
the first call is waiting. If strict sequential execution is necessary, use
|
||||
`forEach` instead.
|
||||
|
||||
{{> autoApiBox "Mongo.Cursor#fetch"}}
|
||||
|
||||
When called from a reactive computation, `fetch` registers dependencies on
|
||||
the matching documents.
|
||||
|
||||
{{> autoApiBox "Mongo.Cursor#count"}}
|
||||
|
||||
Unlike the other functions, `count` registers a dependency only on the
|
||||
number of matching documents. (Updates that just change or reorder the
|
||||
documents in the result set will not trigger a recomputation.)
|
||||
|
||||
{{> autoApiBox "Mongo.Cursor#observe"}}
|
||||
|
||||
Establishes a *live query* that invokes callbacks when the result of
|
||||
the query changes. The callbacks receive the entire contents of the
|
||||
document that was affected, as well as its old contents, if
|
||||
applicable. If you only need to receive the fields that changed, see
|
||||
[`observeChanges`](#observe_changes).
|
||||
|
||||
`callbacks` may have the following functions as properties:
|
||||
|
||||
<dl class="callbacks">
|
||||
<dt><span class="name">added(document)</span> <span class="or">or</span></dt>
|
||||
<dt><span class="name">addedAt(document, atIndex, before)</span></dt>
|
||||
<dd>
|
||||
{{#markdown}}
|
||||
A new document `document` entered the result set. The new document
|
||||
appears at position `atIndex`. It is immediately before the document
|
||||
whose `_id` is `before`. `before` will be `null` if the new document
|
||||
is at the end of the results.
|
||||
{{/markdown}}
|
||||
</dd>
|
||||
|
||||
<dt><span class="name">changed(newDocument, oldDocument)
|
||||
<span class="or">or</span></span></dt>
|
||||
<dt><span class="name">changedAt(newDocument, oldDocument, atIndex)</span></dt>
|
||||
<dd>
|
||||
{{#markdown}}
|
||||
The contents of a document were previously `oldDocument` and are now
|
||||
`newDocument`. The position of the changed document is `atIndex`.
|
||||
{{/markdown}}
|
||||
</dd>
|
||||
|
||||
<dt><span class="name">removed(oldDocument)</span>
|
||||
<span class="or">or</span></dt>
|
||||
<dt><span class="name">removedAt(oldDocument, atIndex)</span></dt>
|
||||
<dd>
|
||||
{{#markdown}}
|
||||
The document `oldDocument` is no longer in the result set. It used to be at position `atIndex`.
|
||||
{{/markdown}}
|
||||
</dd>
|
||||
|
||||
{{#dtdd "movedTo(document, fromIndex, toIndex, before)"}}
|
||||
A document changed its position in the result set, from `fromIndex` to `toIndex`
|
||||
(which is before the document with id `before`). Its current contents is
|
||||
`document`.
|
||||
{{/dtdd}}
|
||||
</dl>
|
||||
|
||||
Use `added`, `changed`, and `removed` when you don't care about the
|
||||
order of the documents in the result set. They are more efficient than
|
||||
`addedAt`, `changedAt`, and `removedAt`.
|
||||
|
||||
Before `observe` returns, `added` (or `addedAt`) will be called zero
|
||||
or more times to deliver the initial results of the query.
|
||||
|
||||
`observe` returns a live query handle, which is an object with a `stop` method.
|
||||
Call `stop` with no arguments to stop calling the callback functions and tear
|
||||
down the query. **The query will run forever until you call this.** If
|
||||
`observe` is called from a `Tracker.autorun` computation, it is automatically
|
||||
stopped when the computation is rerun or stopped.
|
||||
(If the cursor was created with the option `reactive` set to false, it will
|
||||
only deliver the initial results and will not call any further callbacks;
|
||||
it is not necessary to call `stop` on the handle.)
|
||||
|
||||
|
||||
{{> autoApiBox "Mongo.Cursor#observeChanges"}}
|
||||
|
||||
Establishes a *live query* that invokes callbacks when the result of
|
||||
the query changes. In contrast to [`observe`](#observe),
|
||||
`observeChanges` provides only the difference between the old and new
|
||||
result set, not the entire contents of the document that changed.
|
||||
|
||||
`callbacks` may have the following functions as properties:
|
||||
|
||||
<dl class="callbacks">
|
||||
<dt><span class="name">added(id, fields)</span>
|
||||
<span class="or">or</span></dt>
|
||||
<dt><span class="name">addedBefore(id, fields, before)</span></dt>
|
||||
<dd>
|
||||
{{#markdown}}
|
||||
A new document entered the result set. It has the `id` and `fields`
|
||||
specified. `fields` contains all fields of the document excluding the
|
||||
`_id` field. The new document is before the document identified by
|
||||
`before`, or at the end if `before` is `null`.
|
||||
{{/markdown}}
|
||||
</dd>
|
||||
|
||||
{{#dtdd "changed(id, fields)"}}
|
||||
The document identified by `id` has changed. `fields` contains the
|
||||
changed fields with their new values. If a field was removed from the
|
||||
document then it will be present in `fields` with a value of
|
||||
`undefined`.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "movedBefore(id, before)"}}
|
||||
The document identified by `id` changed its position in the ordered result set,
|
||||
and now appears before the document identified by `before`.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "removed(id)"}}
|
||||
The document identified by `id` was removed from the result set.
|
||||
{{/dtdd}}
|
||||
</dl>
|
||||
|
||||
`observeChanges` is significantly more efficient if you do not use
|
||||
`addedBefore` or `movedBefore`.
|
||||
|
||||
Before `observeChanges` returns, `added` (or `addedBefore`) will be called
|
||||
zero or more times to deliver the initial results of the query.
|
||||
|
||||
`observeChanges` returns a live query handle, which is an object with a `stop`
|
||||
method. Call `stop` with no arguments to stop calling the callback functions
|
||||
and tear down the query. **The query will run forever until you call this.**
|
||||
If
|
||||
`observeChanges` is called from a `Tracker.autorun` computation, it is automatically
|
||||
stopped when the computation is rerun or stopped.
|
||||
(If the cursor was created with the option `reactive` set to false, it will
|
||||
only deliver the initial results and will not call any further callbacks;
|
||||
it is not necessary to call `stop` on the handle.)
|
||||
|
||||
{{#note}}
|
||||
Unlike `observe`, `observeChanges` does not provide absolute position
|
||||
information (that is, `atIndex` positions rather than `before`
|
||||
positions.) This is for efficiency.
|
||||
{{/note}}
|
||||
|
||||
Example:
|
||||
|
||||
// Keep track of how many administrators are online.
|
||||
var count = 0;
|
||||
var query = Users.find({admin: true, onlineNow: true});
|
||||
var handle = query.observeChanges({
|
||||
added: function (id, user) {
|
||||
count++;
|
||||
console.log(user.name + " brings the total to " + count + " admins.");
|
||||
},
|
||||
removed: function () {
|
||||
count--;
|
||||
console.log("Lost one. We're now down to " + count + " admins.");
|
||||
}
|
||||
});
|
||||
|
||||
// After five seconds, stop keeping the count.
|
||||
setTimeout(function () {handle.stop();}, 5000);
|
||||
|
||||
{{> autoApiBox "Mongo.ObjectID"}}
|
||||
|
||||
`Mongo.ObjectID` follows the same API as the [Node MongoDB driver
|
||||
`ObjectID`](http://mongodb.github.com/node-mongodb-native/api-bson-generated/objectid.html)
|
||||
class. Note that you must use the `equals` method (or [`EJSON.equals`](#ejson_equals)) to
|
||||
compare them; the `===` operator will not work. If you are writing generic code
|
||||
that needs to deal with `_id` fields that may be either strings or `ObjectID`s, use
|
||||
[`EJSON.equals`](#ejson_equals) instead of `===` to compare them.
|
||||
|
||||
{{#note}}
|
||||
`ObjectID` values created by Meteor will not have meaningful answers to their `getTimestamp`
|
||||
method, since Meteor currently constructs them fully randomly.
|
||||
{{/note}}
|
||||
|
||||
|
||||
|
||||
{{> apiBoxTitle name="Mongo-Style Selectors" id="selectors"}}
|
||||
|
||||
The simplest selectors are just a string or
|
||||
[`Mongo.ObjectID`](#mongo_object_id). These selectors match the
|
||||
document with that value in its `_id` field.
|
||||
|
||||
A slightly more complex form of selector is an object containing a set of keys
|
||||
that must match in a document:
|
||||
|
||||
// Matches all documents where deleted is false
|
||||
{deleted: false}
|
||||
|
||||
// Matches all documents where the name and cognomen are as given
|
||||
{name: "Rhialto", cognomen: "the Marvelous"}
|
||||
|
||||
// Matches every document
|
||||
{}
|
||||
|
||||
But they can also contain more complicated tests:
|
||||
|
||||
// Matches documents where age is greater than 18
|
||||
{age: {$gt: 18}}
|
||||
|
||||
// Also matches documents where tags is an array containing "popular"
|
||||
{tags: "popular"}
|
||||
|
||||
// Matches documents where fruit is one of three possibilities
|
||||
{fruit: {$in: ["peach", "plum", "pear"]}}
|
||||
|
||||
See the [complete
|
||||
documentation](http://docs.mongodb.org/manual/reference/operator/).
|
||||
|
||||
{{> apiBoxTitle name="Mongo-Style Modifiers" id="modifiers"}}
|
||||
|
||||
A modifier is an object that describes how to update a document in
|
||||
place by changing some of its fields. Some examples:
|
||||
|
||||
// Set the 'admin' property on the document to true
|
||||
{$set: {admin: true}}
|
||||
|
||||
// Add 2 to the 'votes' property, and add "Traz"
|
||||
// to the end of the 'supporters' array
|
||||
{$inc: {votes: 2}, $push: {supporters: "Traz"}}
|
||||
|
||||
But if a modifier doesn't contain any $-operators, then it is instead
|
||||
interpreted as a literal document, and completely replaces whatever was
|
||||
previously in the database. (Literal document modifiers are not currently
|
||||
supported by [validated updates](#allow).)
|
||||
|
||||
// Find the document with id "123", and completely replace it.
|
||||
Users.update({_id: "123"}, {name: "Alice", friends: ["Bob"]});
|
||||
|
||||
See the [full list of
|
||||
modifiers](http://docs.mongodb.org/manual/reference/operator/update/).
|
||||
|
||||
|
||||
{{> apiBoxTitle name="Sort Specifiers" id="sortspecifiers"}}
|
||||
|
||||
Sorts may be specified using your choice of several syntaxes:
|
||||
|
||||
// All of these do the same thing (sort in ascending order by
|
||||
// key "a", breaking ties in descending order of key "b")
|
||||
|
||||
[["a", "asc"], ["b", "desc"]]
|
||||
["a", ["b", "desc"]]
|
||||
{a: 1, b: -1}
|
||||
|
||||
The last form will only work if your JavaScript implementation
|
||||
preserves the order of keys in objects. Most do, most of the time, but
|
||||
it's up to you to be sure.
|
||||
|
||||
|
||||
|
||||
{{> apiBoxTitle name="Field Specifiers" id="fieldspecifiers"}}
|
||||
|
||||
Queries can specify a particular set of fields to include or exclude from the
|
||||
result object.
|
||||
|
||||
To exclude specific fields from the result objects, the field specifier is a
|
||||
dictionary whose keys are field names and whose values are `0`. All unspecified
|
||||
fields are included.
|
||||
|
||||
// Users.find({}, {fields: {password: 0, hash: 0}})
|
||||
|
||||
To include only specific fields in the result documents, use `1` as
|
||||
the value. The `_id` field is still included in the result.
|
||||
|
||||
// Users.find({}, {fields: {firstname: 1, lastname: 1}})
|
||||
|
||||
With one exception, it is not possible to mix inclusion and exclusion styles:
|
||||
the keys must either be all 1 or all 0. The exception is that you may specify
|
||||
`_id: 0` in an inclusion specifier, which will leave `_id` out of the result
|
||||
object as well. However, such field specifiers can not be used with
|
||||
[`observeChanges`](#observe_changes), [`observe`](#observe), cursors returned
|
||||
from a [publish function](#meteor_publish), or cursors used in
|
||||
`{{dstache}}#each}}` in a template. They may be used with [`fetch`](#fetch),
|
||||
[`findOne`](#findone), [`forEach`](#foreach), and [`map`](#map).
|
||||
|
||||
|
||||
<a href="http://docs.mongodb.org/manual/reference/operator/projection/">Field
|
||||
operators</a> such as `$` and `$elemMatch` are not available on the client side
|
||||
yet.
|
||||
|
||||
A more advanced example:
|
||||
|
||||
Users.insert({ alterEgos: [{ name: "Kira", alliance: "murderer" },
|
||||
{ name: "L", alliance: "police" }],
|
||||
name: "Yagami Light" });
|
||||
|
||||
Users.findOne({}, { fields: { 'alterEgos.name': 1, _id: 0 } });
|
||||
|
||||
// returns { alterEgos: [{ name: "Kira" }, { name: "L" }] }
|
||||
|
||||
See <a href="http://docs.mongodb.org/manual/tutorial/project-fields-from-query-results/#projection">
|
||||
the MongoDB docs</a> for details of the nested field rules and array behavior.
|
||||
|
||||
|
||||
|
||||
{{/template}}
|
||||
168
docs/client/api/connections.md
Normal file
168
docs/client/api/connections.md
Normal file
@@ -0,0 +1,168 @@
|
||||
{{#template name="api_connections"}}
|
||||
|
||||
<h2 id="connections"><span>Server connections</span></h2>
|
||||
|
||||
These functions manage and inspect the network connection between the
|
||||
Meteor client and server.
|
||||
|
||||
{{> autoApiBox "Meteor.status"}}
|
||||
|
||||
This method returns the status of the connection between the client and
|
||||
the server. The return value is an object with the following fields:
|
||||
|
||||
<dl class="objdesc">
|
||||
{{#dtdd name="connected" type="Boolean"}}
|
||||
True if currently connected to the server. If false, changes and
|
||||
method invocations will be queued up until the connection is
|
||||
reestablished.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="status" type="String"}}
|
||||
Describes the current reconnection status. The possible
|
||||
values are `connected` (the connection is up and
|
||||
running), `connecting` (disconnected and trying to open a
|
||||
new connection), `failed` (permanently failed to connect; e.g., the client
|
||||
and server support different versions of DDP), `waiting` (failed
|
||||
to connect and waiting to try to reconnect) and `offline` (user has disconnected the connection).
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="retryCount" type="Number"}}
|
||||
The number of times the client has tried to reconnect since the
|
||||
connection was lost. 0 when connected.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="retryTime" type="Number or undefined"}}
|
||||
The estimated time of the next reconnection attempt. To turn this
|
||||
into an interval until the next reconnection, use
|
||||
`retryTime - (new Date()).getTime()`. This key will
|
||||
be set only when `status` is `waiting`.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="reason" type="String or undefined"}}
|
||||
If `status` is `failed`, a description of why the connection failed.
|
||||
{{/dtdd}}
|
||||
</dl>
|
||||
|
||||
Instead of using callbacks to notify you on changes, this is
|
||||
a [reactive](#reactivity) data source. You can use it in a
|
||||
[template](#livehtmltemplates) or [computation](#tracker_autorun)
|
||||
to get realtime updates.
|
||||
|
||||
{{> autoApiBox "Meteor.reconnect"}}
|
||||
|
||||
{{> autoApiBox "Meteor.disconnect"}}
|
||||
|
||||
Call this method to disconnect from the server and stop all
|
||||
live data updates. While the client is disconnected it will not receive
|
||||
updates to collections, method calls will be queued until the
|
||||
connection is reestablished, and hot code push will be disabled.
|
||||
|
||||
Call [Meteor.reconnect](#meteor_reconnect) to reestablish the connection
|
||||
and resume data transfer.
|
||||
|
||||
This can be used to save battery on mobile devices when real time
|
||||
updates are not required.
|
||||
|
||||
|
||||
{{> autoApiBox "Meteor.onConnection"}}
|
||||
|
||||
`onConnection` returns an object with a single method `stop`. Calling
|
||||
`stop` unregisters the callback, so that this callback will no longer
|
||||
be called on new connections.
|
||||
|
||||
The callback is called with a single argument, the server-side
|
||||
`connection` representing the connection from the client. This object
|
||||
contains the following fields:
|
||||
|
||||
<dl class="objdesc">
|
||||
{{#dtdd name="id" type="String"}}
|
||||
A globally unique id for this connection.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="close" type="Function"}}
|
||||
Close this DDP connection. The client is free to reconnect, but will
|
||||
receive a different connection with a new `id` if it does.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="onClose" type="Function"}}
|
||||
Register a callback to be called when the connection is closed. If the
|
||||
connection is already closed, the callback will be called immediately.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="clientAddress" type="String"}}
|
||||
The IP address of the client in dotted form (such as `"127.0.0.1"`).
|
||||
|
||||
If you're running your Meteor server behind a proxy (so that clients
|
||||
are connecting to the proxy instead of to your server directly),
|
||||
you'll need to set the `HTTP_FORWARDED_COUNT` environment variable
|
||||
for the correct IP address to be reported by `clientAddress`.
|
||||
|
||||
Set `HTTP_FORWARDED_COUNT` to an integer representing the number of
|
||||
proxies in front of your server. For example, you'd set it to `"1"`
|
||||
when your server was behind one proxy.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="httpHeaders" type="Object"}}
|
||||
When the connection came in over an HTTP transport (such as with
|
||||
Meteor's default SockJS implementation), this field contains
|
||||
whitelisted HTTP headers.
|
||||
|
||||
Cookies are deliberately excluded from the headers as they are a
|
||||
security risk for this transport. For details and alternatives, see
|
||||
the [SockJS
|
||||
documentation](https://github.com/sockjs/sockjs-node#authorisation).
|
||||
{{/dtdd}}
|
||||
</dl>
|
||||
|
||||
{{#note}}
|
||||
|
||||
Currently when a client reconnects to the server (such as after
|
||||
temporarily losing its Internet connection), it will get a new
|
||||
connection each time. The `onConnection` callbacks will be called
|
||||
again, and the new connection will have a new connection `id`.
|
||||
|
||||
In the future, when client reconnection is fully implemented,
|
||||
reconnecting from the client will reconnect to the same connection on
|
||||
the server: the `onConnection` callback won't be called for that
|
||||
connection again, and the connection will still have the same
|
||||
connection `id`.
|
||||
|
||||
{{/note}}
|
||||
|
||||
|
||||
{{> autoApiBox "DDP.connect"}}
|
||||
|
||||
To call methods on another Meteor application or subscribe to its data
|
||||
sets, call `DDP.connect` with the URL of the application.
|
||||
`DDP.connect` returns an object which provides:
|
||||
|
||||
* `subscribe` -
|
||||
Subscribe to a record set. See
|
||||
[Meteor.subscribe](#meteor_subscribe).
|
||||
* `call` -
|
||||
Invoke a method. See [Meteor.call](#meteor_call).
|
||||
* `apply` -
|
||||
Invoke a method with an argument array. See
|
||||
[Meteor.apply](#meteor_apply).
|
||||
* `methods` -
|
||||
Define client-only stubs for methods defined on the remote server. See
|
||||
[Meteor.methods](#meteor_methods).
|
||||
* `status` -
|
||||
Get the current connection status. See
|
||||
[Meteor.status](#meteor_status).
|
||||
* `reconnect` -
|
||||
See [Meteor.reconnect](#meteor_reconnect).
|
||||
* `disconnect` -
|
||||
See [Meteor.disconnect](#meteor_disconnect).
|
||||
* `onReconnect` - Set this to a function to be called as the first step of
|
||||
reconnecting. This function can call methods which will be executed before
|
||||
any other outstanding methods. For example, this can be used to re-establish
|
||||
the appropriate authentication context on the new connection.
|
||||
|
||||
By default, clients open a connection to the server from which they're loaded.
|
||||
When you call `Meteor.subscribe`, `Meteor.status`, `Meteor.call`, and
|
||||
`Meteor.apply`, you are using a connection back to that default
|
||||
server.
|
||||
|
||||
|
||||
{{/template}}
|
||||
47
docs/client/api/core.md
Normal file
47
docs/client/api/core.md
Normal file
@@ -0,0 +1,47 @@
|
||||
{{#template name="api_core"}}
|
||||
|
||||
<h2 id="core"><span>Meteor Core</span></h2>
|
||||
|
||||
{{> autoApiBox "Meteor.isClient"}}
|
||||
{{> autoApiBox "Meteor.isServer"}}
|
||||
|
||||
{{#note}}
|
||||
`Meteor.isServer` can be used to limit where code runs, but it does not
|
||||
prevent code from being sent to the client. Any sensitive code that you
|
||||
don't want served to the client, such as code containing passwords or
|
||||
authentication mechanisms, should be kept in the `server` directory.
|
||||
{{/note}}
|
||||
|
||||
{{> autoApiBox "Meteor.isCordova"}}
|
||||
|
||||
{{> autoApiBox "Meteor.startup"}}
|
||||
|
||||
On a server, the function will run as soon as the server process is
|
||||
finished starting. On a client, the function will run as soon as the DOM
|
||||
is ready.
|
||||
|
||||
The `startup` callbacks are called in the same order as the calls to
|
||||
`Meteor.startup` were made.
|
||||
|
||||
On a client, `startup` callbacks from packages will be called
|
||||
first, followed by `<body>` templates from your `.html` files,
|
||||
followed by your application code.
|
||||
|
||||
// On server startup, if the database is empty, create some initial data.
|
||||
if (Meteor.isServer) {
|
||||
Meteor.startup(function () {
|
||||
if (Rooms.find().count() === 0) {
|
||||
Rooms.insert({name: "Initial room"});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
{{> autoApiBox "Meteor.wrapAsync"}}
|
||||
|
||||
{{> autoApiBox "Meteor.absoluteUrl"}}
|
||||
|
||||
{{> autoApiBox "Meteor.settings"}}
|
||||
|
||||
{{> autoApiBox "Meteor.release"}}
|
||||
|
||||
{{/template}}
|
||||
90
docs/client/api/ejson.md
Normal file
90
docs/client/api/ejson.md
Normal file
@@ -0,0 +1,90 @@
|
||||
{{#template name="api_ejson"}}
|
||||
|
||||
<h2 id="ejson"><span>EJSON</span></h2>
|
||||
|
||||
EJSON is an extension of JSON to support more types. It supports all JSON-safe
|
||||
types, as well as:
|
||||
|
||||
- **Date** (JavaScript `Date`)
|
||||
- **Binary** (JavaScript `Uint8Array` or the
|
||||
result of [`EJSON.newBinary`](#ejson_new_binary))
|
||||
- **User-defined types** (see [`EJSON.addType`](#ejson_add_type). For example,
|
||||
[`Mongo.ObjectID`](#mongo_object_id) is implemented this way.)
|
||||
|
||||
All EJSON serializations are also valid JSON. For example an object with a date
|
||||
and a binary buffer would be serialized in EJSON as:
|
||||
|
||||
{
|
||||
"d": {"$date": 1358205756553},
|
||||
"b": {"$binary": "c3VyZS4="}
|
||||
}
|
||||
|
||||
Meteor supports all built-in EJSON data types in publishers, method arguments
|
||||
and results, Mongo databases, and [`Session`](#session) variables.
|
||||
|
||||
{{> autoApiBox "EJSON.parse"}}
|
||||
|
||||
{{> autoApiBox "EJSON.stringify"}}
|
||||
|
||||
{{> autoApiBox "EJSON.fromJSONValue"}}
|
||||
|
||||
{{> autoApiBox "EJSON.toJSONValue"}}
|
||||
|
||||
{{> autoApiBox "EJSON.equals"}}
|
||||
|
||||
{{> autoApiBox "EJSON.clone"}}
|
||||
|
||||
{{> autoApiBox "EJSON.newBinary"}}
|
||||
|
||||
Buffers of binary data are represented by `Uint8Array` instances on JavaScript
|
||||
platforms that support them. On implementations of JavaScript that do not
|
||||
support `Uint8Array`, binary data buffers are represented by standard arrays
|
||||
containing numbers ranging from 0 to 255, and the `$Uint8ArrayPolyfill` key
|
||||
set to `true`.
|
||||
|
||||
{{> autoApiBox "EJSON.isBinary"}}
|
||||
|
||||
{{> autoApiBox "EJSON.addType"}}
|
||||
|
||||
When you add a type to EJSON, Meteor will be able to use that type in:
|
||||
|
||||
- publishing objects of your type if you pass them to publish handlers.
|
||||
- allowing your type in the return values or arguments to
|
||||
[methods](#methods_header).
|
||||
- storing your type client-side in Minimongo.
|
||||
- allowing your type in [`Session`](#session) variables.
|
||||
|
||||
Instances of your type must implement [`typeName`](#ejson_type_typeName) and
|
||||
[`toJSONValue`](#ejson_type_toJSONValue) methods, and may implement
|
||||
[`clone`](#ejson_type_clone) and [`equals`](#ejson_type_equals) methods if the
|
||||
default implementations are not sufficient.
|
||||
|
||||
{{> autoApiBox "EJSON.CustomType#typeName"}}
|
||||
{{> autoApiBox "EJSON.CustomType#toJSONValue"}}
|
||||
|
||||
For example, the `toJSONValue` method for
|
||||
[`Mongo.ObjectID`](#mongo_object_id) could be:
|
||||
|
||||
function () {
|
||||
return this.toHexString();
|
||||
};
|
||||
|
||||
{{> autoApiBox "EJSON.CustomType#clone"}}
|
||||
|
||||
If your type does not have a `clone` method, `EJSON.clone` will use
|
||||
[`toJSONValue`](#ejson_type_toJSONValue) and the factory instead.
|
||||
|
||||
{{> autoApiBox "EJSON.CustomType#equals"}}
|
||||
|
||||
The `equals` method should define an [equivalence
|
||||
relation](http://en.wikipedia.org/wiki/Equivalence_relation). It should have
|
||||
the following properties:
|
||||
|
||||
- *Reflexivity* - for any instance `a`: `a.equals(a)` must be true.
|
||||
- *Symmetry* - for any two instances `a` and `b`: `a.equals(b)` if and only if `b.equals(a)`.
|
||||
- *Transitivity* - for any three instances `a`, `b`, and `c`: `a.equals(b)` and `b.equals(c)` implies `a.equals(c)`.
|
||||
|
||||
If your type does not have an `equals` method, `EJSON.equals` will compare the
|
||||
result of calling [`toJSONValue`](#ejson_type_toJSONValue) instead.
|
||||
|
||||
{{/template}}
|
||||
57
docs/client/api/email.md
Normal file
57
docs/client/api/email.md
Normal file
@@ -0,0 +1,57 @@
|
||||
{{#template name="api_email"}}
|
||||
|
||||
<h2 id="email"><span>Email</span></h2>
|
||||
|
||||
The `email` package allows sending email from a Meteor app. To use it, add the
|
||||
package to your project with `$ meteor add email`.
|
||||
|
||||
The server reads from the `MAIL_URL` environment variable to determine how to
|
||||
send mail. Currently, Meteor supports sending mail over SMTP; the `MAIL_URL`
|
||||
environment variable should be of the form
|
||||
`smtp://USERNAME:PASSWORD@HOST:PORT/`. For apps deployed with `meteor deploy`,
|
||||
`MAIL_URL` defaults to an account (provided by
|
||||
[Mailgun](http://www.mailgun.com/)) which allows apps to send up to 200 emails
|
||||
per day; you may override this default by assigning to `process.env.MAIL_URL`
|
||||
before your first call to `Email.send`.
|
||||
|
||||
If `MAIL_URL` is not set (eg, when running your application locally),
|
||||
`Email.send` outputs the message to standard output instead.
|
||||
|
||||
{{> autoApiBox "Email.send"}}
|
||||
|
||||
You must provide the `from` option and at least one of `to`, `cc`, and `bcc`;
|
||||
all other options are optional.
|
||||
|
||||
`Email.send` only works on the server. Here is an example of how a
|
||||
client could use a server method call to send an email. (In an actual
|
||||
application, you'd need to be careful to limit the emails that a
|
||||
client could send, to prevent your server from being used as a relay
|
||||
by spammers.)
|
||||
|
||||
// In your server code: define a method that the client can call
|
||||
Meteor.methods({
|
||||
sendEmail: function (to, from, subject, text) {
|
||||
check([to, from, subject, text], [String]);
|
||||
|
||||
// Let other method calls from the same client start running,
|
||||
// without waiting for the email sending to complete.
|
||||
this.unblock();
|
||||
|
||||
Email.send({
|
||||
to: to,
|
||||
from: from,
|
||||
subject: subject,
|
||||
text: text
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// In your client code: asynchronously send an email
|
||||
Meteor.call('sendEmail',
|
||||
'alice@example.com',
|
||||
'bob@example.com',
|
||||
'Hello from Meteor!',
|
||||
'This is a test of Email.send.');
|
||||
|
||||
|
||||
{{/template}}
|
||||
102
docs/client/api/http.md
Normal file
102
docs/client/api/http.md
Normal file
@@ -0,0 +1,102 @@
|
||||
{{#template name="api_http"}}
|
||||
|
||||
<h2 id="http"><span>HTTP</span></h2>
|
||||
|
||||
`HTTP` provides an HTTP request API on the client and server. To use
|
||||
these functions, add the HTTP package to your project with `$ meteor add http`.
|
||||
|
||||
{{> autoApiBox "HTTP.call"}}
|
||||
|
||||
This function initiates an HTTP request to a remote server.
|
||||
|
||||
On the server, this function can be run either synchronously or
|
||||
asynchronously. If the callback is omitted, it runs synchronously
|
||||
and the results are returned once the request completes successfully.
|
||||
If the request was not successful, an error is thrown.
|
||||
This is
|
||||
useful when making server-to-server HTTP API calls from within Meteor
|
||||
methods, as the method can succeed or fail based on the results of the
|
||||
synchronous HTTP call. In this case, consider using
|
||||
[`this.unblock()`](#method_unblock) to allow other methods on the same
|
||||
connection to run in
|
||||
the mean time. On the client, this function must be used
|
||||
asynchronously by passing a callback.
|
||||
|
||||
Both HTTP and HTTPS protocols are supported. The `url` argument must be
|
||||
an absolute URL including protocol and host name on the server, but may be
|
||||
relative to the current host on the client. The `query` option
|
||||
replaces the query string of `url`. Parameters specified in `params`
|
||||
that are put in the URL are appended to any query string.
|
||||
For example, with a `url` of `"/path?query"` and
|
||||
`params` of `{foo:"bar"}`, the final URL will be `"/path?query&foo=bar"`.
|
||||
|
||||
The `params` are put in the URL or the request body, depending on the
|
||||
type of request. In the case of request with no bodies, like GET and
|
||||
HEAD, the parameters will always go in the URL. For a POST or other
|
||||
type of request, the parameters will be encoded into the body with a
|
||||
standard `x-www-form-urlencoded` content type, unless the `content`
|
||||
or `data` option is used to specify a body, in which case the
|
||||
parameters will be appended to the URL instead.
|
||||
|
||||
When run in asynchronous mode, the callback receives two arguments,
|
||||
`error` and `result`. The
|
||||
`error` argument will contain an Error if the request fails in any
|
||||
way, including a network error, time-out, or an HTTP status code in
|
||||
the 400 or 500 range. In case of a 4xx/5xx HTTP status code, the
|
||||
`response` property on `error` matches the contents of the result
|
||||
object. When run in synchronous mode, either `result` is returned
|
||||
from the function, or `error` is thrown.
|
||||
|
||||
Contents of the result object:
|
||||
|
||||
<dl class="objdesc">
|
||||
|
||||
<dt><span class="name">statusCode</span>
|
||||
<span class="type">Number</span></dt>
|
||||
<dd>Numeric HTTP result status code, or <code>null</code> on error.</dd>
|
||||
|
||||
<dt><span class="name">content</span>
|
||||
<span class="type">String</span></dt>
|
||||
<dd>The body of the HTTP response as a string.</dd>
|
||||
|
||||
<dt><span class="name">data</span>
|
||||
<span class="type">Object or <code>null</code></span></dt>
|
||||
<dd>If the response headers indicate JSON content, this contains the body of the document parsed as a JSON object.</dd>
|
||||
|
||||
<dt><span class="name">headers</span>
|
||||
<span class="type">Object</span></dt>
|
||||
<dd>A dictionary of HTTP headers from the response.</dd>
|
||||
|
||||
</dl>
|
||||
|
||||
Example server method:
|
||||
|
||||
Meteor.methods({checkTwitter: function (userId) {
|
||||
check(userId, String);
|
||||
this.unblock();
|
||||
try {
|
||||
var result = HTTP.call("GET", "http://api.twitter.com/xyz",
|
||||
{params: {user: userId}});
|
||||
return true;
|
||||
} catch (e) {
|
||||
// Got a network error, time-out or HTTP error in the 400 or 500 range.
|
||||
return false;
|
||||
}
|
||||
}});
|
||||
|
||||
Example asynchronous HTTP call:
|
||||
|
||||
HTTP.call("POST", "http://api.twitter.com/xyz",
|
||||
{data: {some: "json", stuff: 1}},
|
||||
function (error, result) {
|
||||
if (!error) {
|
||||
Session.set("twizzled", true);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
{{> autoApiBox "HTTP.get"}}
|
||||
{{> autoApiBox "HTTP.post"}}
|
||||
{{> autoApiBox "HTTP.put"}}
|
||||
{{> autoApiBox "HTTP.del"}}
|
||||
{{/template}}
|
||||
167
docs/client/api/methods.md
Normal file
167
docs/client/api/methods.md
Normal file
@@ -0,0 +1,167 @@
|
||||
{{#template name="api_methods"}}
|
||||
|
||||
<h2 id="methods_header"><span>Methods</span></h2>
|
||||
|
||||
Methods are remote functions that Meteor clients can invoke.
|
||||
|
||||
{{> autoApiBox "Meteor.methods"}}
|
||||
|
||||
Example:
|
||||
|
||||
Meteor.methods({
|
||||
foo: function (arg1, arg2) {
|
||||
check(arg1, String);
|
||||
check(arg2, [Number]);
|
||||
// .. do stuff ..
|
||||
if (you want to throw an error)
|
||||
throw new Meteor.Error("pants-not-found", "Can't find my pants");
|
||||
return "some return value";
|
||||
},
|
||||
|
||||
bar: function () {
|
||||
// .. do other stuff ..
|
||||
return "baz";
|
||||
}
|
||||
});
|
||||
|
||||
Calling `methods` on the server defines functions that can be called remotely by
|
||||
clients. They should return an [EJSON](#ejson)-able value or throw an
|
||||
exception. Inside your method invocation, `this` is bound to a method
|
||||
invocation object, which provides the following:
|
||||
|
||||
* `isSimulation`: a boolean value, true if this invocation is a stub.
|
||||
* `unblock`: when called, allows the next method from this client to
|
||||
begin running.
|
||||
* `userId`: the id of the current user.
|
||||
* `setUserId`: a function that associates the current client with a user.
|
||||
* `connection`: on the server, the [connection](#meteor_onconnection) this method call was received on.
|
||||
|
||||
Calling `methods` on the client defines *stub* functions associated with
|
||||
server methods of the same name. You don't have to define a stub for
|
||||
your method if you don't want to. In that case, method calls are just
|
||||
like remote procedure calls in other systems, and you'll have to wait
|
||||
for the results from the server.
|
||||
|
||||
If you do define a stub, when a client invokes a server method it will
|
||||
also run its stub in parallel. On the client, the return value of a
|
||||
stub is ignored. Stubs are run for their side-effects: they are
|
||||
intended to *simulate* the result of what the server's method will do,
|
||||
but without waiting for the round trip delay. If a stub throws an
|
||||
exception it will be logged to the console.
|
||||
|
||||
You use methods all the time, because the database mutators
|
||||
([`insert`](#insert), [`update`](#update), [`remove`](#remove)) are implemented
|
||||
as methods. When you call any of these functions on the client, you're invoking
|
||||
their stub version that update the local cache, and sending the same write
|
||||
request to the server. When the server responds, the client updates the local
|
||||
cache with the writes that actually occurred on the server.
|
||||
|
||||
Since methods usually expect particular types as arguments,
|
||||
use [`check`](#check) liberally to ensure your method arguments have
|
||||
the correct [types and structure](#matchpatterns).
|
||||
|
||||
{{> autoApiBox "MethodInvocation#userId"}}
|
||||
|
||||
The user id is an arbitrary string — typically the id of the user record
|
||||
in the database. You can set it with the `setUserId` function. If you're using
|
||||
the [Meteor accounts system](#accounts_api) then this is handled for you.
|
||||
|
||||
{{> autoApiBox "MethodInvocation#setUserId"}}
|
||||
|
||||
Call this function to change the currently logged in user on the
|
||||
connection that made this method call. This simply sets the value of
|
||||
`userId` for future method calls received on this connection. Pass
|
||||
`null` to log out the connection.
|
||||
|
||||
If you are using the [built-in Meteor accounts system](#accounts_api) then this
|
||||
should correspond to the `_id` field of a document in the
|
||||
[`Meteor.users`](#meteor_users) collection.
|
||||
|
||||
`setUserId` is not retroactive. It affects the current method call and
|
||||
any future method calls on the connection. Any previous method calls on
|
||||
this connection will still see the value of `userId` that was in effect
|
||||
when they started.
|
||||
|
||||
{{> autoApiBox "MethodInvocation#isSimulation"}}
|
||||
|
||||
{{> autoApiBox "MethodInvocation#unblock"}}
|
||||
|
||||
On the server, methods from a given client run one at a time. The N+1th
|
||||
invocation from a client won't start until the Nth invocation
|
||||
returns. However, you can change this by calling `this.unblock`. This
|
||||
will allow the N+1th invocation to start running in a new fiber.
|
||||
|
||||
{{> autoApiBox "MethodInvocation#connection"}}
|
||||
|
||||
{{> autoApiBox "Meteor.Error"}}
|
||||
|
||||
If you want to return an error from a method, throw an exception. Methods can
|
||||
throw any kind of exception. But `Meteor.Error` is the only kind of error that
|
||||
a server will send to the client. If a method function throws a different
|
||||
exception, then it will be mapped to a sanitized version on the
|
||||
wire. Specifically, if the `sanitizedError` field on the thrown error is set to
|
||||
a `Meteor.Error`, then that error will be sent to the client. Otherwise, if no
|
||||
sanitized version is available, the client gets
|
||||
`Meteor.Error(500, 'Internal server error')`.
|
||||
|
||||
{{> autoApiBox "Meteor.call"}}
|
||||
|
||||
This is how to invoke a method. It will run the method on the server. If a
|
||||
stub is available, it will also run the stub on the client. (See also
|
||||
[`Meteor.apply`](#meteor_apply), which is identical to `Meteor.call` except that
|
||||
you specify the parameters as an array instead of as separate arguments and you
|
||||
can specify a few options controlling how the method is executed.)
|
||||
|
||||
If you include a callback function as the last argument (which can't be
|
||||
an argument to the method, since functions aren't serializable), the
|
||||
method will run asynchronously: it will return nothing in particular and
|
||||
will not throw an exception. When the method is complete (which may or
|
||||
may not happen before `Meteor.call` returns), the callback will be
|
||||
called with two arguments: `error` and `result`. If an error was thrown,
|
||||
then `error` will be the exception object. Otherwise, `error` will be
|
||||
undefined and the return value (possibly undefined) will be in `result`.
|
||||
|
||||
// async call
|
||||
Meteor.call('foo', 1, 2, function (error, result) { ... } );
|
||||
|
||||
If you do not pass a callback on the server, the method invocation will
|
||||
block until the method is complete. It will eventually return the
|
||||
return value of the method, or it will throw an exception if the method
|
||||
threw an exception. (Possibly mapped to 500 Server Error if the
|
||||
exception happened remotely and it was not a `Meteor.Error` exception.)
|
||||
|
||||
// sync call
|
||||
var result = Meteor.call('foo', 1, 2);
|
||||
|
||||
On the client, if you do not pass a callback and you are not inside a
|
||||
stub, `call` will return `undefined`, and you will have no way to get
|
||||
the return value of the method. That is because the client doesn't have
|
||||
fibers, so there is not actually any way it can block on the remote
|
||||
execution of a method.
|
||||
|
||||
Finally, if you are inside a stub on the client and call another
|
||||
method, the other method is not executed (no RPC is generated, nothing
|
||||
"real" happens). If that other method has a stub, that stub stands in
|
||||
for the method and is executed. The method call's return value is the
|
||||
return value of the stub function. The client has no problem executing
|
||||
a stub synchronously, and that is why it's okay for the client to use
|
||||
the synchronous `Meteor.call` form from inside a method body, as
|
||||
described earlier.
|
||||
|
||||
Meteor tracks the database writes performed by methods, both on the client and
|
||||
the server, and does not invoke `asyncCallback` until all of the server's writes
|
||||
replace the stub's writes in the local cache. In some cases, there can be a lag
|
||||
between the method's return value being available and the writes being visible:
|
||||
for example, if another method still outstanding wrote to the same document, the
|
||||
local cache may not be up to date until the other method finishes as well. If
|
||||
you want to process the method's result as soon as it arrives from the server,
|
||||
even if the method's writes are not available yet, you can specify an
|
||||
`onResultReceived` callback to [`Meteor.apply`](#meteor_apply).
|
||||
|
||||
{{> autoApiBox "Meteor.apply"}}
|
||||
|
||||
`Meteor.apply` is just like `Meteor.call`, except that the method arguments are
|
||||
passed as an array rather than directly as arguments, and you can specify
|
||||
options about how the client executes the method.
|
||||
|
||||
{{/template}}
|
||||
57
docs/client/api/mobile-config.md
Normal file
57
docs/client/api/mobile-config.md
Normal file
@@ -0,0 +1,57 @@
|
||||
{{#template name="api_mobile_config"}}
|
||||
|
||||
|
||||
<h2 id="mobileconfigjs"><span>Mobile Config File</span></h2>
|
||||
|
||||
If your Meteor application targets mobile platforms such as iOS or
|
||||
Android, you can configure your app's metadata and build process
|
||||
in a special top-level file called
|
||||
`mobile-config.js` which is *not* included in your application and is used only
|
||||
for this configuration.
|
||||
|
||||
The code snippet below is an example `mobile-config.js` file. The rest of this
|
||||
section will explain the specific API commands in greater detail.
|
||||
|
||||
```javascript
|
||||
// This section sets up some basic app metadata,
|
||||
// the entire section is optional.
|
||||
App.info({
|
||||
id: 'com.example.matt.uber',
|
||||
name: 'über',
|
||||
description: 'Get über power in one button click',
|
||||
author: 'Matt Development Group',
|
||||
email: 'contact@example.com',
|
||||
website: 'http://example.com'
|
||||
});
|
||||
|
||||
// Set up resources such as icons and launch screens.
|
||||
App.icons({
|
||||
'iphone': 'icons/icon-60.png',
|
||||
'iphone_2x': 'icons/icon-60@2x.png',
|
||||
// ... more screen sizes and platforms ...
|
||||
});
|
||||
|
||||
App.launchScreens({
|
||||
'iphone': 'splash/Default~iphone.png',
|
||||
'iphone_2x': 'splash/Default@2x~iphone.png',
|
||||
// ... more screen sizes and platforms ...
|
||||
});
|
||||
|
||||
// Set PhoneGap/Cordova preferences
|
||||
App.setPreference('BackgroundColor', '0xff0000ff');
|
||||
App.setPreference('HideKeyboardFormAccessoryBar', true);
|
||||
|
||||
// Pass preferences for a particular PhoneGap/Cordova plugin
|
||||
App.configurePlugin('com.phonegap.plugins.facebookconnect', {
|
||||
APP_ID: '1234567890',
|
||||
API_KEY: 'supersecretapikey'
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
{{> autoApiBox "App.info"}}
|
||||
{{> autoApiBox "App.setPreference"}}
|
||||
{{> autoApiBox "App.configurePlugin"}}
|
||||
{{> autoApiBox "App.icons"}}
|
||||
{{> autoApiBox "App.launchScreens"}}
|
||||
{{/template}}
|
||||
122
docs/client/api/packagejs.md
Normal file
122
docs/client/api/packagejs.md
Normal file
@@ -0,0 +1,122 @@
|
||||
{{#template name="api_packagejs"}}
|
||||
|
||||
<h2 id="packagejs"><span>Package.js</span></h2>
|
||||
|
||||
{{#markdown}} A package is a directory containing a package.js file, which
|
||||
contains roughly three major sections: a basic description, a package
|
||||
definition, and a test definition. By default, the directory name is the name of
|
||||
the package.
|
||||
|
||||
The `package.js` file below is an example of how to use the packaging API. The
|
||||
rest of this section will explain the specific API commands in greater detail.
|
||||
|
||||
|
||||
/* Information about this package */
|
||||
Package.describe({
|
||||
// Short two-sentence summary.
|
||||
summary: "What this does",
|
||||
// Version number.
|
||||
version: "1.0.0",
|
||||
// Optional. Default is package directory name.
|
||||
name: "username:package-name",
|
||||
// Optional github URL to your source repository.
|
||||
git: "https://github.com/something/something.git",
|
||||
});
|
||||
|
||||
/* This defines your actual package */
|
||||
Package.onUse(function (api) {
|
||||
// If no version is specified for an 'api.use' dependency, use the
|
||||
// one defined in Meteor 0.9.0.
|
||||
api.versionsFrom('0.9.0');
|
||||
// Use Underscore package, but only on the server.
|
||||
// Version not specified, so it will be as of Meteor 0.9.0.
|
||||
api.use('underscore', 'server');
|
||||
// Use application-configuration package, version 1.0.0 or newer.
|
||||
api.use('application-configuration@1.0.0');
|
||||
// Give users of this package access to the Templating package.
|
||||
api.imply('templating')
|
||||
// Export the object 'Email' to packages or apps that use this package.
|
||||
api.export('Email', 'server');
|
||||
// Specify the source code for the package.
|
||||
api.addFiles('email.js', 'server');
|
||||
});
|
||||
|
||||
/* This defines the tests for the package */
|
||||
Package.onTest(function (api) {
|
||||
// Sets up a dependency on this package
|
||||
api.use('username:package-name');
|
||||
// Allows you to use the 'tinytest' framework
|
||||
api.use('tinytest@1.0.0');
|
||||
// Specify the source code for the package tests
|
||||
api.addFiles('email_tests.js', 'server');
|
||||
});
|
||||
|
||||
/* This lets you use npm packages in your package*/
|
||||
Npm.depends({
|
||||
simplesmtp: "0.3.10",
|
||||
"stream-buffers": "0.2.5"});
|
||||
|
||||
Build plugins are created with `_transitional_registerBuildPlugin`, an API that is
|
||||
very much in flux. See the coffeescript package for an
|
||||
example. Build plugins are fully-fledged Meteor programs in their own right and
|
||||
have their own namespace, package dependencies, source files and npm
|
||||
requirements.
|
||||
|
||||
<h3 id="packagedescription"><span>Package Description</span></h3>
|
||||
|
||||
Provide basic package information with `Package.describe(options)`. To publish a
|
||||
package, you must define `summary` and `version`.
|
||||
|
||||
{{/markdown}}
|
||||
|
||||
{{> autoApiBox "Package.describe"}}
|
||||
|
||||
|
||||
<h3 id="packagedefinition"><span>Package Definition</span></h3>
|
||||
|
||||
{{#markdown}}
|
||||
Define dependencies and expose package methods with the
|
||||
`Package.onUse` handler. This section lets you define what packages your package
|
||||
depends on, what packages are implied by your package, and what object your
|
||||
package is exported to.
|
||||
{{/markdown}}
|
||||
|
||||
{{> autoApiBox "Package.onUse"}}
|
||||
|
||||
{{> autoApiBox "PackageAPI#versionsFrom" }}
|
||||
{{> autoApiBox "PackageAPI#use" }}
|
||||
{{> autoApiBox "PackageAPI#imply" }}
|
||||
{{> autoApiBox "PackageAPI#export" }}
|
||||
{{> autoApiBox "PackageAPI#addFiles" }}
|
||||
|
||||
<h3 id="packagetests"><span>Unit Tests</span></h3>
|
||||
|
||||
{{#markdown}}
|
||||
Set up your tests with the `Package.onTest` handler, which has an interface
|
||||
that's parallel to that of the `onUse` handler. The tests will need to depend on
|
||||
the package that you have just created. For example, if your package is the
|
||||
`email` package, you have to call `api.use('email')` in order to test the
|
||||
package.
|
||||
|
||||
If you used `meteor create` to set up your package, Meteor will create the
|
||||
required scaffolding in `package.js`, and you'll only need to add unit test code
|
||||
in the `_test.js` file that was created.
|
||||
{{/markdown}}
|
||||
|
||||
{{> autoApiBox "Package.onTest"}}
|
||||
|
||||
|
||||
<h3><span>External Packages and Plugins</span></h3>
|
||||
|
||||
{{#markdown}}
|
||||
Meteor packages can include NPM packages and Cordova plugins by using
|
||||
`Npm.depends` and `Cordova.depends` in the `package.js` file.
|
||||
{{/markdown}}
|
||||
|
||||
{{> autoApiBox "Npm.depends"}}
|
||||
{{> autoApiBox "Npm.require"}}
|
||||
{{> autoApiBox "Cordova.depends"}}
|
||||
{{> autoApiBox "Package.registerBuildPlugin"}}
|
||||
{{> autoApiBox "Plugin.registerSourceHandler"}}
|
||||
|
||||
{{/template}}
|
||||
148
docs/client/api/passwords.md
Normal file
148
docs/client/api/passwords.md
Normal file
@@ -0,0 +1,148 @@
|
||||
{{#template name="api_passwords"}}
|
||||
|
||||
<h2 id="accounts_passwords"><span>Passwords</span></h2>
|
||||
|
||||
The `accounts-password` package contains a full system for password-based
|
||||
authentication. In addition to the basic username and password-based
|
||||
sign-in process, it also supports email-based sign-in including
|
||||
address verification and password recovery emails.
|
||||
|
||||
The Meteor server stores passwords using the
|
||||
[bcrypt](http://en.wikipedia.org/wiki/Bcrypt) algorithm. This helps
|
||||
protect against embarrassing password leaks if the server's database is
|
||||
compromised.
|
||||
|
||||
To add password support to your application, run `$ meteor add
|
||||
accounts-password`. You can construct your own user interface using the
|
||||
functions below, or use the [`accounts-ui` package](#accountsui) to
|
||||
include a turn-key user interface for password-based sign-in.
|
||||
|
||||
|
||||
{{> autoApiBox "Accounts.createUser"}}
|
||||
|
||||
On the client, this function logs in as the newly created user on
|
||||
successful completion. On the server, it returns the newly created user
|
||||
id.
|
||||
|
||||
On the client, you must pass `password` and at least one of `username` or
|
||||
`email` — enough information for the user to be able to log in again
|
||||
later. On the server, you do not need to specify `password`, but the user will
|
||||
not be able to log in until it has a password (eg, set with
|
||||
[`Accounts.setPassword`](#accounts_setpassword)).
|
||||
|
||||
To create an account without a password on the server and still let the
|
||||
user pick their own password, call `createUser` with the `email` option
|
||||
and then
|
||||
call [`Accounts.sendEnrollmentEmail`](#accounts_sendenrollmentemail). This
|
||||
will send the user an email with a link to set their initial password.
|
||||
|
||||
By default the `profile` option is added directly to the new user document. To
|
||||
override this behavior, use [`Accounts.onCreateUser`](#accounts_oncreateuser).
|
||||
|
||||
This function is only used for creating users with passwords. The external
|
||||
service login flows do not use this function.
|
||||
|
||||
|
||||
{{> autoApiBox "Accounts.changePassword"}}
|
||||
|
||||
{{> autoApiBox "Accounts.forgotPassword"}}
|
||||
|
||||
This triggers a call
|
||||
to [`Accounts.sendResetPasswordEmail`](#accounts_sendresetpasswordemail)
|
||||
on the server. When the user visits the link in this email, the callback
|
||||
registered with [`Accounts.onResetPasswordLink`](#Accounts-onResetPasswordLink)
|
||||
will be called.
|
||||
|
||||
If you are using the [`accounts-ui` package](#accountsui), this is handled
|
||||
automatically. Otherwise, it is your responsiblity to prompt the user for the
|
||||
new password and call `resetPassword`.
|
||||
|
||||
{{> autoApiBox "Accounts.resetPassword"}}
|
||||
|
||||
This function accepts tokens passed into the callbacks registered with
|
||||
[`Accounts.onResetPasswordLink`](#Accounts-onResetPasswordLink) and
|
||||
[`Accounts.onEnrollmentLink`](#Accounts-onEnrollmentLink).
|
||||
|
||||
{{> autoApiBox "Accounts.setPassword"}}
|
||||
|
||||
{{> autoApiBox "Accounts.verifyEmail"}}
|
||||
|
||||
This function accepts tokens passed into the callback registered with
|
||||
[`Accounts.onEmailVerificationLink`](#Accounts-onEmailVerificationLink).
|
||||
|
||||
{{> autoApiBox "Accounts.sendResetPasswordEmail"}}
|
||||
|
||||
When the user visits the link in this email, the callback registered with
|
||||
[`Accounts.onResetPasswordLink`](#Accounts-onResetPasswordLink) will be called.
|
||||
|
||||
To customize the contents of the email, see
|
||||
[`Accounts.emailTemplates`](#accounts_emailtemplates).
|
||||
|
||||
{{> autoApiBox "Accounts.sendEnrollmentEmail"}}
|
||||
|
||||
When the user visits the link in this email, the callback registered with
|
||||
[`Accounts.onEnrollmentLink`](#Accounts-onEnrollmentLink) will be called.
|
||||
|
||||
To customize the contents of the email, see
|
||||
[`Accounts.emailTemplates`](#accounts_emailtemplates).
|
||||
|
||||
{{> autoApiBox "Accounts.sendVerificationEmail"}}
|
||||
|
||||
When the user visits the link in this email, the callback registered with
|
||||
[`Accounts.onEmailVerificationLink`](#Accounts-onEmailVerificationLink) will
|
||||
be called.
|
||||
|
||||
To customize the contents of the email, see
|
||||
[`Accounts.emailTemplates`](#accounts_emailtemplates).
|
||||
|
||||
|
||||
{{> autoApiBox "Accounts.onResetPasswordLink"}}
|
||||
|
||||
{{> autoApiBox "Accounts.onEnrollmentLink"}}
|
||||
|
||||
{{> autoApiBox "Accounts.onEmailVerificationLink"}}
|
||||
|
||||
|
||||
|
||||
|
||||
{{> autoApiBox "Accounts.emailTemplates"}}
|
||||
|
||||
This is an `Object` with several fields that are used to generate text/html
|
||||
for the emails sent by `sendResetPasswordEmail`, `sendEnrollmentEmail`,
|
||||
and `sendVerificationEmail`.
|
||||
|
||||
Override fields of the object by assigning to them:
|
||||
|
||||
- `from`: A `String` with an [RFC5322](http://tools.ietf.org/html/rfc5322) From
|
||||
address. By default, the email is sent from `no-reply@meteor.com`. If you
|
||||
wish to receive email from users asking for help with their account, be sure
|
||||
to set this to an email address that you can receive email at.
|
||||
- `siteName`: The public name of your application. Defaults to the DNS name of
|
||||
the application (eg: `awesome.meteor.com`).
|
||||
- `resetPassword`: An `Object` with two fields:
|
||||
- `resetPassword.subject`: A `Function` that takes a user object and returns
|
||||
a `String` for the subject line of a reset password email.
|
||||
- `resetPassword.text`: A `Function` that takes a user object and a url, and
|
||||
returns the body text for a reset password email.
|
||||
- `resetPassword.html`: An optional `Function` that takes a user object and a
|
||||
url, and returns the body html for a reset password email.
|
||||
- `enrollAccount`: Same as `resetPassword`, but for initial password setup for
|
||||
new accounts.
|
||||
- `verifyEmail`: Same as `resetPassword`, but for verifying the users email
|
||||
address.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
Accounts.emailTemplates.siteName = "AwesomeSite";
|
||||
Accounts.emailTemplates.from = "AwesomeSite Admin <accounts@example.com>";
|
||||
Accounts.emailTemplates.enrollAccount.subject = function (user) {
|
||||
return "Welcome to Awesome Town, " + user.profile.name;
|
||||
};
|
||||
Accounts.emailTemplates.enrollAccount.text = function (user, url) {
|
||||
return "You have been selected to participate in building a better future!"
|
||||
+ " To activate your account, simply click the link below:\n\n"
|
||||
+ url;
|
||||
};
|
||||
|
||||
{{/template}}
|
||||
221
docs/client/api/pubsub.md
Normal file
221
docs/client/api/pubsub.md
Normal file
@@ -0,0 +1,221 @@
|
||||
{{#template name="api_pubsub"}}
|
||||
|
||||
<h2 id="publishandsubscribe"><span>Publish and subscribe</span></h2>
|
||||
|
||||
These functions control how Meteor servers publish sets of records and
|
||||
how clients can subscribe to those sets.
|
||||
|
||||
{{> autoApiBox "Meteor.publish"}}
|
||||
|
||||
To publish records to clients, call `Meteor.publish` on the server with
|
||||
two parameters: the name of the record set, and a *publish function*
|
||||
that Meteor will call each time a client subscribes to the name.
|
||||
|
||||
Publish functions can return a
|
||||
[`Collection.Cursor`](#mongo_cursor), in which case Meteor
|
||||
will publish that cursor's documents to each subscribed client. You can
|
||||
also return an array of `Collection.Cursor`s, in which case Meteor will
|
||||
publish all of the cursors.
|
||||
|
||||
{{#warning}}
|
||||
If you return multiple cursors in an array, they currently must all be from
|
||||
different collections. We hope to lift this restriction in a future release.
|
||||
{{/warning}}
|
||||
|
||||
// server: publish the rooms collection, minus secret info.
|
||||
Meteor.publish("rooms", function () {
|
||||
return Rooms.find({}, {fields: {secretInfo: 0}});
|
||||
});
|
||||
|
||||
// ... and publish secret info for rooms where the logged-in user
|
||||
// is an admin. If the client subscribes to both streams, the records
|
||||
// are merged together into the same documents in the Rooms collection.
|
||||
Meteor.publish("adminSecretInfo", function () {
|
||||
return Rooms.find({admin: this.userId}, {fields: {secretInfo: 1}});
|
||||
});
|
||||
|
||||
// publish dependent documents and simulate joins
|
||||
Meteor.publish("roomAndMessages", function (roomId) {
|
||||
check(roomId, String);
|
||||
return [
|
||||
Rooms.find({_id: roomId}, {fields: {secretInfo: 0}}),
|
||||
Messages.find({roomId: roomId})
|
||||
];
|
||||
});
|
||||
|
||||
Alternatively, a publish function can directly control its published record set
|
||||
by calling the functions [`added`](#publish_added) (to add a new document to the
|
||||
published record set), [`changed`](#publish_changed) (to change or clear some
|
||||
fields on a document already in the published record set), and
|
||||
[`removed`](#publish_removed) (to remove documents from the published record
|
||||
set). These methods are provided by `this` in your publish function.
|
||||
|
||||
If a publish function does not return a cursor or array of cursors, it is
|
||||
assumed to be using the low-level `added`/`changed`/`removed` interface, and it
|
||||
**must also call [`ready`](#publish_ready) once the initial record set is
|
||||
complete**.
|
||||
|
||||
Example:
|
||||
|
||||
// server: publish the current size of a collection
|
||||
Meteor.publish("counts-by-room", function (roomId) {
|
||||
var self = this;
|
||||
check(roomId, String);
|
||||
var count = 0;
|
||||
var initializing = true;
|
||||
|
||||
// observeChanges only returns after the initial `added` callbacks
|
||||
// have run. Until then, we don't want to send a lot of
|
||||
// `self.changed()` messages - hence tracking the
|
||||
// `initializing` state.
|
||||
var handle = Messages.find({roomId: roomId}).observeChanges({
|
||||
added: function (id) {
|
||||
count++;
|
||||
if (!initializing)
|
||||
self.changed("counts", roomId, {count: count});
|
||||
},
|
||||
removed: function (id) {
|
||||
count--;
|
||||
self.changed("counts", roomId, {count: count});
|
||||
}
|
||||
// don't care about changed
|
||||
});
|
||||
|
||||
// Instead, we'll send one `self.added()` message right after
|
||||
// observeChanges has returned, and mark the subscription as
|
||||
// ready.
|
||||
initializing = false;
|
||||
self.added("counts", roomId, {count: count});
|
||||
self.ready();
|
||||
|
||||
// Stop observing the cursor when client unsubs.
|
||||
// Stopping a subscription automatically takes
|
||||
// care of sending the client any removed messages.
|
||||
self.onStop(function () {
|
||||
handle.stop();
|
||||
});
|
||||
});
|
||||
|
||||
// client: declare collection to hold count object
|
||||
Counts = new Mongo.Collection("counts");
|
||||
|
||||
// client: subscribe to the count for the current room
|
||||
Tracker.autorun(function () {
|
||||
Meteor.subscribe("counts-by-room", Session.get("roomId"));
|
||||
});
|
||||
|
||||
// client: use the new collection
|
||||
console.log("Current room has " +
|
||||
Counts.findOne(Session.get("roomId")).count +
|
||||
" messages.");
|
||||
|
||||
// server: sometimes publish a query, sometimes publish nothing
|
||||
Meteor.publish("secretData", function () {
|
||||
if (this.userId === 'superuser') {
|
||||
return SecretData.find();
|
||||
} else {
|
||||
// Declare that no data is being published. If you leave this line
|
||||
// out, Meteor will never consider the subscription ready because
|
||||
// it thinks you're using the added/changed/removed interface where
|
||||
// you have to explicitly call this.ready().
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
Since publish functions usually expect particular types as arguments,
|
||||
use [`check`](#check) liberally to ensure the arguments have
|
||||
the correct [types and structure](#matchpatterns).
|
||||
|
||||
{{#warning}}
|
||||
Meteor will emit a warning message if you call `Meteor.publish` in a
|
||||
project that includes the `autopublish` package. Your publish function
|
||||
will still work.
|
||||
{{/warning}}
|
||||
|
||||
{{> autoApiBox "Subscription#userId"}}
|
||||
|
||||
This is constant. However, if the logged-in user changes, the publish
|
||||
function is rerun with the new value.
|
||||
|
||||
{{> autoApiBox "Subscription#added"}}
|
||||
{{> autoApiBox "Subscription#changed"}}
|
||||
{{> autoApiBox "Subscription#removed"}}
|
||||
{{> autoApiBox "Subscription#ready"}}
|
||||
{{> autoApiBox "Subscription#onStop"}}
|
||||
|
||||
If you call [`observe`](#observe) or [`observeChanges`](#observe_changes) in your
|
||||
publish handler, this is the place to stop the observes.
|
||||
|
||||
{{> autoApiBox "Subscription#error"}}
|
||||
{{> autoApiBox "Subscription#stop"}}
|
||||
{{> autoApiBox "Subscription#connection"}}
|
||||
|
||||
{{> autoApiBox "Meteor.subscribe"}}
|
||||
|
||||
When you subscribe to a record set, it tells the server to send records to the
|
||||
client. The client stores these records in local [Minimongo
|
||||
collections](#mongo_collection), with the same name as the `collection`
|
||||
argument used in the publish handler's [`added`](#publish_added),
|
||||
[`changed`](#publish_changed), and [`removed`](#publish_removed)
|
||||
callbacks. Meteor will queue incoming records until you declare the
|
||||
[`Mongo.Collection`](#mongo_collection) on the client with the matching
|
||||
collection name.
|
||||
|
||||
// okay to subscribe (and possibly receive data) before declaring
|
||||
// the client collection that will hold it. assume "allplayers"
|
||||
// publishes data from server's "players" collection.
|
||||
Meteor.subscribe("allplayers");
|
||||
...
|
||||
// client queues incoming players records until ...
|
||||
...
|
||||
Players = new Mongo.Collection("players");
|
||||
|
||||
The client will see a document if the document is currently in the published
|
||||
record set of any of its subscriptions.
|
||||
|
||||
The `onReady` callback is called with no arguments when the server
|
||||
[marks the subscription as ready](#publish_ready). The `onError` callback is
|
||||
called with a [`Meteor.Error`](#meteor_error) if the subscription fails or is
|
||||
terminated by the server.
|
||||
|
||||
`Meteor.subscribe` returns a subscription handle, which is an object with the
|
||||
following methods:
|
||||
|
||||
<dl class="callbacks">
|
||||
{{#dtdd "stop()"}}
|
||||
Cancel the subscription. This will typically result in the server directing the
|
||||
client to remove the subscription's data from the client's cache.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "ready()"}}
|
||||
True if the server has [marked the subscription as ready](#publish_ready). A
|
||||
reactive data source.
|
||||
{{/dtdd}}
|
||||
</dl>
|
||||
|
||||
If you call `Meteor.subscribe` within a [reactive computation](#reactivity),
|
||||
for example using
|
||||
[`Tracker.autorun`](#tracker_autorun), the subscription will automatically be
|
||||
cancelled when the computation is invalidated or stopped; it's not necessary
|
||||
to call `stop` on
|
||||
subscriptions made from inside `autorun`. However, if the next iteration
|
||||
of your run function subscribes to the same record set (same name and
|
||||
parameters), Meteor is smart enough to skip a wasteful
|
||||
unsubscribe/resubscribe. For example:
|
||||
|
||||
Tracker.autorun(function () {
|
||||
Meteor.subscribe("chat", {room: Session.get("current-room")});
|
||||
Meteor.subscribe("privateMessages");
|
||||
});
|
||||
|
||||
This subscribes you to the chat messages in the current room and to your private
|
||||
messages. When you change rooms by calling `Session.set("current-room",
|
||||
"new-room")`, Meteor will subscribe to the new room's chat messages,
|
||||
unsubscribe from the original room's chat messages, and continue to
|
||||
stay subscribed to your private messages.
|
||||
|
||||
If more than one subscription sends conflicting values for a field (same
|
||||
collection name, document ID, and field name), then the value on the client will
|
||||
be one of the published values, chosen arbitrarily.
|
||||
|
||||
{{/template}}
|
||||
41
docs/client/api/reactive-var.md
Normal file
41
docs/client/api/reactive-var.md
Normal file
@@ -0,0 +1,41 @@
|
||||
{{#template name="api_reactive_var"}}
|
||||
|
||||
|
||||
<h2 id="reactivevar_pkg"><span>ReactiveVar</span></h2>
|
||||
|
||||
To use `ReactiveVar`, add the `reactive-var` package to your project with
|
||||
`$ meteor add reactive-var`.
|
||||
|
||||
{{> autoApiBox "ReactiveVar"}}
|
||||
|
||||
A ReactiveVar holds a single value that can be get and set, such that calling
|
||||
`set` will invalidate any Computations that called `get`, according to the
|
||||
usual contract for reactive data sources.
|
||||
|
||||
A ReactiveVar is similar to a Session variable, with a few differences:
|
||||
|
||||
* ReactiveVars don't have global names, like the "foo" in `Session.get("foo")`.
|
||||
Instead, they may be created and used locally, for example attached to a
|
||||
template instance, as in: `this.foo.get()`.
|
||||
|
||||
* ReactiveVars are not automatically migrated across hot code pushes,
|
||||
whereas Session state is.
|
||||
|
||||
* ReactiveVars can hold any value, while Session variables are limited to
|
||||
JSON or EJSON.
|
||||
|
||||
An important property of ReactiveVars — which is sometimes a
|
||||
reason for using one — is that setting the value to the same
|
||||
value as before has no effect; it does not trigger any invalidations.
|
||||
So if one autorun sets a ReactiveVar, and another autorun gets the
|
||||
ReactiveVar, a re-run of the first autorun won't necessarily trigger
|
||||
the second. By default, only primitive values are compared this way,
|
||||
while calling `set` on an argument that is an *object* (not a
|
||||
primitive) always counts as a change. You can configure this behavior
|
||||
using the `equalsFunc` argument.
|
||||
|
||||
{{> autoApiBox "ReactiveVar#get"}}
|
||||
|
||||
{{> autoApiBox "ReactiveVar#set"}}
|
||||
|
||||
{{/template}}
|
||||
112
docs/client/api/session.md
Normal file
112
docs/client/api/session.md
Normal file
@@ -0,0 +1,112 @@
|
||||
{{#template name="api_session"}}
|
||||
|
||||
|
||||
<h2 id="session"><span>Session</span></h2>
|
||||
|
||||
`Session` provides a global object on the client that you can use to
|
||||
store an arbitrary set of key-value pairs. Use it to store things like
|
||||
the currently selected item in a list.
|
||||
|
||||
What's special about `Session` is that it's reactive. If
|
||||
you call [`Session.get`](#session_get)`("currentList")`
|
||||
from inside a template, the template will automatically be rerendered
|
||||
whenever [`Session.set`](#session_set)`("currentList", x)` is called.
|
||||
|
||||
{{> autoApiBox "Session.set"}}
|
||||
|
||||
Example:
|
||||
|
||||
Tracker.autorun(function () {
|
||||
Meteor.subscribe("chat-history", {room: Session.get("currentRoomId")});
|
||||
});
|
||||
|
||||
// Causes the function passed to Tracker.autorun to be re-run, so
|
||||
// that the chat-history subscription is moved to the room "home".
|
||||
Session.set("currentRoomId", "home");
|
||||
|
||||
{{> autoApiBox "Session.setDefault"}}
|
||||
|
||||
This is useful in initialization code, to avoid re-initializing a session
|
||||
variable every time a new version of your app is loaded.
|
||||
|
||||
{{> autoApiBox "Session.get"}}
|
||||
|
||||
Example:
|
||||
|
||||
// in main.html
|
||||
{{lt}}template name="main">
|
||||
<p>We've always been at war with {{dstache}}theEnemy}}.</p>
|
||||
{{lt}}/template>
|
||||
|
||||
// in main.js
|
||||
Template.main.helpers({
|
||||
theEnemy: function () {
|
||||
return Session.get("enemy");
|
||||
}
|
||||
});
|
||||
|
||||
Session.set("enemy", "Eastasia");
|
||||
// Page will say "We've always been at war with Eastasia"
|
||||
|
||||
Session.set("enemy", "Eurasia");
|
||||
// Page will change to say "We've always been at war with Eurasia"
|
||||
|
||||
|
||||
{{> autoApiBox "Session.equals"}}
|
||||
|
||||
If value is a scalar, then these two expressions do the same thing:
|
||||
|
||||
(1) Session.get("key") === value
|
||||
(2) Session.equals("key", value)
|
||||
|
||||
... but the second one is always better. It triggers fewer invalidations
|
||||
(template redraws), making your program more efficient.
|
||||
|
||||
Example:
|
||||
|
||||
{{lt}}template name="postsView">
|
||||
{{dstache}}! Show a dynamically updating list of items. Let the user click on an
|
||||
item to select it. The selected item is given a CSS class so it
|
||||
can be rendered differently. }}
|
||||
|
||||
{{dstache}}#each posts}}
|
||||
{{dstache}}> postItem }}
|
||||
{{dstache}}/each}}
|
||||
{{lt}}/template>
|
||||
|
||||
{{lt}}template name="postItem">
|
||||
<div class="{{dstache}}postClass}}">{{dstache}}title}}</div>
|
||||
{{lt}}/template>
|
||||
|
||||
///// in JS file
|
||||
Template.postsView.helpers({
|
||||
posts: function() {
|
||||
return Posts.find();
|
||||
}
|
||||
});
|
||||
|
||||
Template.postItem.helpers({
|
||||
postClass: function() {
|
||||
return Session.equals("selectedPost", this._id) ?
|
||||
"selected" : "";
|
||||
}
|
||||
});
|
||||
|
||||
Template.postItem.events({
|
||||
'click': function() {
|
||||
Session.set("selectedPost", this._id);
|
||||
}
|
||||
});
|
||||
|
||||
// Using Session.equals here means that when the user clicks
|
||||
// on an item and changes the selection, only the newly selected
|
||||
// and the newly unselected items are re-rendered.
|
||||
//
|
||||
// If Session.get had been used instead of Session.equals, then
|
||||
// when the selection changed, all the items would be re-rendered.
|
||||
|
||||
For object and array session values, you cannot use `Session.equals`; instead,
|
||||
you need to use the `underscore` package and write
|
||||
`_.isEqual(Session.get(key), value)`.
|
||||
|
||||
{{/template}}
|
||||
364
docs/client/api/templates.md
Normal file
364
docs/client/api/templates.md
Normal file
@@ -0,0 +1,364 @@
|
||||
{{#template name="api_templates"}}
|
||||
|
||||
|
||||
<h2 id="templates_api"><span>Templates</span></h2>
|
||||
|
||||
|
||||
When you write a template as `<{{! }}template name="foo"> ... <{{!
|
||||
}}/template>` in an HTML file in your app, Meteor generates a
|
||||
"template object" named `Template.foo`.
|
||||
|
||||
The same template may occur many times on a page, and these
|
||||
occurrences are called template instances. Template instances have a
|
||||
life cycle of being created, put into the document, and later taken
|
||||
out of the document and destroyed. Meteor manages these stages for
|
||||
you, including determining when a template instance has been removed
|
||||
or replaced and should be cleaned up. You can associate data with a
|
||||
template instance, and you can access its DOM nodes when it is in the
|
||||
document.
|
||||
|
||||
{{> autoApiBox "Template#events"}}
|
||||
|
||||
Declare event handlers for instances of this template. Multiple calls add
|
||||
new event handlers in addition to the existing ones.
|
||||
|
||||
See [Event Maps](#eventmaps) for a detailed description of the event
|
||||
map format and how event handling works in Meteor.
|
||||
|
||||
{{> autoApiBox "Template#helpers"}}
|
||||
|
||||
Each template has a local dictionary of helpers that are made available to it,
|
||||
and this call specifies helpers to add to the template's dictionary.
|
||||
|
||||
Example:
|
||||
|
||||
Template.myTemplate.helpers({
|
||||
foo: function () {
|
||||
return Session.get("foo");
|
||||
}
|
||||
});
|
||||
|
||||
Now you can invoke this helper with `{{dstache}}foo}}` in the template defined
|
||||
with `<{{! }}template name="myTemplate">`.
|
||||
|
||||
To create a helper that can be used in any template, use
|
||||
[`Template.registerHelper`](#template_registerhelper).
|
||||
|
||||
|
||||
{{> autoApiBox "Template#rendered"}}
|
||||
|
||||
This callback is called once when an instance of Template.*myTemplate* is
|
||||
rendered into DOM nodes and put into the document for the first time.
|
||||
|
||||
In the body of the callback, `this` is a [template
|
||||
instance](#template_inst) object that is unique to this occurrence of
|
||||
the template and persists across re-renderings. Use the `created` and
|
||||
`destroyed` callbacks to perform initialization or clean-up on the
|
||||
object.
|
||||
|
||||
Because your template has been rendered, you can use functions like
|
||||
[`this.findAll`](#template_findAll) which look at its DOM nodes.
|
||||
|
||||
{{> autoApiBox "Template#created"}}
|
||||
|
||||
This callback is called before your template's logic is evaluated for the first
|
||||
time. Inside the callback, `this` is the new [template
|
||||
instance](#template_inst) object. Properties you set on this object will be
|
||||
visible from the `rendered` and `destroyed` callbacks and from event handlers.
|
||||
|
||||
This callback fires once and is the first callback to fire. Every
|
||||
`created` has a corresponding `destroyed`; that is, if you get a
|
||||
`created` callback with a certain template instance object in `this`,
|
||||
you will eventually get a `destroyed` callback for the same object.
|
||||
|
||||
`created` is a useful way to set up values on template instance that are
|
||||
read from template helpers using `Template.instance()`.
|
||||
|
||||
{{> autoApiBox "Template#destroyed"}}
|
||||
|
||||
This callback is called when an occurrence of a template is taken off
|
||||
the page for any reason and not replaced with a re-rendering. Inside
|
||||
the callback, `this` is the [template instance](#template_inst) object
|
||||
being destroyed.
|
||||
|
||||
This callback is most useful for cleaning up or undoing any external effects of
|
||||
`created` or `rendered`. It fires once and is the last callback to fire.
|
||||
|
||||
|
||||
<h2 id="template_inst"><span>Template instances</span></h2>
|
||||
|
||||
A template instance object represents an occurrence of a template in
|
||||
the document. It can be used to access the DOM and it can be
|
||||
assigned properties that persist as the template is reactively updated.
|
||||
|
||||
Template instance objects are found as the value of `this` in the
|
||||
`created`, `rendered`, and `destroyed` template callbacks, and as an
|
||||
argument to event handlers. You can access the current template instance
|
||||
from helpers using [`Template.instance()`](#template_instance).
|
||||
|
||||
In addition to the properties and functions described below, you can assign
|
||||
additional properties of your choice to the object. Use the
|
||||
[`created`](#template_created) and [`destroyed`](#template_destroyed) callbacks
|
||||
to perform initialization or clean-up on the object.
|
||||
|
||||
You can only access `findAll`, `find`, `firstNode`, and `lastNode`
|
||||
from the `rendered` callback and event handlers, not from `created`
|
||||
and `destroyed`, because they require the template instance to be
|
||||
in the DOM.
|
||||
|
||||
Template instance objects are `instanceof Blaze.TemplateInstance`.
|
||||
|
||||
{{> autoApiBox "Blaze.TemplateInstance#findAll"}}
|
||||
|
||||
`template.findAll` returns an array of DOM elements matching `selector`.
|
||||
|
||||
{{> autoApiBox "Blaze.TemplateInstance#$"}}
|
||||
|
||||
`template.$` returns a [jQuery object](http://api.jquery.com/Types/#jQuery) of
|
||||
those same elements. jQuery objects are similar to arrays, with
|
||||
additional methods defined by the jQuery library.
|
||||
|
||||
The template instance serves as the document root for the selector. Only
|
||||
elements inside the template and its sub-templates can match parts of
|
||||
the selector.
|
||||
|
||||
{{> autoApiBox "Blaze.TemplateInstance#find"}}
|
||||
|
||||
Returns one DOM element matching `selector`, or `null` if there are no
|
||||
such elements.
|
||||
|
||||
The template instance serves as the document root for the selector. Only
|
||||
elements inside the template and its sub-templates can match parts of
|
||||
the selector.
|
||||
|
||||
{{> autoApiBox "Blaze.TemplateInstance#firstNode"}}
|
||||
|
||||
The two nodes `firstNode` and `lastNode` indicate the extent of the
|
||||
rendered template in the DOM. The rendered template includes these
|
||||
nodes, their intervening siblings, and their descendents. These two
|
||||
nodes are siblings (they have the same parent), and `lastNode` comes
|
||||
after `firstNode`, or else they are the same node.
|
||||
|
||||
{{> autoApiBox "Blaze.TemplateInstance#lastNode"}}
|
||||
|
||||
{{> autoApiBox "Blaze.TemplateInstance#data"}}
|
||||
|
||||
This property provides access to the data context at the top level of
|
||||
the template. It is updated each time the template is re-rendered.
|
||||
Access is read-only and non-reactive.
|
||||
|
||||
{{> autoApiBox "Blaze.TemplateInstance#autorun"}}
|
||||
|
||||
You can use `this.autorun` from a [`created`](#template_created) or
|
||||
[`rendered`](#template_rendered) callback to reactively update the DOM
|
||||
or the template instance. The Computation is automatically stopped
|
||||
when the template is destroyed.
|
||||
|
||||
Alias for `template.view.autorun`.
|
||||
|
||||
{{> autoApiBox "Blaze.TemplateInstance#view"}}
|
||||
|
||||
{{> autoApiBox "Template.registerHelper"}}
|
||||
|
||||
{{> autoApiBox "Template.instance"}}
|
||||
|
||||
{{> autoApiBox "Template.currentData"}}
|
||||
|
||||
{{> autoApiBox "Template.parentData"}}
|
||||
|
||||
For example, `Template.parentData(0)` is equivalent to `Template.currentData()`. `Template.parentData(2)`
|
||||
is equivalent to `{{dstache}}../..}}` in a template.
|
||||
|
||||
{{> autoApiBox "Template.body"}}
|
||||
|
||||
You can define helpers and event maps on `Template.body` just like on
|
||||
any `Template.myTemplate` object.
|
||||
|
||||
Helpers on `Template.body` are only available in the `<body>` tags of
|
||||
your app. To register a global helper, use
|
||||
[Template.registerHelper](#template_registerhelper).
|
||||
Event maps on `Template.body` don't apply to elements added to the
|
||||
|
||||
body via `Blaze.render`, jQuery, or the DOM API, or to the body element
|
||||
itself. To handle events on the body, window, or document, use jQuery
|
||||
or the DOM API.
|
||||
|
||||
{{> autoApiBox "Template.dynamic"}}
|
||||
|
||||
`Template.dynamic` allows you to include a template by name, where the name
|
||||
may be calculated by a helper and may change reactively. The `data`
|
||||
argument is optional, and if it is omitted, the current data context
|
||||
is used.
|
||||
|
||||
For example, if there is a template named "foo", `{{dstache}}> Template.dynamic
|
||||
template="foo"}}` is equivalent to `{{dstache}}> foo}}`.
|
||||
|
||||
{{> apiBoxTitle name="Event Maps" id="eventmaps"}}
|
||||
|
||||
An event map is an object where
|
||||
the properties specify a set of events to handle, and the values are
|
||||
the handlers for those events. The property can be in one of several
|
||||
forms:
|
||||
|
||||
<dl>
|
||||
{{#dtdd "<em>eventtype</em>"}}
|
||||
Matches a particular type of event, such as 'click'.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "<em>eventtype selector</em>"}}
|
||||
Matches a particular type of event, but only when it appears on
|
||||
an element that matches a certain CSS selector.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "<em>event1, event2</em>"}}
|
||||
To handle more than one type of event with the same function, use a
|
||||
comma-separated list.
|
||||
{{/dtdd}}
|
||||
</dl>
|
||||
|
||||
The handler function receives two arguments: `event`, an object with
|
||||
information about the event, and `template`, a [template
|
||||
instance](#template_inst) for the template where the handler is
|
||||
defined. The handler also receives some additional context data in
|
||||
`this`, depending on the context of the current element handling the
|
||||
event. In a template, an element's context is the
|
||||
data context where that element occurs, which is set by
|
||||
block helpers such as `#with` and `#each`.
|
||||
|
||||
Example:
|
||||
|
||||
{
|
||||
// Fires when any element is clicked
|
||||
'click': function (event) { ... },
|
||||
|
||||
// Fires when any element with the 'accept' class is clicked
|
||||
'click .accept': function (event) { ... },
|
||||
|
||||
// Fires when 'accept' is clicked or focused, or a key is pressed
|
||||
'click .accept, focus .accept, keypress': function (event) { ... }
|
||||
}
|
||||
|
||||
Most events bubble up the document tree from their originating
|
||||
element. For example, `'click p'` catches a click anywhere in a
|
||||
paragraph, even if the click originated on a link, span, or some other
|
||||
element inside the paragraph. The originating element of the event
|
||||
is available as the `target` property, while the element that matched
|
||||
the selector and is currently handling it is called `currentTarget`.
|
||||
|
||||
{
|
||||
'click p': function (event) {
|
||||
var paragraph = event.currentTarget; // always a P
|
||||
var clickedElement = event.target; // could be the P or a child element
|
||||
}
|
||||
}
|
||||
|
||||
If a selector matches multiple elements that an event bubbles to, it
|
||||
will be called multiple times, for example in the case of `'click
|
||||
div'` or `'click *'`. If no selector is given, the handler
|
||||
will only be called once, on the original target element.
|
||||
|
||||
The following properties and methods are available on the event object
|
||||
passed to handlers:
|
||||
|
||||
<dl class="objdesc">
|
||||
{{#dtdd name="type" type="String"}}
|
||||
The event's type, such as "click", "blur" or "keypress".
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="target" type="DOM Element"}}
|
||||
The element that originated the event.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="currentTarget" type="DOM Element"}}
|
||||
The element currently handling the event. This is the element that
|
||||
matched the selector in the event map. For events that bubble, it may
|
||||
be `target` or an ancestor of `target`, and its value changes as the
|
||||
event bubbles.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd name="which" type="Number"}}
|
||||
For mouse events, the number of the mouse button (1=left, 2=middle, 3=right).
|
||||
For key events, a character or key code.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "stopPropagation()"}}
|
||||
Prevent the event from propagating (bubbling) up to other elements.
|
||||
Other event handlers matching the same element are still fired, in
|
||||
this and other event maps.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "stopImmediatePropagation()"}}
|
||||
Prevent all additional event handlers from being run on this event,
|
||||
including other handlers in this event map, handlers reached by
|
||||
bubbling, and handlers in other event maps.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "preventDefault()"}}
|
||||
Prevents the action the browser would normally take in response to this
|
||||
event, such as following a link or submitting a form. Further handlers
|
||||
are still called, but cannot reverse the effect.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "isPropagationStopped()"}}
|
||||
Returns whether `stopPropagation()` has been called for this event.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "isImmediatePropagationStopped()"}}
|
||||
Returns whether `stopImmediatePropagation()` has been called for this event.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "isDefaultPrevented()"}}
|
||||
Returns whether `preventDefault()` has been called for this event.
|
||||
{{/dtdd}}
|
||||
</dl>
|
||||
|
||||
Returning `false` from a handler is the same as calling
|
||||
both `stopImmediatePropagation` and `preventDefault` on the event.
|
||||
|
||||
Event types and their uses include:
|
||||
|
||||
<dl class="objdesc">
|
||||
{{#dtdd "<code>click</code>"}}
|
||||
Mouse click on any element, including a link, button, form control, or div.
|
||||
Use `preventDefault()` to prevent a clicked link from being followed.
|
||||
Some ways of activating an element from the keyboard also fire `click`.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "<code>dblclick</code>"}}
|
||||
Double-click.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "<code>focus, blur</code>"}}
|
||||
A text input field or other form control gains or loses focus. You
|
||||
can make any element focusable by giving it a `tabindex` property.
|
||||
Browsers differ on whether links, checkboxes, and radio buttons are
|
||||
natively focusable. These events do not bubble.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "<code>change</code>"}}
|
||||
A checkbox or radio button changes state. For text fields, use
|
||||
`blur` or key events to respond to changes.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "<code>mouseenter, mouseleave</code>"}} The pointer enters or
|
||||
leaves the bounds of an element. These events do not bubble.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "<code>mousedown, mouseup</code>"}}
|
||||
The mouse button is newly down or up.
|
||||
{{/dtdd}}
|
||||
|
||||
{{#dtdd "<code>keydown, keypress, keyup</code>"}}
|
||||
The user presses a keyboard key. `keypress` is most useful for
|
||||
catching typing in text fields, while `keydown` and `keyup` can be
|
||||
used for arrow keys or modifier keys.
|
||||
{{/dtdd}}
|
||||
|
||||
</dl>
|
||||
|
||||
Other DOM events are available as well, but for the events above,
|
||||
Meteor has taken some care to ensure that they work uniformly in all
|
||||
browsers.
|
||||
|
||||
|
||||
{{/template}}
|
||||
25
docs/client/api/timers.md
Normal file
25
docs/client/api/timers.md
Normal file
@@ -0,0 +1,25 @@
|
||||
{{#template name="api_timers"}}
|
||||
<h2 id="timers"><span>Timers</span></h2>
|
||||
|
||||
Meteor uses global environment variables
|
||||
to keep track of things like the current request's user. To make sure
|
||||
these variables have the right values, you need to use
|
||||
`Meteor.setTimeout` instead of `setTimeout` and `Meteor.setInterval`
|
||||
instead of `setInterval`.
|
||||
|
||||
These functions work just like their native JavaScript equivalents.
|
||||
If you call the native function, you'll get an error stating that Meteor
|
||||
code must always run within a Fiber, and advising to use
|
||||
`Meteor.bindEnvironment`.
|
||||
|
||||
{{> autoApiBox "Meteor.setTimeout"}}
|
||||
|
||||
Returns a handle that can be used by `Meteor.clearTimeout`.
|
||||
|
||||
{{> autoApiBox "Meteor.setInterval"}}
|
||||
|
||||
Returns a handle that can be used by `Meteor.clearInterval`.
|
||||
|
||||
{{> autoApiBox "Meteor.clearTimeout"}}
|
||||
{{> autoApiBox "Meteor.clearInterval"}}
|
||||
{{/template}}
|
||||
313
docs/client/api/tracker.md
Normal file
313
docs/client/api/tracker.md
Normal file
@@ -0,0 +1,313 @@
|
||||
{{#template name="api_tracker"}}
|
||||
|
||||
<h2 id="tracker"><span>Tracker</span></h2>
|
||||
|
||||
Meteor has a simple dependency tracking system which allows it to
|
||||
automatically rerun templates and other computations whenever
|
||||
[`Session`](#session) variables, database queries, and other data
|
||||
sources change.
|
||||
|
||||
Unlike most other systems, you don't have to manually declare these
|
||||
dependencies — it "just works". The mechanism is simple and
|
||||
efficient. When you call a function that supports reactive updates
|
||||
(such as a database query), it automatically saves the current
|
||||
Computation object, if any (representing, for example, the current
|
||||
template being rendered). Later, when the data changes, the function
|
||||
can "invalidate" the Computation, causing it to rerun (rerendering the
|
||||
template).
|
||||
|
||||
Applications will find [`Tracker.autorun`](#tracker_autorun) useful, while more
|
||||
advanced facilities such as `Tracker.Dependency` and `onInvalidate`
|
||||
callbacks are intended primarily for package authors implementing new
|
||||
reactive data sources.
|
||||
|
||||
To learn more about how Tracker works and to explore advanced ways to use it,
|
||||
visit the <a href="http://manual.meteor.com/#tracker"> Tracker</a> chapter in the
|
||||
<a href="http://manual.meteor.com/">Meteor Manual</a>, which describes it in
|
||||
complete detail.
|
||||
|
||||
{{> autoApiBox "Tracker.autorun" }}
|
||||
|
||||
`Tracker.autorun` allows you to run a function that depends on reactive data
|
||||
sources, in such a way that if there are changes to the data later,
|
||||
the function will be rerun.
|
||||
|
||||
For example, you can monitor a cursor (which is a reactive data
|
||||
source) and aggregate it into a session variable:
|
||||
|
||||
Tracker.autorun(function () {
|
||||
var oldest = _.max(Monkeys.find().fetch(), function (monkey) {
|
||||
return monkey.age;
|
||||
});
|
||||
if (oldest)
|
||||
Session.set("oldest", oldest.name);
|
||||
});
|
||||
|
||||
Or you can wait for a session variable to have a certain value, and do
|
||||
something the first time it does, calling `stop` on the computation to
|
||||
prevent further rerunning:
|
||||
|
||||
Tracker.autorun(function (c) {
|
||||
if (! Session.equals("shouldAlert", true))
|
||||
return;
|
||||
|
||||
c.stop();
|
||||
alert("Oh no!");
|
||||
});
|
||||
|
||||
The function is invoked immediately, at which point it may alert and
|
||||
stop right away if `shouldAlert` is already true. If not, the
|
||||
function is run again when `shouldAlert` becomes true.
|
||||
|
||||
A change to a data dependency does not cause an immediate rerun, but
|
||||
rather "invalidates" the computation, causing it to rerun the next
|
||||
time a flush occurs. A flush will occur automatically as soon as
|
||||
the system is idle if there are invalidated computations. You can
|
||||
also use [`Tracker.flush`](#tracker_flush) to cause an immediate flush of
|
||||
all pending reruns.
|
||||
|
||||
If you nest calls to `Tracker.autorun`, then when the outer call stops or
|
||||
reruns, the inner call will stop automatically. Subscriptions and
|
||||
observers are also automatically stopped when used as part of a
|
||||
computation that is rerun, allowing new ones to be established. See
|
||||
[`Meteor.subscribe`](#meteor_subscribe) for more information about
|
||||
subscriptions and reactivity.
|
||||
|
||||
If the initial run of an autorun throws an exception, the computation
|
||||
is automatically stopped and won't be rerun.
|
||||
|
||||
{{> autoApiBox "Tracker.flush" }}
|
||||
|
||||
Normally, when you make changes (like writing to the database),
|
||||
their impact (like updating the DOM) is delayed until the system is
|
||||
idle. This keeps things predictable — you can know that the DOM
|
||||
won't go changing out from under your code as it runs. It's also one
|
||||
of the things that makes Meteor fast.
|
||||
|
||||
`Tracker.flush` forces all of the pending reactive updates to complete.
|
||||
For example, if an event handler changes a Session
|
||||
variable that will cause part of the user interface to rerender, the
|
||||
handler can call `flush` to perform the rerender immediately and then
|
||||
access the resulting DOM.
|
||||
|
||||
An automatic flush occurs whenever the system is idle which performs
|
||||
exactly the same work as `Tracker.flush`. The flushing process consists
|
||||
of rerunning any invalidated computations. If additional
|
||||
invalidations happen while flushing, they are processed as part of the
|
||||
same flush until there is no more work to be done. Callbacks
|
||||
registered with [`Tracker.afterFlush`](#tracker_afterflush) are called
|
||||
after processing outstanding invalidations.
|
||||
|
||||
It is illegal to call `flush` from inside a `flush` or from a running
|
||||
computation.
|
||||
|
||||
The <a href="http://manual.meteor.com/#tracker-theflushcycle">Meteor Manual</a>
|
||||
describes the motivation for the flush cycle and the guarantees made by
|
||||
`Tracker.flush` and `Tracker.afterFlush`.
|
||||
|
||||
{{> autoApiBox "Tracker.nonreactive" }}
|
||||
|
||||
Calls `func` with `Tracker.currentComputation` temporarily set to `null`
|
||||
and returns `func`'s own return value. If `func` accesses reactive data
|
||||
sources, these data sources will never cause a rerun of the enclosing
|
||||
computation.
|
||||
|
||||
{{> autoApiBox "Tracker.active" }}
|
||||
|
||||
This value is useful for data source implementations to determine
|
||||
whether they are being accessed reactively or not.
|
||||
|
||||
{{> autoApiBox "Tracker.currentComputation" }}
|
||||
|
||||
It's very rare to need to access `currentComputation` directly. The
|
||||
current computation is used implicitly by
|
||||
[`Tracker.active`](#tracker_active) (which tests whether there is one),
|
||||
[`dependency.depend()`](#dependency_depend) (which registers that it depends on a
|
||||
dependency), and [`Tracker.onInvalidate`](#tracker_oninvalidate) (which
|
||||
registers a callback with it).
|
||||
|
||||
{{> autoApiBox "Tracker.onInvalidate" }}
|
||||
|
||||
See [*`computation`*`.onInvalidate`](#computation_oninvalidate) for more
|
||||
details.
|
||||
|
||||
{{> autoApiBox "Tracker.afterFlush" }}
|
||||
|
||||
Functions scheduled by multiple calls to `afterFlush` are guaranteed
|
||||
to run in the order that `afterFlush` was called. Functions are
|
||||
guaranteed to be called at a time when there are no invalidated
|
||||
computations that need rerunning. This means that if an `afterFlush`
|
||||
function invalidates a computation, that computation will be rerun
|
||||
before any other `afterFlush` functions are called.
|
||||
|
||||
<h2 id="tracker_computation"><span>Tracker.Computation</span></h2>
|
||||
|
||||
A Computation object represents code that is repeatedly rerun in
|
||||
response to reactive data changes. Computations don't have return
|
||||
values; they just perform actions, such as rerendering a template on
|
||||
the screen. Computations are created using [`Tracker.autorun`](#tracker_autorun).
|
||||
Use [`stop`](#computation_stop) to prevent further rerunning of a
|
||||
computation.
|
||||
|
||||
Each time a computation runs, it may access various reactive data
|
||||
sources that serve as inputs to the computation, which are called its
|
||||
dependencies. At some future time, one of these dependencies may
|
||||
trigger the computation to be rerun by invalidating it. When this
|
||||
happens, the dependencies are cleared, and the computation is
|
||||
scheduled to be rerun at flush time.
|
||||
|
||||
The *current computation*
|
||||
([`Tracker.currentComputation`](#tracker_currentcomputation)) is the
|
||||
computation that is currently being run or rerun (computed), and the
|
||||
one that gains a dependency when a reactive data source is accessed.
|
||||
Data sources are responsible for tracking these dependencies using
|
||||
[`Tracker.Dependency`](#tracker_dependency) objects.
|
||||
|
||||
Invalidating a computation sets its `invalidated` property to true
|
||||
and immediately calls all of the computation's `onInvalidate`
|
||||
callbacks. When a flush occurs, if the computation has been invalidated
|
||||
and not stopped, then the computation is rerun by setting the
|
||||
`invalidated` property to `false` and calling the original function
|
||||
that was passed to `Tracker.autorun`. A flush will occur when the current
|
||||
code finishes running, or sooner if `Tracker.flush` is called.
|
||||
|
||||
Stopping a computation invalidates it (if it is valid) for the purpose
|
||||
of calling callbacks, but ensures that it will never be rerun.
|
||||
|
||||
Example:
|
||||
|
||||
// if we're in a computation, then perform some clean-up
|
||||
// when the current computation is invalidated (rerun or
|
||||
// stopped)
|
||||
if (Tracker.active) {
|
||||
Tracker.onInvalidate(function () {
|
||||
x.destroy();
|
||||
y.finalize();
|
||||
});
|
||||
}
|
||||
|
||||
{{> autoApiBox "Tracker.Computation#stop"}}
|
||||
|
||||
Stopping a computation is irreversible and guarantees that it will
|
||||
never be rerun. You can stop a computation at any time, including
|
||||
from the computation's own run function. Stopping a computation that
|
||||
is already stopped has no effect.
|
||||
|
||||
Stopping a computation causes its `onInvalidate` callbacks to run
|
||||
immediately if it is not currently invalidated.
|
||||
|
||||
Nested computations are stopped automatically when their enclosing
|
||||
computation is rerun.
|
||||
|
||||
{{> autoApiBox "Tracker.Computation#invalidate" }}
|
||||
|
||||
Invalidating a computation marks it to be rerun at
|
||||
[flush time](#tracker_flush), at
|
||||
which point the computation becomes valid again. It is rare to
|
||||
invalidate a computation manually, because reactive data sources
|
||||
invalidate their calling computations when they change. Reactive data
|
||||
sources in turn perform this invalidation using one or more
|
||||
[`Tracker.Dependency`](#tracker_dependency) objects.
|
||||
|
||||
Invalidating a computation immediately calls all `onInvalidate`
|
||||
callbacks registered on it. Invalidating a computation that is
|
||||
currently invalidated or is stopped has no effect. A computation can
|
||||
invalidate itself, but if it continues to do so indefinitely, the
|
||||
result will be an infinite loop.
|
||||
|
||||
{{> autoApiBox "Tracker.Computation#onInvalidate" }}
|
||||
|
||||
`onInvalidate` registers a one-time callback that either fires
|
||||
immediately or as soon as the computation is next invalidated or
|
||||
stopped. It is used by reactive data sources to clean up resources or
|
||||
break dependencies when a computation is rerun or stopped.
|
||||
|
||||
To get a callback after a computation has been recomputed, you can
|
||||
call [`Tracker.afterFlush`](#tracker_afterflush) from `onInvalidate`.
|
||||
|
||||
{{> autoApiBox "Tracker.Computation#stopped" }}
|
||||
|
||||
{{> autoApiBox "Tracker.Computation#invalidated" }}
|
||||
|
||||
This property is initially false. It is set to true by `stop()` and
|
||||
`invalidate()`. It is reset to false when the computation is
|
||||
recomputed at flush time.
|
||||
|
||||
{{> autoApiBox "Tracker.Computation#firstRun" }}
|
||||
|
||||
This property is a convenience to support the common pattern where a
|
||||
computation has logic specific to the first run.
|
||||
|
||||
<h2 id="tracker_dependency"><span>Tracker.Dependency</span></h2>
|
||||
|
||||
A Dependency represents an atomic unit of reactive data that a
|
||||
computation might depend on. Reactive data sources such as Session or
|
||||
Minimongo internally create different Dependency objects for different
|
||||
pieces of data, each of which may be depended on by multiple
|
||||
computations. When the data changes, the computations are
|
||||
invalidated.
|
||||
|
||||
Dependencies don't store data, they just track the set of computations to
|
||||
invalidate if something changes. Typically, a data value will be
|
||||
accompanied by a Dependency object that tracks the computations that depend
|
||||
on it, as in this example:
|
||||
|
||||
var weather = "sunny";
|
||||
var weatherDep = new Tracker.Dependency;
|
||||
|
||||
var getWeather = function () {
|
||||
weatherDep.depend()
|
||||
return weather;
|
||||
};
|
||||
|
||||
var setWeather = function (w) {
|
||||
weather = w;
|
||||
// (could add logic here to only call changed()
|
||||
// if the new value is different from the old)
|
||||
weatherDep.changed();
|
||||
};
|
||||
|
||||
This example implements a weather data source with a simple getter and
|
||||
setter. The getter records that the current computation depends on
|
||||
the `weatherDep` dependency using `depend()`, while the setter
|
||||
signals the dependency to invalidate all dependent computations by
|
||||
calling `changed()`.
|
||||
|
||||
The reason Dependencies do not store data themselves is that it can be
|
||||
useful to associate multiple Dependencies with the same piece of data.
|
||||
For example, one Dependency might represent the result of a database
|
||||
query, while another might represent just the number of documents in
|
||||
the result. A Dependency could represent whether the weather is sunny
|
||||
or not, or whether the temperature is above freezing.
|
||||
[`Session.equals`](#session_equals) is implemented this way for
|
||||
efficiency. When you call `Session.equals("weather", "sunny")`, the
|
||||
current computation is made to depend on an internal Dependency that
|
||||
does not change if the weather goes from, say, "rainy" to "cloudy".
|
||||
|
||||
Conceptually, the only two things a Dependency can do are gain a
|
||||
dependent and change.
|
||||
|
||||
A Dependency's dependent computations are always valid (they have
|
||||
`invalidated === false`). If a dependent is invalidated at any time,
|
||||
either by the Dependency itself or some other way, it is immediately
|
||||
removed.
|
||||
|
||||
See the <a href="http://manual.meteor.com/#tracker-reactivevaluewithdependency">
|
||||
Meteor Manual</a> to learn how to create a reactive data source using
|
||||
Tracker.Dependency.
|
||||
|
||||
{{> autoApiBox "Tracker.Dependency#changed" }}
|
||||
|
||||
{{> autoApiBox "Tracker.Dependency#depend" }}
|
||||
|
||||
`dep.depend()` is used in reactive data source implementations to record
|
||||
the fact that `dep` is being accessed from the current computation.
|
||||
|
||||
{{> autoApiBox "Tracker.Dependency#hasDependents" }}
|
||||
|
||||
For reactive data sources that create many internal Dependencies,
|
||||
this function is useful to determine whether a particular Dependency is
|
||||
still tracking any dependency relationships or if it can be cleaned up
|
||||
to save memory.
|
||||
|
||||
{{/template}}
|
||||
@@ -149,7 +149,7 @@ can add multiple packages with one command
|
||||
Optionally, adds version constraints. Running `meteor add package@1.1.0` will
|
||||
add the package at version `1.1.0` or higher (but not `2.0.0` or higher). If you
|
||||
want to use version `1.1.0` exactly, use `meteor add package@=1.1.0`. You can also
|
||||
'or' constraints together: for example, '=1.0.0 || =2.0.1' means either 1.0.0 (exactly)
|
||||
'or' constraints together: for example, `meteor add 'package@=1.0.0 || =2.0.1'` means either 1.0.0 (exactly)
|
||||
or 2.0.1 (exactly).
|
||||
|
||||
To remove a version constraint for a specific package, run `meteor add` again
|
||||
|
||||
@@ -89,7 +89,7 @@ server code but not served to the client, like private data files.
|
||||
|
||||
There are more assets to consider on the client side. Meteor
|
||||
gathers all JavaScript files in your tree, with the exception of
|
||||
the `server`, `public`, and `private` subdirectories, for the
|
||||
the `server`, `tests`, `public`, and `private` subdirectories, for the
|
||||
client. It minifies this bundle and serves it to each new client.
|
||||
You're free to use a single JavaScript file for your entire application, or
|
||||
create a nested tree of separate files, or anything in between.
|
||||
@@ -100,7 +100,7 @@ executed without being wrapped in a new variable scope. This means
|
||||
that each top-level `var` defines a global variable. In addition,
|
||||
these files are executed before other client-side JavaScript files.
|
||||
|
||||
Files outside the `client`, `server` and `tests` subdirectories are loaded on
|
||||
Files outside the `client`, `server`, `tests`, `public` and `private` subdirectories are loaded on
|
||||
both the client and the server! That's the place for model definitions and
|
||||
other functions. Meteor provides the variables [`isClient`](#meteor_isclient) and
|
||||
[`isServer`](#meteor_isserver) so that your code can alter its behavior depending
|
||||
@@ -427,7 +427,7 @@ Meteor templates when compiled.
|
||||
{{#note}}
|
||||
Today, the only templating system that ships with Meteor is Spacebars, though
|
||||
our community has created packages for other languages such as
|
||||
[Jade](https://atmospherejs.com/package/jade).
|
||||
[Jade](https://atmospherejs.com/mquandalle/jade).
|
||||
{{/note}}
|
||||
|
||||
To define templates, create a file in your project with the `.html`
|
||||
@@ -793,9 +793,10 @@ things). However, we will still write the new versions.json file.
|
||||
|
||||
Meteor uses extended semver versioning for its packages: that means that the version
|
||||
number has three parts separated by dots: major version, minor version and patch version
|
||||
(for example: 1.2.3) with an optional pre-release version. You can read more about it here
|
||||
(www.semver.org). Additionally, because some meteor packages wrap external libraries,
|
||||
Meteor supports the convention of using _ to denote a wrap number.
|
||||
(for example: 1.2.3) with an optional pre-release version. You can read more about it on
|
||||
[semver.org](http://www.semver.org).
|
||||
Additionally, because some meteor packages wrap external libraries,
|
||||
Meteor supports the convention of using `_` to denote a wrap number.
|
||||
|
||||
You can read more about [`package.js`](#packagejs) files in the API
|
||||
section.
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -42,8 +42,12 @@ pre {
|
||||
|
||||
code {
|
||||
font-family: monospace;
|
||||
font-size: 1.1em;
|
||||
white-space: pre;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
pre code {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
ul {
|
||||
@@ -392,23 +396,7 @@ h3.api-title {
|
||||
}
|
||||
|
||||
#main pre {
|
||||
-moz-border-radius: 10px;
|
||||
-webkit-border-radius: 10px;
|
||||
-o-border-radius: 10px;
|
||||
-ms-border-radius: 10px;
|
||||
-khtml-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
border-color: #777;
|
||||
border-style: solid;
|
||||
background-color: white;
|
||||
border-width: 1px;
|
||||
padding: 5px;
|
||||
margin: 1em 0 1em 0;
|
||||
}
|
||||
|
||||
#main pre, #main pre code { /* override inline code font and white-space*/
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
#main a.selflink:link, #main a.selflink:visited, #main a.selflink:hover {
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
var release = Meteor.release ? "0.9.4" : "(checkout)";
|
||||
|
||||
Template.headline.helpers({
|
||||
release: function () {
|
||||
return Meteor.release ? "0.9.4-pre.11" : "(checkout)";
|
||||
return release;
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.startup(function () {
|
||||
// XXX this is broken by the new multi-page layout. Also, it was
|
||||
// broken before the multi-page layout because it had illegible
|
||||
// colors. Just turn it off for now. We'll fix it and turn it on
|
||||
// later.
|
||||
// prettyPrint();
|
||||
|
||||
//mixpanel tracking
|
||||
mixpanel.track('docs');
|
||||
|
||||
@@ -103,7 +99,7 @@ var hideMenu = function () {
|
||||
};
|
||||
|
||||
var toc = [
|
||||
{name: "Meteor " + Template.headline.release(), id: "top"}, [
|
||||
{name: "Meteor " + release, id: "top"}, [
|
||||
"Quick start",
|
||||
"Seven principles",
|
||||
"Resources"
|
||||
@@ -402,7 +398,7 @@ var toc = [
|
||||
|
||||
{name: "mobile-config.js", id: "mobileconfigjs"}, [
|
||||
{name: "App.info", id: "App-info"},
|
||||
{name: "App.set", id: "App-set"},
|
||||
{name: "App.setPreference", id: "App-setPreference"},
|
||||
{name: "App.configurePlugin", id: "App-configurePlugin"},
|
||||
{name: "App.icons", id: "App-icons"},
|
||||
{name: "App.launchScreens", id: "App-launchScreens"}
|
||||
@@ -411,17 +407,13 @@ var toc = [
|
||||
|
||||
"Packages", [ [
|
||||
"accounts-ui",
|
||||
"appcache",
|
||||
"audit-argument-checks",
|
||||
"browser-policy",
|
||||
"coffeescript",
|
||||
"fastclick",
|
||||
"force-ssl",
|
||||
"jquery",
|
||||
"less",
|
||||
"oauth-encryption",
|
||||
"random",
|
||||
"spiderable",
|
||||
"stylus",
|
||||
"showdown",
|
||||
"underscore",
|
||||
|
||||
@@ -43,29 +43,29 @@ platforms](https://github.com/meteor/meteor/wiki/Supported-Platforms).
|
||||
|
||||
Install Meteor:
|
||||
|
||||
<pre>
|
||||
```
|
||||
$ curl https://install.meteor.com | /bin/sh
|
||||
</pre>
|
||||
```
|
||||
|
||||
Create a project:
|
||||
|
||||
<pre>
|
||||
```
|
||||
$ meteor create myapp
|
||||
</pre>
|
||||
```
|
||||
|
||||
Run it locally:
|
||||
|
||||
<pre>
|
||||
```
|
||||
$ cd myapp
|
||||
$ meteor
|
||||
=> Meteor server running on: http://localhost:3000/
|
||||
</pre>
|
||||
# Meteor server running on: http://localhost:3000/
|
||||
```
|
||||
|
||||
Unleash it on the world (on a free server we provide):
|
||||
|
||||
<pre>
|
||||
```
|
||||
$ meteor deploy myapp.meteor.com
|
||||
</pre>
|
||||
```
|
||||
|
||||
<h2 id="sevenprinciples">Seven Principles of Meteor</h2>
|
||||
|
||||
|
||||
@@ -19,17 +19,13 @@ and removed with:
|
||||
Meteor Development Group maintains the following packages:
|
||||
|
||||
{{> pkg_accounts_ui}}
|
||||
{{> pkg_appcache}}
|
||||
{{> pkg_audit_argument_checks}}
|
||||
{{> pkg_browser_policy}}
|
||||
{{> pkg_coffeescript}}
|
||||
{{> pkg_fastclick}}
|
||||
{{> pkg_force_ssl}}
|
||||
{{> pkg_jquery}}
|
||||
{{> pkg_less}}
|
||||
{{> pkg_oauth_encryption}}
|
||||
{{> pkg_random}}
|
||||
{{> pkg_spiderable}}
|
||||
{{> pkg_stylus}}
|
||||
{{> pkg_showdown}}
|
||||
{{> pkg_underscore}}
|
||||
|
||||
@@ -4,3 +4,4 @@
|
||||
|
||||
notices-for-0.9.0
|
||||
notices-for-0.9.1
|
||||
0.9.4-platform-file
|
||||
|
||||
2
examples/clock/.meteor/platforms
Normal file
2
examples/clock/.meteor/platforms
Normal file
@@ -0,0 +1,2 @@
|
||||
server
|
||||
browser
|
||||
@@ -1 +1 @@
|
||||
METEOR@0.9.3
|
||||
METEOR@0.9.4
|
||||
|
||||
@@ -1,52 +1,52 @@
|
||||
application-configuration@1.0.2
|
||||
autopublish@1.0.0
|
||||
autoupdate@1.1.1
|
||||
base64@1.0.0
|
||||
binary-heap@1.0.0
|
||||
blaze-tools@1.0.0
|
||||
blaze@2.0.1
|
||||
boilerplate-generator@1.0.0
|
||||
callback-hook@1.0.0
|
||||
check@1.0.1
|
||||
ctl-helper@1.0.3
|
||||
ctl@1.0.1
|
||||
ddp@1.0.9
|
||||
deps@1.0.4
|
||||
ejson@1.0.3
|
||||
fastclick@1.0.0
|
||||
follower-livedata@1.0.1
|
||||
geojson-utils@1.0.0
|
||||
html-tools@1.0.1
|
||||
htmljs@1.0.1
|
||||
http@1.0.6
|
||||
id-map@1.0.0
|
||||
insecure@1.0.0
|
||||
jquery@1.0.0
|
||||
json@1.0.0
|
||||
livedata@1.0.10
|
||||
logging@1.0.3
|
||||
meteor-platform@1.1.1
|
||||
meteor@1.1.1
|
||||
minifiers@1.1.0
|
||||
minimongo@1.0.3
|
||||
mobile-status-bar@1.0.0
|
||||
mongo@1.0.6
|
||||
observe-sequence@1.0.2
|
||||
ordered-dict@1.0.0
|
||||
random@1.0.0
|
||||
reactive-dict@1.0.3
|
||||
reactive-var@1.0.2
|
||||
reload@1.1.0
|
||||
retry@1.0.0
|
||||
routepolicy@1.0.1
|
||||
session@1.0.2
|
||||
spacebars-compiler@1.0.2
|
||||
spacebars@1.0.2
|
||||
standard-app-packages@1.0.2
|
||||
templating@1.0.7
|
||||
tracker@1.0.2
|
||||
ui@1.0.3
|
||||
underscore@1.0.0
|
||||
url@1.0.0
|
||||
webapp-hashing@1.0.0
|
||||
webapp@1.1.2
|
||||
application-configuration@1.0.3
|
||||
autopublish@1.0.1
|
||||
autoupdate@1.1.2
|
||||
base64@1.0.1
|
||||
binary-heap@1.0.1
|
||||
blaze-tools@1.0.1
|
||||
blaze@2.0.2
|
||||
boilerplate-generator@1.0.1
|
||||
callback-hook@1.0.1
|
||||
check@1.0.2
|
||||
ctl-helper@1.0.4
|
||||
ctl@1.0.2
|
||||
ddp@1.0.10
|
||||
deps@1.0.5
|
||||
ejson@1.0.4
|
||||
fastclick@1.0.1
|
||||
follower-livedata@1.0.2
|
||||
geojson-utils@1.0.1
|
||||
html-tools@1.0.2
|
||||
htmljs@1.0.2
|
||||
http@1.0.7
|
||||
id-map@1.0.1
|
||||
insecure@1.0.1
|
||||
jquery@1.0.1
|
||||
json@1.0.1
|
||||
livedata@1.0.11
|
||||
logging@1.0.4
|
||||
meteor-platform@1.1.2
|
||||
meteor@1.1.2
|
||||
minifiers@1.1.1
|
||||
minimongo@1.0.4
|
||||
mobile-status-bar@1.0.1
|
||||
mongo@1.0.7
|
||||
observe-sequence@1.0.3
|
||||
ordered-dict@1.0.1
|
||||
random@1.0.1
|
||||
reactive-dict@1.0.4
|
||||
reactive-var@1.0.3
|
||||
reload@1.1.1
|
||||
retry@1.0.1
|
||||
routepolicy@1.0.2
|
||||
session@1.0.3
|
||||
spacebars-compiler@1.0.3
|
||||
spacebars@1.0.3
|
||||
standard-app-packages@1.0.3
|
||||
templating@1.0.8
|
||||
tracker@1.0.3
|
||||
ui@1.0.4
|
||||
underscore@1.0.1
|
||||
url@1.0.1
|
||||
webapp-hashing@1.0.1
|
||||
webapp@1.1.3
|
||||
|
||||
@@ -4,3 +4,4 @@
|
||||
|
||||
notices-for-0.9.0
|
||||
notices-for-0.9.1
|
||||
0.9.4-platform-file
|
||||
|
||||
2
examples/leaderboard/.meteor/platforms
Normal file
2
examples/leaderboard/.meteor/platforms
Normal file
@@ -0,0 +1,2 @@
|
||||
server
|
||||
browser
|
||||
@@ -1 +1 @@
|
||||
METEOR@0.9.3
|
||||
METEOR@0.9.4
|
||||
|
||||
@@ -1,52 +1,52 @@
|
||||
application-configuration@1.0.2
|
||||
autopublish@1.0.0
|
||||
autoupdate@1.1.1
|
||||
base64@1.0.0
|
||||
binary-heap@1.0.0
|
||||
blaze-tools@1.0.0
|
||||
blaze@2.0.1
|
||||
boilerplate-generator@1.0.0
|
||||
callback-hook@1.0.0
|
||||
check@1.0.1
|
||||
ctl-helper@1.0.3
|
||||
ctl@1.0.1
|
||||
ddp@1.0.9
|
||||
deps@1.0.4
|
||||
ejson@1.0.3
|
||||
fastclick@1.0.0
|
||||
follower-livedata@1.0.1
|
||||
geojson-utils@1.0.0
|
||||
html-tools@1.0.1
|
||||
htmljs@1.0.1
|
||||
http@1.0.6
|
||||
id-map@1.0.0
|
||||
insecure@1.0.0
|
||||
jquery@1.0.0
|
||||
json@1.0.0
|
||||
livedata@1.0.10
|
||||
logging@1.0.3
|
||||
meteor-platform@1.1.1
|
||||
meteor@1.1.1
|
||||
minifiers@1.1.0
|
||||
minimongo@1.0.3
|
||||
mobile-status-bar@1.0.0
|
||||
mongo@1.0.6
|
||||
observe-sequence@1.0.2
|
||||
ordered-dict@1.0.0
|
||||
random@1.0.0
|
||||
reactive-dict@1.0.3
|
||||
reactive-var@1.0.2
|
||||
reload@1.1.0
|
||||
retry@1.0.0
|
||||
routepolicy@1.0.1
|
||||
session@1.0.2
|
||||
spacebars-compiler@1.0.2
|
||||
spacebars@1.0.2
|
||||
standard-app-packages@1.0.2
|
||||
templating@1.0.7
|
||||
tracker@1.0.2
|
||||
ui@1.0.3
|
||||
underscore@1.0.0
|
||||
url@1.0.0
|
||||
webapp-hashing@1.0.0
|
||||
webapp@1.1.2
|
||||
application-configuration@1.0.3
|
||||
autopublish@1.0.1
|
||||
autoupdate@1.1.2
|
||||
base64@1.0.1
|
||||
binary-heap@1.0.1
|
||||
blaze-tools@1.0.1
|
||||
blaze@2.0.2
|
||||
boilerplate-generator@1.0.1
|
||||
callback-hook@1.0.1
|
||||
check@1.0.2
|
||||
ctl-helper@1.0.4
|
||||
ctl@1.0.2
|
||||
ddp@1.0.10
|
||||
deps@1.0.5
|
||||
ejson@1.0.4
|
||||
fastclick@1.0.1
|
||||
follower-livedata@1.0.2
|
||||
geojson-utils@1.0.1
|
||||
html-tools@1.0.2
|
||||
htmljs@1.0.2
|
||||
http@1.0.7
|
||||
id-map@1.0.1
|
||||
insecure@1.0.1
|
||||
jquery@1.0.1
|
||||
json@1.0.1
|
||||
livedata@1.0.11
|
||||
logging@1.0.4
|
||||
meteor-platform@1.1.2
|
||||
meteor@1.1.2
|
||||
minifiers@1.1.1
|
||||
minimongo@1.0.4
|
||||
mobile-status-bar@1.0.1
|
||||
mongo@1.0.7
|
||||
observe-sequence@1.0.3
|
||||
ordered-dict@1.0.1
|
||||
random@1.0.1
|
||||
reactive-dict@1.0.4
|
||||
reactive-var@1.0.3
|
||||
reload@1.1.1
|
||||
retry@1.0.1
|
||||
routepolicy@1.0.2
|
||||
session@1.0.3
|
||||
spacebars-compiler@1.0.3
|
||||
spacebars@1.0.3
|
||||
standard-app-packages@1.0.3
|
||||
templating@1.0.8
|
||||
tracker@1.0.3
|
||||
ui@1.0.4
|
||||
underscore@1.0.1
|
||||
url@1.0.1
|
||||
webapp-hashing@1.0.1
|
||||
webapp@1.1.3
|
||||
|
||||
@@ -4,3 +4,4 @@
|
||||
|
||||
notices-for-0.9.0
|
||||
notices-for-0.9.1
|
||||
0.9.4-platform-file
|
||||
|
||||
2
examples/parties/.meteor/platforms
Normal file
2
examples/parties/.meteor/platforms
Normal file
@@ -0,0 +1,2 @@
|
||||
server
|
||||
browser
|
||||
@@ -1 +1 @@
|
||||
METEOR@0.9.3
|
||||
METEOR@0.9.4
|
||||
|
||||
@@ -1,72 +1,72 @@
|
||||
accounts-base@1.1.1
|
||||
accounts-facebook@1.0.1
|
||||
accounts-oauth@1.1.1
|
||||
accounts-password@1.0.2
|
||||
accounts-twitter@1.0.1
|
||||
accounts-ui-unstyled@1.1.2
|
||||
accounts-ui@1.1.1
|
||||
application-configuration@1.0.2
|
||||
audit-argument-checks@1.0.0
|
||||
autoupdate@1.1.1
|
||||
base64@1.0.0
|
||||
binary-heap@1.0.0
|
||||
blaze-tools@1.0.0
|
||||
blaze@2.0.1
|
||||
boilerplate-generator@1.0.0
|
||||
accounts-base@1.1.2
|
||||
accounts-facebook@1.0.2
|
||||
accounts-oauth@1.1.2
|
||||
accounts-password@1.0.3
|
||||
accounts-twitter@1.0.2
|
||||
accounts-ui-unstyled@1.1.3
|
||||
accounts-ui@1.1.2
|
||||
application-configuration@1.0.3
|
||||
audit-argument-checks@1.0.1
|
||||
autoupdate@1.1.2
|
||||
base64@1.0.1
|
||||
binary-heap@1.0.1
|
||||
blaze-tools@1.0.1
|
||||
blaze@2.0.2
|
||||
boilerplate-generator@1.0.1
|
||||
bootstrap@1.0.1
|
||||
callback-hook@1.0.0
|
||||
check@1.0.1
|
||||
ctl-helper@1.0.3
|
||||
ctl@1.0.1
|
||||
callback-hook@1.0.1
|
||||
check@1.0.2
|
||||
ctl-helper@1.0.4
|
||||
ctl@1.0.2
|
||||
d3@1.0.0
|
||||
ddp@1.0.9
|
||||
deps@1.0.4
|
||||
ejson@1.0.3
|
||||
email@1.0.3
|
||||
facebook@1.1.0
|
||||
fastclick@1.0.0
|
||||
follower-livedata@1.0.1
|
||||
geojson-utils@1.0.0
|
||||
html-tools@1.0.1
|
||||
htmljs@1.0.1
|
||||
http@1.0.6
|
||||
id-map@1.0.0
|
||||
jquery@1.0.0
|
||||
json@1.0.0
|
||||
less@1.0.9
|
||||
livedata@1.0.10
|
||||
localstorage@1.0.0
|
||||
logging@1.0.3
|
||||
meteor-platform@1.1.1
|
||||
meteor@1.1.1
|
||||
minifiers@1.1.0
|
||||
minimongo@1.0.3
|
||||
mobile-status-bar@1.0.0
|
||||
mongo@1.0.6
|
||||
ddp@1.0.10
|
||||
deps@1.0.5
|
||||
ejson@1.0.4
|
||||
email@1.0.4
|
||||
facebook@1.1.1
|
||||
fastclick@1.0.1
|
||||
follower-livedata@1.0.2
|
||||
geojson-utils@1.0.1
|
||||
html-tools@1.0.2
|
||||
htmljs@1.0.2
|
||||
http@1.0.7
|
||||
id-map@1.0.1
|
||||
jquery@1.0.1
|
||||
json@1.0.1
|
||||
less@1.0.10
|
||||
livedata@1.0.11
|
||||
localstorage@1.0.1
|
||||
logging@1.0.4
|
||||
meteor-platform@1.1.2
|
||||
meteor@1.1.2
|
||||
minifiers@1.1.1
|
||||
minimongo@1.0.4
|
||||
mobile-status-bar@1.0.1
|
||||
mongo@1.0.7
|
||||
npm-bcrypt@0.7.7
|
||||
oauth1@1.1.0
|
||||
oauth2@1.1.0
|
||||
oauth@1.1.0
|
||||
observe-sequence@1.0.2
|
||||
ordered-dict@1.0.0
|
||||
random@1.0.0
|
||||
reactive-dict@1.0.3
|
||||
reactive-var@1.0.2
|
||||
reload@1.1.0
|
||||
retry@1.0.0
|
||||
routepolicy@1.0.1
|
||||
service-configuration@1.0.1
|
||||
session@1.0.2
|
||||
sha@1.0.0
|
||||
spacebars-compiler@1.0.2
|
||||
spacebars@1.0.2
|
||||
srp@1.0.0
|
||||
standard-app-packages@1.0.2
|
||||
templating@1.0.7
|
||||
tracker@1.0.2
|
||||
twitter@1.1.0
|
||||
ui@1.0.3
|
||||
underscore@1.0.0
|
||||
url@1.0.0
|
||||
webapp-hashing@1.0.0
|
||||
webapp@1.1.2
|
||||
oauth1@1.1.1
|
||||
oauth2@1.1.1
|
||||
oauth@1.1.1
|
||||
observe-sequence@1.0.3
|
||||
ordered-dict@1.0.1
|
||||
random@1.0.1
|
||||
reactive-dict@1.0.4
|
||||
reactive-var@1.0.3
|
||||
reload@1.1.1
|
||||
retry@1.0.1
|
||||
routepolicy@1.0.2
|
||||
service-configuration@1.0.2
|
||||
session@1.0.3
|
||||
sha@1.0.1
|
||||
spacebars-compiler@1.0.3
|
||||
spacebars@1.0.3
|
||||
srp@1.0.1
|
||||
standard-app-packages@1.0.3
|
||||
templating@1.0.8
|
||||
tracker@1.0.3
|
||||
twitter@1.1.1
|
||||
ui@1.0.4
|
||||
underscore@1.0.1
|
||||
url@1.0.1
|
||||
webapp-hashing@1.0.1
|
||||
webapp@1.1.3
|
||||
|
||||
@@ -5,7 +5,7 @@ Meteor.subscribe("parties");
|
||||
|
||||
// If no party selected, or if the selected party was deleted, select one.
|
||||
Meteor.startup(function () {
|
||||
Deps.autorun(function () {
|
||||
Tracker.autorun(function () {
|
||||
var selected = Session.get("selected");
|
||||
if (! selected || ! Parties.findOne(selected)) {
|
||||
var party = Parties.findOne();
|
||||
@@ -130,7 +130,7 @@ Template.map.rendered = function () {
|
||||
self.node = self.find("svg");
|
||||
|
||||
if (! self.handle) {
|
||||
self.handle = Deps.autorun(function () {
|
||||
self.handle = Tracker.autorun(function () {
|
||||
var selected = Session.get('selected');
|
||||
var selectedParty = selected && Parties.findOne(selected);
|
||||
var radius = function (party) {
|
||||
|
||||
@@ -8,6 +8,3 @@ insecure
|
||||
less
|
||||
iron:router
|
||||
accounts-password
|
||||
fastclick
|
||||
noorderstorm:hammer
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
METEOR@0.9.4-pre.8
|
||||
METEOR@0.9.4
|
||||
|
||||
@@ -1,65 +1,65 @@
|
||||
accounts-base@1.1.2-pre.2
|
||||
accounts-password@1.0.3-pre.2
|
||||
application-configuration@1.0.3-pre.2
|
||||
autoupdate@1.1.2-pre.3
|
||||
base64@1.0.1-pre.2
|
||||
binary-heap@1.0.1-pre.2
|
||||
blaze-tools@1.0.1-pre.2
|
||||
blaze@2.0.2-pre.2
|
||||
boilerplate-generator@1.0.1-pre.3
|
||||
callback-hook@1.0.1-pre.2
|
||||
check@1.0.2-pre.2
|
||||
ctl-helper@1.0.4-pre.2
|
||||
ctl@1.0.2-pre.2
|
||||
ddp@1.0.10-pre.2
|
||||
deps@1.0.5-pre.2
|
||||
ejson@1.0.4-pre.2
|
||||
email@1.0.4-pre.2
|
||||
fastclick@1.0.1-pre.3
|
||||
follower-livedata@1.0.2-pre.2
|
||||
geojson-utils@1.0.1-pre.2
|
||||
html-tools@1.0.2-pre.2
|
||||
htmljs@1.0.2-pre.3
|
||||
http@1.0.7-pre.2
|
||||
id-map@1.0.1-pre.2
|
||||
insecure@1.0.1-pre.2
|
||||
accounts-base@1.1.2
|
||||
accounts-password@1.0.3
|
||||
application-configuration@1.0.3
|
||||
autoupdate@1.1.2
|
||||
base64@1.0.1
|
||||
binary-heap@1.0.1
|
||||
blaze-tools@1.0.1
|
||||
blaze@2.0.2
|
||||
boilerplate-generator@1.0.1
|
||||
callback-hook@1.0.1
|
||||
check@1.0.2
|
||||
ctl-helper@1.0.4
|
||||
ctl@1.0.2
|
||||
ddp@1.0.10
|
||||
deps@1.0.5
|
||||
ejson@1.0.4
|
||||
email@1.0.4
|
||||
fastclick@1.0.1
|
||||
follower-livedata@1.0.2
|
||||
geojson-utils@1.0.1
|
||||
html-tools@1.0.2
|
||||
htmljs@1.0.2
|
||||
http@1.0.7
|
||||
id-map@1.0.1
|
||||
insecure@1.0.1
|
||||
iron:core@0.3.4
|
||||
iron:dynamic-template@0.4.1
|
||||
iron:layout@0.4.1
|
||||
iron:router@0.9.4
|
||||
jquery@1.0.1-pre.2
|
||||
json@1.0.1-pre.2
|
||||
less@1.0.10-pre.3
|
||||
livedata@1.0.11-pre.2
|
||||
localstorage@1.0.1-pre.2
|
||||
logging@1.0.4-pre.2
|
||||
meteor-platform@1.1.2-pre.3
|
||||
meteor@1.1.2-pre.3
|
||||
minifiers@1.1.1-pre.2
|
||||
minimongo@1.0.4-pre.3
|
||||
mobile-status-bar@1.0.1-pre.2
|
||||
mongo@1.0.7-pre.2
|
||||
noorderstorm:hammer@0.1.3
|
||||
jquery@1.0.1
|
||||
json@1.0.1
|
||||
launch-screen@1.0.0
|
||||
less@1.0.10
|
||||
livedata@1.0.11
|
||||
localstorage@1.0.1
|
||||
logging@1.0.4
|
||||
meteor-platform@1.1.2
|
||||
meteor@1.1.2
|
||||
minifiers@1.1.1
|
||||
minimongo@1.0.4
|
||||
mobile-status-bar@1.0.1
|
||||
mongo@1.0.7
|
||||
npm-bcrypt@0.7.7
|
||||
observe-sequence@1.0.3-pre.2
|
||||
ordered-dict@1.0.1-pre.2
|
||||
random@1.0.1-pre.2
|
||||
reactive-dict@1.0.4-pre.2
|
||||
reactive-var@1.0.3-pre.2
|
||||
reload@1.1.1-pre.2
|
||||
retry@1.0.1-pre.2
|
||||
routepolicy@1.0.2-pre.2
|
||||
service-configuration@1.0.2-pre.2
|
||||
session@1.0.3-pre.2
|
||||
sha@1.0.1-pre.2
|
||||
spacebars-compiler@1.0.3-pre.2
|
||||
spacebars@1.0.3-pre.2
|
||||
srp@1.0.1-pre.1
|
||||
standard-app-packages@1.0.3-pre.2
|
||||
templating@1.0.8-pre.3
|
||||
tracker@1.0.3-pre.2
|
||||
ui@1.0.4-pre.2
|
||||
underscore@1.0.1-pre.2
|
||||
url@1.0.1-pre.2
|
||||
webapp-hashing@1.0.1-pre.2
|
||||
webapp@1.1.3-pre.3
|
||||
observe-sequence@1.0.3
|
||||
ordered-dict@1.0.1
|
||||
random@1.0.1
|
||||
reactive-dict@1.0.4
|
||||
reactive-var@1.0.3
|
||||
reload@1.1.1
|
||||
retry@1.0.1
|
||||
routepolicy@1.0.2
|
||||
service-configuration@1.0.2
|
||||
session@1.0.3
|
||||
sha@1.0.1
|
||||
spacebars-compiler@1.0.3
|
||||
spacebars@1.0.3
|
||||
srp@1.0.1
|
||||
standard-app-packages@1.0.3
|
||||
templating@1.0.8
|
||||
tracker@1.0.3
|
||||
ui@1.0.4
|
||||
underscore@1.0.1
|
||||
url@1.0.1
|
||||
webapp-hashing@1.0.1
|
||||
webapp@1.1.3
|
||||
|
||||
82
examples/todos/client/lib/jquery.touchwipe.js
Normal file
82
examples/todos/client/lib/jquery.touchwipe.js
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* jQuery Plugin to obtain touch gestures from iPhone, iPod Touch and iPad, should also work with Android mobile phones (not tested yet!)
|
||||
* Common usage: wipe images (left and right to show the previous or next image)
|
||||
*
|
||||
* @author Andreas Waltl, netCU Internetagentur (http://www.netcu.de)
|
||||
* @version 1.1.1 (9th December 2010) - fix bug (older IE's had problems)
|
||||
* @version 1.1 (1st September 2010) - support wipe up and wipe down
|
||||
* @version 1.0 (15th July 2010)
|
||||
*/
|
||||
(function($) {
|
||||
$.fn.touchwipe = function(settings) {
|
||||
var config = {
|
||||
min_move_x: 20,
|
||||
min_move_y: 20,
|
||||
wipeLeft: function() { },
|
||||
wipeRight: function() { },
|
||||
wipeUp: function() { },
|
||||
wipeDown: function() { },
|
||||
preventDefaultEvents: true
|
||||
};
|
||||
|
||||
if (settings) $.extend(config, settings);
|
||||
|
||||
this.each(function() {
|
||||
var startX;
|
||||
var startY;
|
||||
var isMoving = false;
|
||||
|
||||
function cancelTouch() {
|
||||
this.removeEventListener('touchmove', onTouchMove);
|
||||
startX = null;
|
||||
isMoving = false;
|
||||
}
|
||||
|
||||
function onTouchMove(e) {
|
||||
if(config.preventDefaultEvents) {
|
||||
e.preventDefault();
|
||||
}
|
||||
if(isMoving) {
|
||||
var x = e.touches[0].pageX;
|
||||
var y = e.touches[0].pageY;
|
||||
var dx = startX - x;
|
||||
var dy = startY - y;
|
||||
if(Math.abs(dx) >= config.min_move_x) {
|
||||
cancelTouch();
|
||||
if(dx > 0) {
|
||||
config.wipeLeft();
|
||||
}
|
||||
else {
|
||||
config.wipeRight();
|
||||
}
|
||||
}
|
||||
else if(Math.abs(dy) >= config.min_move_y) {
|
||||
cancelTouch();
|
||||
if(dy > 0) {
|
||||
config.wipeDown();
|
||||
}
|
||||
else {
|
||||
config.wipeUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onTouchStart(e)
|
||||
{
|
||||
if (e.touches.length == 1) {
|
||||
startX = e.touches[0].pageX;
|
||||
startY = e.touches[0].pageY;
|
||||
isMoving = true;
|
||||
this.addEventListener('touchmove', onTouchMove, false);
|
||||
}
|
||||
}
|
||||
if ('ontouchstart' in document.documentElement) {
|
||||
this.addEventListener('touchstart', onTouchStart, false);
|
||||
}
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
@@ -1,10 +1,10 @@
|
||||
@font-face {
|
||||
font-family: 'todos';
|
||||
src:url('icon/todos.eot?o4fu7p');
|
||||
src:url('icon/todos.eot?#iefixo4fu7p') format('embedded-opentype'),
|
||||
url('icon/todos.woff?o4fu7p') format('woff'),
|
||||
url('icon/todos.ttf?o4fu7p') format('truetype'),
|
||||
url('icon/todos.svg?o4fu7p#todos') format('svg');
|
||||
src:url('icon/todos.eot?-5w3um4');
|
||||
src:url('icon/todos.eot?#iefix5w3um4') format('embedded-opentype'),
|
||||
url('icon/todos.woff?5w3um4') format('woff'),
|
||||
url('icon/todos.ttf?5w3um4') format('truetype'),
|
||||
url('icon/todos.svg?5w3um4#todos') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@@ -23,9 +23,13 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
|
||||
.icon-unlock:before {
|
||||
content: "\e600";
|
||||
}
|
||||
.icon-user-add:before {
|
||||
content: "\e604";
|
||||
}
|
||||
.icon-cog:before {
|
||||
content: "\e606";
|
||||
}
|
||||
@@ -44,6 +48,9 @@
|
||||
.icon-close:before {
|
||||
content: "\e60c";
|
||||
}
|
||||
.icon-cross:before {
|
||||
content: "\e60d";
|
||||
}
|
||||
.icon-sync:before {
|
||||
content: "\e60e";
|
||||
}
|
||||
@@ -53,6 +60,9 @@
|
||||
.icon-check:before {
|
||||
content: "\e612";
|
||||
}
|
||||
.icon-share:before {
|
||||
content: "\e617";
|
||||
}
|
||||
.icon-email:before {
|
||||
content: "\e619";
|
||||
}
|
||||
@@ -37,6 +37,10 @@ body {
|
||||
background: @color-tertiary;
|
||||
opacity: 1;
|
||||
|
||||
@media screen and (min-width: 40em) {
|
||||
left: @menu-width;
|
||||
}
|
||||
|
||||
.content-scrollable {
|
||||
.position(absolute, 0, 0, 0, 0);
|
||||
.transform(translate3d(0, 0, 0));
|
||||
@@ -48,13 +52,14 @@ body {
|
||||
.menu-open & {
|
||||
.transform(translate3d(@menu-width, 0, 0));
|
||||
opacity: .85;
|
||||
}
|
||||
left: 0;
|
||||
|
||||
// Show menu on desktop, negate .menu-open
|
||||
@media screen and (min-width: 40em) {
|
||||
.transform(translate3d(0, 0, 0)); //reset transform and use position properties instead
|
||||
left: @menu-width;
|
||||
opacity: 1;
|
||||
@media screen and (min-width: 40em) {
|
||||
// Show menu on desktop, negate .menu-open
|
||||
.transform(translate3d(0, 0, 0)); //reset transform and use position properties instead
|
||||
opacity: 1;
|
||||
left: @menu-width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +85,11 @@
|
||||
color: @color-empty;
|
||||
.count-list { background: @color-primary; }
|
||||
}
|
||||
|
||||
.cordova &:hover {
|
||||
// Prevent hover states from being noticeable on Cordova apps
|
||||
color: rgba(255,255,255,.4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,29 @@
|
||||
@import 'util/reset.lessimport';
|
||||
@import 'util/reset.import.less';
|
||||
|
||||
// Mixins & utilities
|
||||
@import 'util/helpers.lessimport';
|
||||
@import 'util/lesshat.lessimport';
|
||||
@import 'util/text.lessimport';
|
||||
@import 'util/typography.lessimport';
|
||||
@import 'util/variables.lessimport';
|
||||
@import 'util/helpers.import.less';
|
||||
@import 'util/lesshat.import.less';
|
||||
@import 'util/text.import.less';
|
||||
@import 'util/typography.import.less';
|
||||
@import 'util/variables.import.less';
|
||||
|
||||
// Global namespace
|
||||
@import 'globals/base.lessimport';
|
||||
@import 'globals/button.lessimport';
|
||||
@import 'globals/form.lessimport';
|
||||
@import 'globals/icon.lessimport';
|
||||
@import 'globals/layout.lessimport';
|
||||
@import 'globals/link.lessimport';
|
||||
@import 'globals/menu.lessimport';
|
||||
@import 'globals/nav.lessimport';
|
||||
@import 'globals/base.import.less';
|
||||
@import 'globals/button.import.less';
|
||||
@import 'globals/form.import.less';
|
||||
@import 'globals/icon.import.less';
|
||||
@import 'globals/layout.import.less';
|
||||
@import 'globals/link.import.less';
|
||||
@import 'globals/menu.import.less';
|
||||
@import 'globals/nav.import.less';
|
||||
|
||||
// Global templates
|
||||
@import 'globals/list-items.lessimport';
|
||||
@import 'globals/message.lessimport';
|
||||
@import 'globals/notification.lessimport';
|
||||
@import 'globals/list-items.import.less';
|
||||
@import 'globals/message.import.less';
|
||||
@import 'globals/notification.import.less';
|
||||
|
||||
// Templates
|
||||
@import '../templates/lists-show.lessimport';
|
||||
@import '../templates/auth.lessimport';
|
||||
@import '../templates/app-not-found.lessimport';
|
||||
@import '../templates/loading.lessimport';
|
||||
@import '../templates/lists-show.import.less';
|
||||
@import '../templates/auth.import.less';
|
||||
@import '../templates/app-not-found.import.less';
|
||||
@import '../templates/loading.import.less';
|
||||
@@ -10,7 +10,7 @@
|
||||
{{else}}
|
||||
<span class="icon-arrow-down"></span>
|
||||
{{/if}}
|
||||
{{email}}
|
||||
{{emailLocalPart}}
|
||||
</a>
|
||||
{{#if userMenuOpen}}
|
||||
<a class="js-logout btn-secondary">Logout</a>
|
||||
@@ -31,10 +31,10 @@
|
||||
{{#if userId}}
|
||||
<span class="icon-lock"></span>
|
||||
{{/if}}
|
||||
{{name}}
|
||||
{{#if incompleteCount}}
|
||||
<span class="count-list">{{incompleteCount}}</span>
|
||||
{{/if}}
|
||||
{{name}}
|
||||
</a>
|
||||
{{/each}}
|
||||
|
||||
|
||||
@@ -4,21 +4,33 @@ Session.setDefault(MENU_KEY, false);
|
||||
var USER_MENU_KEY = 'userMenuOpen';
|
||||
Session.setDefault(USER_MENU_KEY, false);
|
||||
|
||||
var SHOW_CONNECTION_ISSUE_KEY = 'showConnectionIssue';
|
||||
Session.setDefault(SHOW_CONNECTION_ISSUE_KEY, false);
|
||||
|
||||
var CONNECTION_ISSUE_TIMEOUT = 1000;
|
||||
|
||||
Meteor.startup(function () {
|
||||
// set up a swipe left / right handler
|
||||
$(document.body).touchwipe({
|
||||
wipeLeft: function () {
|
||||
Session.set(MENU_KEY, false);
|
||||
},
|
||||
wipeRight: function () {
|
||||
Session.set(MENU_KEY, true);
|
||||
},
|
||||
preventDefaultEvents: false
|
||||
});
|
||||
|
||||
// Don't show the connection error box unless we haven't connected within
|
||||
// 1 second of app starting
|
||||
setTimeout(function () {
|
||||
Session.set(SHOW_CONNECTION_ISSUE_KEY, true);
|
||||
}, CONNECTION_ISSUE_TIMEOUT);
|
||||
});
|
||||
|
||||
Template.appBody.rendered = function() {
|
||||
if (Meteor.isCordova) {
|
||||
// set up a swipe left / right handler
|
||||
this.hammer = new Hammer(this.find('#container'));
|
||||
this.hammer.on('swipeleft swiperight', function(event) {
|
||||
if (event.gesture.direction === 'right') {
|
||||
Session.set(MENU_KEY, true);
|
||||
} else if (event.gesture.direction === 'left') {
|
||||
Session.set(MENU_KEY, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.find('#content-container')._uihooks = {
|
||||
insertElement: function(node, next) {;
|
||||
insertElement: function(node, next) {
|
||||
$(node)
|
||||
.hide()
|
||||
.insertBefore(next)
|
||||
@@ -32,12 +44,6 @@ Template.appBody.rendered = function() {
|
||||
};
|
||||
};
|
||||
|
||||
Template.appBody.destroyed = function() {
|
||||
if (Meteor.isCordova) {
|
||||
this.hammer.destroy();
|
||||
}
|
||||
};
|
||||
|
||||
Template.appBody.helpers({
|
||||
// We use #each on an array of one item so that the "list" template is
|
||||
// removed and a new copy is added when changing lists, which is
|
||||
@@ -52,8 +58,9 @@ Template.appBody.helpers({
|
||||
cordova: function() {
|
||||
return Meteor.isCordova && 'cordova';
|
||||
},
|
||||
email: function() {
|
||||
return Meteor.user().emails[0].address;
|
||||
emailLocalPart: function() {
|
||||
var email = Meteor.user().emails[0].address;
|
||||
return email.substring(0, email.indexOf('@'));
|
||||
},
|
||||
userMenuOpen: function() {
|
||||
return Session.get(USER_MENU_KEY);
|
||||
@@ -68,7 +75,11 @@ Template.appBody.helpers({
|
||||
}
|
||||
},
|
||||
connected: function() {
|
||||
return Meteor.status().connected;
|
||||
if (Session.get(SHOW_CONNECTION_ISSUE_KEY)) {
|
||||
return Meteor.status().connected;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -34,10 +34,9 @@ Template.listsShow.helpers({
|
||||
var editList = function(list, template) {
|
||||
Session.set(EDITING_KEY, true);
|
||||
|
||||
// wait for the template to redraw based on the reactive change
|
||||
Tracker.afterFlush(function() {
|
||||
template.$('.js-edit-form input[type=text]').focus();
|
||||
});
|
||||
// force the template to redraw based on the reactive change
|
||||
Tracker.flush();
|
||||
template.$('.js-edit-form input[type=text]').focus();
|
||||
};
|
||||
|
||||
var saveList = function(list, template) {
|
||||
@@ -117,15 +116,13 @@ Template.listsShow.events({
|
||||
'change .list-edit': function(event, template) {
|
||||
if ($(event.target).val() === 'edit') {
|
||||
editList(this, template);
|
||||
|
||||
} else if ($(event.target).val() === 'delete') {
|
||||
if (! deleteList(this, template)) {
|
||||
// reset the select
|
||||
event.target.selectedIndex = 0;
|
||||
}
|
||||
deleteList(this, template);
|
||||
} else {
|
||||
toggleListPrivacy(this, template);
|
||||
}
|
||||
|
||||
event.target.selectedIndex = 0;
|
||||
},
|
||||
|
||||
'click .js-edit-list': function(event, template) {
|
||||
|
||||
@@ -18,22 +18,32 @@ Router.configure({
|
||||
}
|
||||
});
|
||||
|
||||
if (Meteor.isClient) {
|
||||
var launchScreenHandle = LaunchScreen.hold();
|
||||
}
|
||||
|
||||
Router.map(function() {
|
||||
this.route('join');
|
||||
this.route('signin');
|
||||
|
||||
this.route('listsShow', {
|
||||
path: '/lists/:_id',
|
||||
// subscribe to todos before the page is rendered but don't wait on the
|
||||
// subscribe to todos before the page is rendered but don't wait on the
|
||||
// subscription, we'll just render the items as they arrive
|
||||
onBeforeAction: function() {
|
||||
onBeforeAction: function () {
|
||||
this.todosHandle = Meteor.subscribe('todos', this.params._id);
|
||||
},
|
||||
data: function() {
|
||||
data: function () {
|
||||
return Lists.findOne(this.params._id);
|
||||
},
|
||||
action: function () {
|
||||
this.render();
|
||||
if (Meteor.isClient) {
|
||||
launchScreenHandle.release();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
this.route('home', {
|
||||
path: '/',
|
||||
action: function() {
|
||||
@@ -45,4 +55,4 @@ Router.map(function() {
|
||||
if (Meteor.isClient) {
|
||||
Router.onBeforeAction('loading', {except: ['join', 'signin']});
|
||||
Router.onBeforeAction('dataNotFound', {except: ['join', 'signin']});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,13 +7,21 @@ App.info({
|
||||
});
|
||||
|
||||
App.icons({
|
||||
// iOS
|
||||
'iphone': 'resources/icons/icon-60.png',
|
||||
'iphone-2x': 'resources/icons/icon-60@2x.png',
|
||||
'iphone_2x': 'resources/icons/icon-60@2x.png',
|
||||
'ipad': 'resources/icons/icon-72.png',
|
||||
'ipad-2x': 'resources/icons/icon-72@2x.png'
|
||||
'ipad_2x': 'resources/icons/icon-72@2x.png',
|
||||
|
||||
// Android - XXX these are the same as iOS for now
|
||||
'android_ldpi': 'resources/icons/icon-60.png',
|
||||
'android_mdpi': 'resources/icons/icon-60.png',
|
||||
'android_hdpi': 'resources/icons/icon-72.png',
|
||||
'android_xhdpi': 'resources/icons/icon-72@2x.png'
|
||||
});
|
||||
|
||||
App.launchScreens({
|
||||
// iOS
|
||||
'iphone': 'resources/splash/Default~iphone.png',
|
||||
'iphone_2x': 'resources/splash/Default@2x~iphone.png',
|
||||
'iphone5': 'resources/splash/Default-568h@2x~iphone.png',
|
||||
|
||||
Binary file not shown.
@@ -8,15 +8,18 @@
|
||||
<missing-glyph horiz-adv-x="512" />
|
||||
<glyph unicode=" " d="" horiz-adv-x="256" />
|
||||
<glyph unicode="" d="M448.016 22.235v233.749c0 0.994-0.097 1.963-0.236 2.917-0.055 0.372-0.095 0.749-0.17 1.113-0.761 3.72-2.568 7.050-5.082 9.704-0.126 0.133-0.24 0.277-0.37 0.407-0.248 0.247-0.517 0.472-0.776 0.706-0.215 0.193-0.42 0.4-0.644 0.585-0.145 0.12-0.304 0.223-0.452 0.338-1.253 0.977-2.622 1.808-4.088 2.467-0.372 0.167-0.752 0.316-1.135 0.461-2.194 0.828-4.562 1.302-7.046 1.302h-276.092l0.001 27.925c0 57.388 46.688 104.075 104.075 104.075 43.019 0 80.017-26.237 95.849-63.548 0.006-0.014 0.015-0.022 0.021-0.036 2.989-7.283 10.142-12.416 18.502-12.416 11.046 0 20 8.953 20 20 0 2.355-0.429 4.605-1.176 6.705-0.091 0.347-0.21 0.719-0.391 1.146-21.833 51.791-73.070 88.148-132.806 88.148-79.564 0-144.065-64.497-144.075-144.060 0 0 0-0.001 0-0.003v-27.938h-27.425c-10.355 0-18.873-7.871-19.896-17.955-0.068-0.672-0.104-1.354-0.104-2.045v-231.666c-0.309-1.397-0.484-2.844-0.484-4.334 0-11.047 8.955-20 20-20h344.135c11.046 0 20 8.955 20 20-0.001 0.764-0.052 1.514-0.135 2.253zM104.5 235.984h303.516v-196h-303.516v196zM288.016 158.99c0 17.673-14.327 32-32 32s-32-14.327-32-32c0-10.134 4.716-19.161 12.067-25.024v-28.988c-0.002-11.046 8.953-20 20-20 11.045 0.002 20 8.956 19.998 20l0.001 29.093c7.275 5.866 11.934 14.847 11.934 24.919z" />
|
||||
<glyph unicode="" d="M195.538 36.414c46.458 0 91.505 9.090 133.89 27.016 7.282 3.080 14.427 6.408 21.44 9.959v7.527c0 46.996-97.17 89.854-123.19 93.994-8.079 1.285-8.264 23.498-8.264 23.498s23.738 23.497 28.911 55.097c13.916 0 22.513 33.593 8.594 45.412 0.582 12.441 17.889 97.67-69.732 97.67s-70.313-85.229-69.734-97.67c-13.917-11.819-5.323-45.412 8.595-45.412 5.171-31.6 28.909-55.097 28.909-55.097s-0.184-22.213-8.263-23.498c-25.743-4.096-121.126-46.097-123.14-92.506 12.25-7.078 24.956-13.416 38.098-18.975 42.383-17.925 87.429-27.015 133.886-27.015zM455.032 312.5h-40.004v40.005c0.001 11.045-8.953 19.996-19.998 19.996-11.044 0-19.999-8.953-19.999-19.998v-40.003h-40.001c-11.047 0-20-8.954-19.999-20-0.001-11.045 8.952-19.998 19.998-19.998h40.002v-40.001c0-11.047 8.954-20 20-20s19.998 8.953 19.998 19.998v40.003h40.005c11.045-0.001 19.997 8.953 19.997 19.998s-8.954 20-19.999 20z" />
|
||||
<glyph unicode="" d="M198.229 404.257l13.884-13.884c11.64-11.645 27.131-18.058 43.621-18.058 0.159 0 0.318 0 0.479 0.002 0.146-0.001 0.29-0.002 0.436-0.002 16.495 0 31.988 6.415 43.61 18.049l13.805 13.802c9.792-3.147 19.291-7.096 28.446-11.821v-19.988c0-16.439 6.703-32.402 18.421-43.944 11.536-11.692 27.483-18.381 43.902-18.381l19.721-0.001c4.584-8.953 8.426-18.231 11.507-27.787l-13.838-13.838c-11.611-11.612-18.159-27.621-18.047-44.048-0.124-16.442 6.422-32.467 18.047-44.095l13.964-13.964c-3.149-9.852-7.106-19.406-11.852-28.615l-19.492-0.001c-0.004 0-0.006 0-0.011 0-16.42 0-32.37-6.69-43.907-18.388-11.715-11.54-18.415-27.5-18.415-43.938v-19.558c-9.19-4.743-18.728-8.703-28.561-11.857l-13.674 13.673c-11.639 11.65-27.132 18.065-43.627 18.065-0.146 0-0.29-0.001-0.436-0.002-0.159 0.002-0.318 0.002-0.479 0.002-16.489 0-31.981-6.413-43.614-18.051l-13.776-13.777c-9.937 3.169-19.572 7.16-28.854 11.951l-0.001 19.065c0.006 16.427-6.684 32.382-18.386 43.923-11.541 11.715-27.502 18.417-43.939 18.417h-19.253c-4.888 9.423-8.949 19.21-12.164 29.312l13.745 13.745c11.623 11.624 18.169 27.648 18.044 44.091 0.112 16.427-6.436 32.436-18.046 44.047l-13.615 13.616c3.145 9.806 7.091 19.314 11.818 28.483h19.471c16.439 0 32.401 6.701 43.942 18.419 11.699 11.543 18.389 27.497 18.383 43.905l0.001 19.514c9.246 4.773 18.844 8.753 28.74 11.917zM210.743 449.896c-29.966-5.973-57.829-17.758-82.376-34.134l-0.002-42.933c0.002-5.838-2.443-11.097-6.353-14.84-3.743-3.915-9.006-6.364-14.851-6.364h-42.903c-16.312-24.473-28.066-52.242-34.044-82.102l30.195-30.197c4.128-4.128 6.117-9.575 5.999-14.984 0.123-5.415-1.867-10.869-5.999-15.002l-30.281-30.28c5.985-30.201 17.87-58.276 34.413-82.974h42.62c5.845 0 11.107-2.45 14.851-6.365 3.909-3.741 6.354-8.999 6.353-14.838l0.002-42.502c24.581-16.398 52.488-28.193 82.503-34.158l30.327 30.328c4.014 4.016 9.275 6.007 14.536 6.007 0.156 0 0.31-0.002 0.465-0.005 0.149 0.003 0.301 0.005 0.45 0.005 5.263 0 10.523-1.991 14.535-6.007l30.271-30.267c29.89 5.984 57.688 17.756 82.178 34.095v42.978c0 5.845 2.45 11.107 6.365 14.851 3.743 3.909 9.001 6.354 14.839 6.353l42.938 0.002c16.334 24.516 28.091 52.337 34.052 82.252l-30.525 30.526c-4.133 4.133-6.122 9.587-6 15.002-0.118 5.409 1.871 10.856 6 14.984l30.441 30.444c-5.955 29.572-17.579 57.089-33.685 81.379l-43.222 0.002c-0.002 0-0.004 0-0.004 0-5.837 0-11.094 2.445-14.835 6.354-3.915 3.743-6.365 9.006-6.365 14.851v43.408c-24.456 16.316-52.209 28.079-82.053 34.070l-30.396-30.392c-4.012-4.016-9.273-6.007-14.535-6.007-0.15 0-0.301 0.002-0.45 0.006-0.154-0.004-0.309-0.006-0.465-0.006-5.261 0-10.522 1.991-14.536 6.007l-30.453 30.453zM255.928 322.764c-54.507 0-98.693-44.186-98.693-98.692s44.187-98.691 98.693-98.691v-0.067c0.373 0 0.746-0.006 1.12-0.002 7.403 0.080 14.607 0.971 21.528 2.591 0.511 0.119 0.966 0.248 1.397 0.381 8.664 2.494 14.97 10.506 14.869 19.958-0.121 11.355-9.423 20.463-20.778 20.343-1.498-0.016-2.951-0.201-4.354-0.521-0.045-0.008-0.089 0-0.133-0.011-4.090-0.995-8.354-1.548-12.736-1.612-0.293 0.037-0.595 0.062-0.913 0.062-31.743 0-57.571 25.825-57.571 57.569s25.828 57.571 57.571 57.571c31.744 0 57.57-25.826 57.57-57.571 0-4.462-0.514-8.808-1.482-12.979-0.010-0.045-0.004-0.089-0.010-0.134-0.305-1.406-0.474-2.862-0.474-4.36 0-11.355 9.204-20.561 20.561-20.561 9.453 0 17.396 6.389 19.798 15.079 0.131 0.433 0.254 0.89 0.368 1.402 1.546 6.938 2.361 14.15 2.361 21.553 0 54.506-44.186 98.692-98.692 98.692z" />
|
||||
<glyph unicode="" d="M256 111.438c-11.047-0.001-20.002 8.953-20 20v120c-0.002 11.046 8.953 20.001 20 20.001v0c11.045-0.001 20-8.954 20-20.001l-0.002-120.001c0.002-11.044-8.953-19.999-19.998-19.999v0zM459.75 367.396h-107.75v60.040c0 10.172-7.596 18.548-17.418 19.816-0.848 0.108-1.705 0.186-2.582 0.186h-152.002c-0.877 0-1.734-0.076-2.582-0.186-9.822-1.27-17.418-9.646-17.418-19.814v-60.042h-107.998c-11.045 0-20-8.956-20-20.001s8.955-20 20-20h13.608l26.958-307.957h0.107c0-11.046 8.955-20 20-20h286.686c11.047 0 20 8.955 20 20h0.074l26.958 307.957h13.358c11.045 0 20 8.955 20 20s-8.954 20.001-19.999 20.001zM199.998 407.437h112.002v-40.041h-112.002v40.041zM381.031 39.438h-250.062l-25.207 287.956h300.477l-25.208-287.956zM336.002 111.438c11.045 0.001 20 8.955 19.998 19.999l0.002 120.001c0 11.047-8.955 20-20 20.001-11.047 0-20.002-8.955-20-20.001v-120c-0.002-11.047 8.953-20.001 20-20zM175.998 111.438c11.045 0.001 20 8.955 19.998 19.999l0.002 120.001c0 11.047-8.955 20-20 20.001-11.047 0-20.002-8.955-20-20.001v-120c-0.002-11.047 8.953-20.001 20-20zM256 111.438c11.045 0.001 20 8.955 19.998 19.999l0.002 120.001c0 11.047-8.955 20-20 20.001-11.047 0-20.002-8.955-20-20.001v-120c-0.002-11.047 8.953-20.001 20-20z" />
|
||||
<glyph unicode="" d="M459.75 367.396h-107.75v60.040c0 10.172-7.596 18.548-17.418 19.816-0.848 0.108-1.705 0.186-2.582 0.186h-152.002c-0.877 0-1.734-0.076-2.582-0.186-9.822-1.27-17.418-9.646-17.418-19.814v-60.042h-107.998c-11.045 0-20-8.956-20-20.001s8.955-20 20-20h13.608l26.958-307.957h0.107c0-11.046 8.955-20 20-20h286.686c11.047 0 20 8.955 20 20h0.074l26.958 307.957h13.358c11.045 0 20 8.955 20 20s-8.954 20.001-19.999 20.001zM199.998 407.437h112.002v-40.041h-112.002v40.041zM381.031 39.438h-250.062l-25.207 287.956h300.477l-25.208-287.956zM336.002 111.438c11.045 0.001 20 8.955 19.998 19.999l0.002 120.001c0 11.047-8.955 20-20 20.001-11.047 0-20.002-8.955-20-20.001v-120c-0.002-11.047 8.953-20.001 20-20zM175.998 111.438c11.045 0.001 20 8.955 19.998 19.999l0.002 120.001c0 11.047-8.955 20-20 20.001-11.047 0-20.002-8.955-20-20.001v-120c-0.002-11.047 8.953-20.001 20-20zM256 111.438c11.045 0.001 20 8.955 19.998 19.999l0.002 120.001c0 11.047-8.955 20-20 20.001-11.047 0-20.002-8.955-20-20.001v-120c-0.002-11.047 8.953-20.001 20-20z" />
|
||||
<glyph unicode="" d="M474.28 348.312c6.352 6.354 7.536 15.918 3.555 23.468-0.92 1.762-2.116 3.416-3.596 4.896-0.143 0.143-0.297 0.264-0.443 0.4l-64.659 64.317c-0.024 0.024-0.044 0.053-0.069 0.077-3.906 3.906-9.025 5.858-14.146 5.857-5.121 0.002-10.242-1.951-14.148-5.857-0.032-0.033-0.060-0.068-0.092-0.102l-318.084-318.084c-2.934-2.567-5.105-5.979-6.149-9.874l-23.803-88.832c-1.85-6.902 0.124-14.267 5.176-19.319 3.801-3.8 8.908-5.857 14.144-5.857 1.726 0 3.465 0.223 5.176 0.682l88.832 23.803c3.648 0.978 6.866 2.952 9.37 5.608l260.743 260.742c0.563 0.452 1.111 0.935 1.634 1.457 0.521 0.522 1.003 1.069 1.455 1.632l53.875 53.874c0.418 0.355 0.834 0.716 1.229 1.112zM403.45 334.17l-36.796 36.601 28.305 28.305 36.797-36.6-28.306-28.306zM140.783 71.502l-36.7 36.7 234.286 234.284 36.797-36.601-234.383-234.383zM80.248 47.686l5.871 21.911 16.040-16.040-21.911-5.871z" />
|
||||
<glyph unicode="" d="M256 408c49.148 0 95.354-19.14 130.107-53.892 34.753-34.754 53.893-80.961 53.893-130.108 0-49.148-19.14-95.354-53.893-130.107s-80.959-53.893-130.107-53.893c-49.147 0-95.354 19.14-130.108 53.893-34.752 34.754-53.892 80.959-53.892 130.107s19.14 95.354 53.892 130.108c34.754 34.752 80.961 53.892 130.108 53.892zM256 448c-123.712 0-224-100.288-224-224s100.288-224 224-224 224 100.288 224 224-100.288 224-224 224v0zM364.501 243.5h-88.004v88.004c0.001 11.045-8.953 19.997-19.998 19.997-11.044 0-19.999-8.954-19.999-19.999v-88.002h-88c-11.047 0-20-8.954-19.999-20-0.001-11.045 8.952-19.998 19.998-19.998h88.001v-88.002c0-11.047 8.954-20 20-19.999 11.045-0.001 19.998 8.952 19.998 19.998v88.003h88.006c11.045-0.001 19.997 8.953 19.997 19.998s-8.955 20-20 20z" />
|
||||
<glyph unicode="" d="M460.501 243.5h-184.004v184.002c0.001 11.045-8.953 19.998-19.998 19.998-11.044 0-19.999-8.955-19.999-20v-184h-184.001c-11.047 0-20-8.954-19.999-20-0.001-11.045 8.952-19.998 19.998-19.998l184.002 0.001v-184.005c0-11.047 8.954-20 20-19.998 11.045-0.002 19.998 8.951 19.998 19.998v184.005h184.005c11.045-0.001 19.997 8.953 19.997 19.998 0 11.044-8.954 19.999-19.999 19.999z" />
|
||||
<glyph unicode="" d="M346.511 161.067c7.81-7.811 7.809-20.475 0-28.283-7.811-7.811-20.473-7.812-28.281-0.001l-62.23 62.229-62.228-62.229c-7.811-7.811-20.472-7.811-28.281 0-7.812 7.811-7.812 20.473-0.001 28.284l62.227 62.228-62.226 62.225c-7.811 7.811-7.811 20.473 0 28.282 7.81 7.812 20.472 7.812 28.284 0.001l62.225-62.225 62.227 62.226c7.811 7.81 20.475 7.81 28.283 0 7.811-7.81 7.812-20.472 0.001-28.28l-62.228-62.229 62.228-62.228zM414.392 65.608c-87.478-87.478-229.307-87.478-316.783 0-87.479 87.478-87.479 229.307 0 316.783 87.477 87.479 229.306 87.479 316.783 0 87.477-87.476 87.477-229.306 0-316.783zM440 224.001c-0.001 49.148-19.14 95.354-53.893 130.106s-80.96 53.893-130.107 53.894c-49.148-0.001-95.355-19.141-130.108-53.893-34.753-34.754-53.891-80.959-53.893-130.107 0.001-49.148 19.141-95.355 53.893-130.108 34.754-34.753 80.959-53.892 130.108-53.892 49.148 0 95.354 19.139 130.107 53.892s53.892 80.96 53.893 130.108z" />
|
||||
<glyph unicode="" d="M506.643 2.142l-221.86 221.858 221.859 221.859c7.811 7.811 7.81 20.474-0.002 28.283-7.809 7.811-20.471 7.811-28.281 0l-221.858-221.859-221.86 221.859c-7.81 7.812-20.473 7.811-28.283 0s-7.811-20.472 0-28.283l221.861-221.859-221.861-221.862c-7.811-7.809-7.81-20.471 0-28.28s20.474-7.811 28.283 0l221.86 221.859 221.861-221.859c7.809-7.812 20.471-7.811 28.28 0 7.81 7.81 7.811 20.473 0.001 28.284z" />
|
||||
<glyph unicode="" d="M499.391 271.027c-7.811 7.811-20.475 7.811-28.283 0l-10.712-10.712c-18.178 96.329-102.752 169.196-204.364 169.196-80.473 0-150.266-45.701-184.855-112.564-2.398-4.639-2.137-4.182-2.502-4.998-0.018-0.039-0.035-0.078-0.053-0.117-0.008-0.016-0.012-0.029-0.020-0.045l0.002-0.002c-0.992-2.373-1.543-4.975-1.543-7.707 0-11.047 8.955-20 20-20 7.656 0 14.299 4.305 17.66 10.621l0.004-0.002c8.094 16.695 19.006 32.102 32.512 45.607 31.73 31.732 73.92 49.207 118.795 49.207 44.873 0 87.062-17.475 118.793-49.207 22.796-22.794 38.222-50.988 45.108-81.697l-13.073 13.074c-7.811 7.812-20.475 7.811-28.285 0-7.812-7.811-7.812-20.475 0-28.285l46.15-46.148c4.020-4.021 9.324-5.955 14.592-5.838 5.264-0.113 10.562 1.82 14.576 5.838l45.5 45.494c7.81 7.811 7.808 20.475-0.002 28.285zM424.996 158.945c-7.656 0-14.299-4.305-17.662-10.621l-0.004 0.002c-8.092-16.697-19.004-32.104-32.51-45.609-31.732-31.73-73.92-49.205-118.795-49.205-44.873 0-87.062 17.475-118.793 49.205-24.116 24.116-39.99 54.273-46.224 87.058l14.646-14.646c7.811-7.811 20.475-7.809 28.283 0.002 7.812 7.811 7.812 20.475 0 28.283l-46.148 46.15c-4.021 4.020-9.326 5.955-14.594 5.836-5.262 0.115-10.561-1.82-14.576-5.836l-45.498-45.496c-7.811-7.811-7.809-20.475 0-28.285 7.811-7.811 20.475-7.811 28.285 0l9.739 9.739c17.046-97.722 102.28-172.011 204.88-172.011 80.473 0 150.266 45.701 184.854 112.562 2.4 4.641 2.139 4.182 2.504 5 0.016 0.039 0.035 0.078 0.053 0.117 0.006 0.016 0.012 0.027 0.020 0.045l-0.004 0.002c0.992 2.371 1.545 4.975 1.545 7.707-0.001 11.046-8.956 20.001-20.001 20.001zM73.203 207.58l0.412-0.412-0.7 0.124 0.288 0.288z" />
|
||||
<glyph unicode="" d="M448.016 22.235v233.749c0 9.551-6.701 17.526-15.655 19.513-0.105 0.023-0.207 0.060-0.314 0.081-0.222 0.045-0.452 0.065-0.677 0.104-1.093 0.185-2.208 0.303-3.354 0.303h-27.951l0.001 27.925h0.010c0 79.57-64.505 144.075-144.075 144.075-79.564 0-144.065-64.496-144.075-144.059v-27.942h-27.426c-10.355 0-18.873-7.871-19.896-17.955-0.068-0.672-0.104-1.354-0.104-2.045v-231.666c-0.309-1.396-0.484-2.844-0.484-4.334 0-11.047 8.955-20 20-20h344.134c11.046 0 20 8.955 20 20 0 0.762-0.051 1.512-0.134 2.251zM104.5 235.984h303.516v-196h-303.516v196zM151.925 303.909c0 57.388 46.688 104.075 104.075 104.075 57.295 0 103.921-46.537 104.071-103.798 0-0.042-0.006-0.082-0.006-0.124v-28.078h-208.141l0.001 27.925zM276.082 134.071l-0.001-29.094c0.002-11.044-8.953-19.998-19.998-19.999-11.047-0.001-20.002 8.953-20 20v28.987c-7.352 5.863-12.067 14.891-12.067 25.024 0 17.673 14.327 32 32 32s32-14.327 32-32c0-10.071-4.659-19.052-11.934-24.918z" />
|
||||
<glyph unicode="" d="M474.299 380.125c-7.811 7.809-20.475 7.809-28.285 0l-267.822-267.822-112.030 112.031c-7.812 7.812-20.477 7.81-28.285 0-7.812-7.81-7.812-20.474 0-28.284l125.787-125.787c0.126-0.133 0.236-0.275 0.367-0.406 3.91-3.91 9.036-5.862 14.161-5.857 5.125-0.005 10.251 1.947 14.161 5.857 0.124 0.124 0.228 0.259 0.348 0.385l281.598 281.6c7.81 7.81 7.81 20.471 0 28.283z" />
|
||||
<glyph unicode="" d="M447.999 20.078v279.922c0 11.045-8.955 20-20 20h-89.329c-11.047 0-20-8.957-20-20.002s8.955-20 20-20h69.329v-239.998h-303.999v239.998h68.665c11.046 0 20 8.955 20 20s-8.954 20-20 20.002h-89.33c-11.046 0-20-8.957-20-20.002 0-1.743 0.246-3.424 0.665-5.037v-274.961c0-11.047 8.955-20 20-20h344.003c11.045 0 20 8.955 20 20 0 0.026-0.004 0.052-0.004 0.078zM332.811 379.917l-62.226 62.225c-4.020 4.021-9.325 5.956-14.593 5.837-0.806 0.017-1.611 0-2.414-0.080-0.279-0.027-0.549-0.080-0.825-0.119-0.371-0.052-0.742-0.096-1.109-0.169-0.328-0.065-0.645-0.155-0.966-0.236-0.311-0.078-0.623-0.146-0.93-0.239-0.32-0.098-0.63-0.218-0.943-0.33-0.302-0.108-0.605-0.207-0.902-0.33-0.299-0.124-0.585-0.27-0.877-0.407-0.299-0.141-0.6-0.273-0.893-0.43-0.29-0.155-0.566-0.332-0.847-0.5-0.277-0.166-0.558-0.322-0.828-0.503-0.334-0.224-0.65-0.471-0.97-0.713-0.198-0.151-0.404-0.288-0.598-0.447-0.524-0.429-1.027-0.883-1.504-1.363l-62.199-62.195c-7.811-7.811-7.809-20.475 0.001-28.285 7.811-7.811 20.475-7.811 28.284 0l28.082 28.083v-219.713c0-11.047 8.956-20 20.001-20s20 8.955 20 20v220.601l28.971-28.97c7.811-7.812 20.474-7.811 28.284 0 7.813 7.808 7.813 20.472 0.001 28.283z" />
|
||||
<glyph unicode="" d="M480.016 345.999c0.374 5.020-1.123 10.182-4.613 14.342-2.992 3.566-6.969 5.811-11.197 6.697-0.065 0.014-0.134 0.033-0.198 0.047-0.541 0.109-1.086 0.188-1.636 0.25-0.125 0.016-0.246 0.039-0.371 0.051-0.514 0.049-1.026 0.068-1.545 0.078-0.146 0.002-0.291 0.021-0.438 0.021h-408.004c-10.708 0-19.424-8.422-19.949-19-0.017-0.314-0.046-0.629-0.048-0.945 0-0.018-0.003-0.037-0.003-0.057 0-0.025 0.004-0.051 0.004-0.076v-247.846c0-0.027-0.004-0.053-0.004-0.078 0-11.045 8.955-20 20-20h408.002c6.904 0 12.99 3.498 16.585 8.818 0.050 0.074 0.091 0.156 0.14 0.229 0.303 0.465 0.598 0.934 0.861 1.42 0.023 0.041 0.040 0.086 0.062 0.129 1.496 2.803 2.352 6.004 2.352 9.402v0 0 246.518zM72.016 304.922l169.973-140.594c3.284-3.217 7.459-5.084 11.782-5.561 0.080-0.012 0.16-0.025 0.24-0.033 0.419-0.041 0.838-0.057 1.259-0.070 0.248-0.010 0.497-0.029 0.746-0.029s0.498 0.021 0.746 0.029c0.421 0.014 0.84 0.029 1.259 0.070 0.080 0.008 0.16 0.021 0.24 0.033 4.323 0.479 8.498 2.344 11.782 5.561l169.973 140.604v-185.447h-368v185.437zM107.533 327.485h296.955l-148.473-122.711-148.482 122.711z" />
|
||||
<glyph unicode="" d="M256.012 352c5.118 0 10.235-1.952 14.141-5.856l172.077-172.049c7.812-7.81 7.812-20.473 0.003-28.285-7.811-7.811-20.474-7.812-28.284-0.002l-157.938 157.91-157.96-157.934c-7.812-7.809-20.476-7.809-28.284 0.002-7.81 7.812-7.809 20.475 0.003 28.285l172.102 172.072c3.904 3.905 9.022 5.857 14.14 5.857z" />
|
||||
<glyph unicode="" d="M255.988 95.999c-5.118 0-10.235 1.952-14.141 5.856l-172.077 172.049c-7.812 7.81-7.812 20.473-0.003 28.285 7.811 7.811 20.474 7.812 28.284 0.002l157.938-157.91 157.961 157.934c7.812 7.809 20.476 7.808 28.284-0.002 7.81-7.812 7.809-20.475-0.003-28.285l-172.102-172.072c-3.905-3.905-9.023-5.857-14.141-5.857z" />
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 17 KiB |
Binary file not shown.
Binary file not shown.
@@ -4,3 +4,4 @@
|
||||
|
||||
notices-for-0.9.0
|
||||
notices-for-0.9.1
|
||||
0.9.4-platform-file
|
||||
|
||||
2
examples/wordplay/.meteor/platforms
Normal file
2
examples/wordplay/.meteor/platforms
Normal file
@@ -0,0 +1,2 @@
|
||||
server
|
||||
browser
|
||||
@@ -1 +1 @@
|
||||
METEOR@0.9.3
|
||||
METEOR@0.9.4
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
application-configuration@1.0.2
|
||||
autoupdate@1.1.1
|
||||
base64@1.0.0
|
||||
binary-heap@1.0.0
|
||||
blaze-tools@1.0.0
|
||||
blaze@2.0.1
|
||||
boilerplate-generator@1.0.0
|
||||
callback-hook@1.0.0
|
||||
check@1.0.1
|
||||
ctl-helper@1.0.3
|
||||
ctl@1.0.1
|
||||
ddp@1.0.9
|
||||
deps@1.0.4
|
||||
ejson@1.0.3
|
||||
fastclick@1.0.0
|
||||
follower-livedata@1.0.1
|
||||
geojson-utils@1.0.0
|
||||
html-tools@1.0.1
|
||||
htmljs@1.0.1
|
||||
http@1.0.6
|
||||
id-map@1.0.0
|
||||
insecure@1.0.0
|
||||
jquery@1.0.0
|
||||
json@1.0.0
|
||||
livedata@1.0.10
|
||||
logging@1.0.3
|
||||
meteor-platform@1.1.1
|
||||
meteor@1.1.1
|
||||
minifiers@1.1.0
|
||||
minimongo@1.0.3
|
||||
mobile-status-bar@1.0.0
|
||||
mongo@1.0.6
|
||||
observe-sequence@1.0.2
|
||||
ordered-dict@1.0.0
|
||||
random@1.0.0
|
||||
reactive-dict@1.0.3
|
||||
reactive-var@1.0.2
|
||||
reload@1.1.0
|
||||
retry@1.0.0
|
||||
routepolicy@1.0.1
|
||||
session@1.0.2
|
||||
spacebars-compiler@1.0.2
|
||||
spacebars@1.0.2
|
||||
standard-app-packages@1.0.2
|
||||
templating@1.0.7
|
||||
tracker@1.0.2
|
||||
ui@1.0.3
|
||||
underscore@1.0.0
|
||||
url@1.0.0
|
||||
webapp-hashing@1.0.0
|
||||
webapp@1.1.2
|
||||
application-configuration@1.0.3
|
||||
autoupdate@1.1.2
|
||||
base64@1.0.1
|
||||
binary-heap@1.0.1
|
||||
blaze-tools@1.0.1
|
||||
blaze@2.0.2
|
||||
boilerplate-generator@1.0.1
|
||||
callback-hook@1.0.1
|
||||
check@1.0.2
|
||||
ctl-helper@1.0.4
|
||||
ctl@1.0.2
|
||||
ddp@1.0.10
|
||||
deps@1.0.5
|
||||
ejson@1.0.4
|
||||
fastclick@1.0.1
|
||||
follower-livedata@1.0.2
|
||||
geojson-utils@1.0.1
|
||||
html-tools@1.0.2
|
||||
htmljs@1.0.2
|
||||
http@1.0.7
|
||||
id-map@1.0.1
|
||||
insecure@1.0.1
|
||||
jquery@1.0.1
|
||||
json@1.0.1
|
||||
livedata@1.0.11
|
||||
logging@1.0.4
|
||||
meteor-platform@1.1.2
|
||||
meteor@1.1.2
|
||||
minifiers@1.1.1
|
||||
minimongo@1.0.4
|
||||
mobile-status-bar@1.0.1
|
||||
mongo@1.0.7
|
||||
observe-sequence@1.0.3
|
||||
ordered-dict@1.0.1
|
||||
random@1.0.1
|
||||
reactive-dict@1.0.4
|
||||
reactive-var@1.0.3
|
||||
reload@1.1.1
|
||||
retry@1.0.1
|
||||
routepolicy@1.0.2
|
||||
session@1.0.3
|
||||
spacebars-compiler@1.0.3
|
||||
spacebars@1.0.3
|
||||
standard-app-packages@1.0.3
|
||||
templating@1.0.8
|
||||
tracker@1.0.3
|
||||
ui@1.0.4
|
||||
underscore@1.0.1
|
||||
url@1.0.1
|
||||
webapp-hashing@1.0.1
|
||||
webapp@1.1.3
|
||||
|
||||
@@ -228,7 +228,7 @@ Meteor.startup(function () {
|
||||
|
||||
// subscribe to all the players, the game i'm in, and all
|
||||
// the words in that game.
|
||||
Deps.autorun(function () {
|
||||
Tracker.autorun(function () {
|
||||
Meteor.subscribe('players');
|
||||
|
||||
if (Session.get('player_id')) {
|
||||
|
||||
2
meteor
2
meteor
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
BUNDLE_VERSION=0.3.58
|
||||
BUNDLE_VERSION=0.3.59
|
||||
|
||||
# OS Check. Put here because here is where we download the precompiled
|
||||
# bundles that are arch specific.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "A user account system",
|
||||
version: "1.1.2-pre.2"
|
||||
version: "1.1.2"
|
||||
});
|
||||
|
||||
Package.on_use(function (api) {
|
||||
|
||||
@@ -80,6 +80,7 @@ AccountsTest = {
|
||||
* 2. `done`: A function to call when the password reset UI flow is complete. The normal
|
||||
* login process is suspended until this function is called, so that the
|
||||
* password for user A can be reset even if user B was logged in.
|
||||
* @locus Client
|
||||
*/
|
||||
Accounts.onResetPasswordLink = function (callback) {
|
||||
if (accountsCallbacks["reset-password"]) {
|
||||
@@ -104,6 +105,7 @@ Accounts.onResetPasswordLink = function (callback) {
|
||||
* The normal login process is suspended until this function is called, so
|
||||
* that the user can be notified that they are verifying their email before
|
||||
* being logged in.
|
||||
* @locus Client
|
||||
*/
|
||||
Accounts.onEmailVerificationLink = function (callback) {
|
||||
if (accountsCallbacks["verify-email"]) {
|
||||
@@ -128,6 +130,7 @@ Accounts.onEmailVerificationLink = function (callback) {
|
||||
* 2. `done`: A function to call when the enrollment UI flow is complete.
|
||||
* The normal login process is suspended until this function is called, so that
|
||||
* user A can be enrolled even if user B was logged in.
|
||||
* @locus Client
|
||||
*/
|
||||
Accounts.onEnrollmentLink = function (callback) {
|
||||
if (accountsCallbacks["enroll-account"]) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Login service for Facebook accounts",
|
||||
version: "1.0.2-pre.2"
|
||||
version: "1.0.2"
|
||||
});
|
||||
|
||||
Package.on_use(function(api) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Login service for Github accounts",
|
||||
version: "1.0.2-pre.2"
|
||||
version: "1.0.2"
|
||||
});
|
||||
|
||||
Package.on_use(function(api) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Login service for Google accounts",
|
||||
version: "1.0.2-pre.2"
|
||||
version: "1.0.2"
|
||||
});
|
||||
|
||||
Package.on_use(function(api) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Login service for Meetup accounts",
|
||||
version: "1.0.2-pre.2"
|
||||
version: "1.0.2"
|
||||
});
|
||||
|
||||
Package.on_use(function(api) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Login service for Meteor developer accounts",
|
||||
version: "1.0.2-pre.2"
|
||||
version: "1.0.2"
|
||||
});
|
||||
|
||||
Package.on_use(function (api) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Package.describe({
|
||||
summary: "Common code for OAuth-based login services",
|
||||
version: "1.1.2-pre.2"
|
||||
version: "1.1.2"
|
||||
});
|
||||
|
||||
Package.on_use(function (api) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user