├── .editorconfig ├── .eslintrc ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── Bugs.yml │ ├── Documentation.yml │ ├── Features.yml │ └── config.yml └── workflows │ └── tests.yml ├── .gitignore ├── CNAME ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── backbone-min.js ├── backbone-min.js.map ├── backbone-min.map ├── backbone.js ├── bower.json ├── debug-info.js ├── docs ├── backbone.html ├── backbone.localStorage.html ├── docco.css ├── examples │ ├── backbone.localStorage.html │ └── todos │ │ └── todos.html ├── images │ ├── airbnb.png │ ├── arrows.png │ ├── artsy.jpg │ ├── backbone.png │ ├── background.png │ ├── basecamp-calendar.jpg │ ├── bitbucket.jpg │ ├── blossom.jpg │ ├── cloudapp.jpg │ ├── code-school.jpg │ ├── dc-workspace.jpg │ ├── delicious.jpg │ ├── disqus.jpg │ ├── earth.jpg │ ├── easel.jpg │ ├── enigma.jpg │ ├── flow.jpg │ ├── foursquare.jpg │ ├── gawker.jpg │ ├── gilt.jpg │ ├── groupon.jpg │ ├── hulu.jpg │ ├── inkling.jpg │ ├── intro-collections.svg │ ├── intro-model-view.svg │ ├── intro-routing.svg │ ├── intro-views.svg │ ├── irccloud.png │ ├── jolicloud.jpg │ ├── khan-academy.jpg │ ├── newsblur.jpg │ ├── pandora.jpg │ ├── pitchfork.jpg │ ├── quartz.jpg │ ├── rdio.jpg │ ├── salon.jpg │ ├── seatgeek.jpg │ ├── slavery-footprint.jpg │ ├── soundcloud.png │ ├── spin.jpg │ ├── stripe.png │ ├── tilemill.jpg │ ├── todos.jpg │ ├── trello.jpg │ ├── tzigla.jpg │ ├── usa-today.jpg │ ├── vox.jpg │ ├── walmart-mobile.png │ ├── wpcom-notifications.jpg │ └── zocdoc.jpg ├── js │ └── jquery.lazyload.js ├── public │ ├── fonts │ │ ├── aller-bold.eot │ │ ├── aller-bold.ttf │ │ ├── aller-bold.woff │ │ ├── aller-light.eot │ │ ├── aller-light.ttf │ │ ├── aller-light.woff │ │ ├── roboto-black.eot │ │ ├── roboto-black.ttf │ │ └── roboto-black.woff │ ├── images │ │ └── grey_@2X.png │ └── stylesheets │ │ └── normalize.css ├── search.js └── todos.html ├── examples ├── backbone.localStorage.js └── todos │ ├── destroy.png │ ├── index.html │ ├── todos.css │ └── todos.js ├── favicon.ico ├── index.html ├── karma.conf-sauce.js ├── karma.conf.js ├── modules ├── .eslintrc ├── debug-info.js └── package.json ├── package-lock.json ├── package.json └── test ├── .eslintrc ├── collection.js ├── debuginfo.js ├── events.js ├── index.html ├── model.coffee ├── model.js ├── noconflict.js ├── router.js ├── setup ├── dom-setup.js └── environment.js ├── sync.js ├── vendor ├── jquery.js ├── json2.js ├── qunit.css ├── qunit.js ├── require.js └── underscore.js └── view.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | indent_style = space 11 | indent_size = 2 12 | charset = utf-8 13 | insert_final_newline = true 14 | trim_trailing_whitespace = true 15 | 16 | [**/package.json] 17 | indent_size = 2 18 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true, 5 | "amd": true 6 | }, 7 | "globals": { 8 | "attachEvent": false, 9 | "detachEvent": false 10 | }, 11 | "rules": { 12 | "array-bracket-spacing": 2, 13 | "block-scoped-var": 2, 14 | "brace-style": [1, "1tbs", {"allowSingleLine": true}], 15 | "camelcase": 2, 16 | "comma-dangle": [2, "never"], 17 | "comma-spacing": 2, 18 | "computed-property-spacing": [2, "never"], 19 | "dot-notation": [2, { "allowKeywords": false }], 20 | "eol-last": 2, 21 | "eqeqeq": [2, "smart"], 22 | "indent": [2, 2, { 23 | "MemberExpression": 0, 24 | "SwitchCase": 1, 25 | "VariableDeclarator": 2 26 | }], 27 | "key-spacing": 1, 28 | "keyword-spacing": [2, { "after": true }], 29 | "linebreak-style": 2, 30 | "max-depth": [1, 4], 31 | "max-params": [1, 5], 32 | "new-cap": [2, {"newIsCapExceptions": ["model"]}], 33 | "no-alert": 2, 34 | "no-caller": 2, 35 | "no-catch-shadow": 2, 36 | "no-console": 2, 37 | "no-debugger": 2, 38 | "no-delete-var": 2, 39 | "no-div-regex": 1, 40 | "no-dupe-args": 2, 41 | "no-dupe-keys": 2, 42 | "no-duplicate-case": 2, 43 | "no-else-return": 1, 44 | "no-empty-character-class": 2, 45 | "no-eval": 2, 46 | "no-ex-assign": 2, 47 | "no-extend-native": 2, 48 | "no-extra-boolean-cast": 2, 49 | "no-extra-parens": 1, 50 | "no-extra-semi": 2, 51 | "no-fallthrough": 2, 52 | "no-floating-decimal": 2, 53 | "no-func-assign": 2, 54 | "no-implied-eval": 2, 55 | "no-inner-declarations": 2, 56 | "no-irregular-whitespace": 2, 57 | "no-label-var": 2, 58 | "no-labels": 2, 59 | "no-lone-blocks": 2, 60 | "no-lonely-if": 2, 61 | "no-multi-str": 2, 62 | "no-native-reassign": 2, 63 | "no-negated-in-lhs": 1, 64 | "no-new-object": 2, 65 | "no-new-wrappers": 2, 66 | "no-obj-calls": 2, 67 | "no-octal": 2, 68 | "no-octal-escape": 2, 69 | "no-proto": 2, 70 | "no-redeclare": 2, 71 | "no-shadow": 2, 72 | "no-spaced-func": 2, 73 | "no-throw-literal": 2, 74 | "no-trailing-spaces": 2, 75 | "no-undef": 2, 76 | "no-undef-init": 2, 77 | "no-undefined": 2, 78 | "no-unneeded-ternary": 2, 79 | "no-unreachable": 2, 80 | "no-unused-expressions": [2, {"allowTernary": true, "allowShortCircuit": true}], 81 | "no-with": 2, 82 | "object-curly-spacing": [2, "never"], 83 | "quote-props": [1, "consistent-as-needed", {"keywords": true}], 84 | "quotes": [2, "single", "avoid-escape"], 85 | "radix": 2, 86 | "semi": 2, 87 | "space-before-function-paren": [2, {"anonymous": "never", "named": "never"}], 88 | "space-infix-ops": 2, 89 | "space-unary-ops": [2, { "words": true, "nonwords": false }], 90 | "use-isnan": 2, 91 | "valid-typeof": 2, 92 | "wrap-iife": [2, "inside"] 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | tidelift: "npm/backbone" 2 | patreon: juliangonggrijp 3 | github: [jgonggrijp] 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Bugs.yml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: | 3 | Report something that is not working correctly. 4 | Not intended for security issues! 5 | title: Foo.bar should bazoonite, but frobulates instead 6 | body: 7 | - type: markdown 8 | attributes: 9 | value: " 10 | Thank you for taking the effort to report a bug.\n\n 11 | 12 | Is your bug a security issue? In that case, **please do not use this 13 | form!** Instead, see the [security 14 | policy](https://github.com/jashkenas/backbone/security/policy) on how to 15 | report the issue.\n\n 16 | 17 | ## Identification\n\n 18 | 19 | To start, some quick questions to pinpoint the issue." 20 | - type: input 21 | id: component 22 | attributes: 23 | label: Affected component 24 | description: > 25 | Which part of Backbone is affected? Please be as specific as possible, 26 | for example “the silent option of Collection.reset” or 27 | “importing Backbone with require.js”. 28 | placeholder: the sync event triggered after Model.fetch 29 | validations: 30 | required: true 31 | - type: input 32 | id: expected 33 | attributes: 34 | label: Expected behavior 35 | description: | 36 | In one sentence, what *should* the affected component do? 37 | placeholder: | 38 | Forward all options passed to Model.fetch to the event handler 39 | validations: 40 | required: true 41 | - type: input 42 | id: actual 43 | attributes: 44 | label: Actual behavior 45 | description: | 46 | In one sentence, what does the affected component *actually* do? 47 | placeholder: | 48 | Forward options to the method called last, e.g. save. 49 | validations: 50 | required: true 51 | - type: markdown 52 | attributes: 53 | value: " 54 | After filling the above three fields, please review the issue title. It 55 | should be short, including elements of all three fields and not much 56 | else.\n\n 57 | 58 | For example: **After Model.fetch, sync event may include 59 | options of a later sync, save or destroy call**\n\n 60 | 61 | ## Context" 62 | - type: textarea 63 | id: docs 64 | attributes: 65 | label: Relevant documentation 66 | description: | 67 | Which documentation, if any, did you base your above expectation on? 68 | Provide one link per line. 69 | placeholder: | 70 | - https://backbonejs.org/#Model-fetch 71 | - https://backbonejs.org/#Events-catalog 72 | - type: textarea 73 | id: stack 74 | attributes: 75 | label: Software stack 76 | description: " 77 | With which version(s) of Backbone, Underscore/Lodash, jQuery/Zepto, 78 | other relevant libraries or tools, your browser, etcetera, did you 79 | experience this problem? Please list one per line, including name, 80 | version number(s) and variant(s) if applicable.\n\n 81 | 82 | **Tip:** if you are using the bleeding-edge version of 83 | Backbone, much of this information can be obtained by using 84 | [debugInfo](https://backbonejs.org/#Utility-Backbone-debugInfo) 85 | and copy-pasting its console output below." 86 | placeholder: " 87 | - Backbone 1.4.1 and latest `master` (commit fcf5df6)\n 88 | - Underscore 1.13.6\n 89 | - jQuery 3.6.3 (slim build)\n 90 | - Marionette 4.1.2\n 91 | - Firefox 100\n 92 | - Node.js 14.6\n 93 | 94 | OR (stretch form field to see example content):\n 95 | 96 | ```json\n 97 | Backbone debug info: {\n 98 | \ \ \"backbone\": \"1.5.0\",\n 99 | \ \ \"distribution\": \"MARK_DEVELOPMENT\",\n 100 | \ \ \"_\": \"lodash 4.17.21\",\n 101 | \ \ \"$\": \"3.6.0\",\n 102 | \ \ \"navigator\": {\n 103 | \ \ \ \ \"userAgent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/116.0\",\n 104 | \ \ \ \ \"platform\": \"MacIntel\",\n 105 | \ \ \ \ \"webdriver\": false\n 106 | \ \ }\n 107 | }\n 108 | ```\n 109 | 110 | - Backbone `master` checked out on August 10, 2023\n 111 | - Marionette 4.1.2" 112 | validations: 113 | required: true 114 | - type: textarea 115 | id: discourse 116 | attributes: 117 | label: Related issues, prior discussion and CCs 118 | description: > 119 | Please list any issue numbers, pull requests or links to discussions 120 | elsewhere on the internet that may be relevant. You can also attract the 121 | attention of other GitHub users by listing their `@handles` here. 122 | placeholder: " 123 | #4229, #3410\n 124 | a Stack Overflow or Matrix link\n 125 | @jgonggrijp" 126 | - type: markdown 127 | attributes: 128 | value: "## Bug details" 129 | - type: input 130 | id: error 131 | attributes: 132 | label: Error 133 | description: > 134 | If possible, name the error that you observed and that anyone trying to 135 | reproduce the bug should look for. 136 | placeholder: TypeError (options.success is not an object) 137 | - type: textarea 138 | id: repro 139 | attributes: 140 | label: Steps to reproduce 141 | description: > 142 | List the minimal steps needed to make the bug happen. Include code 143 | examples as needed. 144 | validations: 145 | required: true 146 | - type: textarea 147 | id: details 148 | attributes: 149 | label: Additional information 150 | description: >- 151 | This is a free-form field where you can add any further details that may 152 | help to understand the bug. For example, you might provide permalinks to 153 | the affected lines of code in your actual project, attach logs or 154 | screenshots, point out things you noticed while debugging, and explain 155 | why the bug is especially problematic for your use case. 156 | - type: markdown 157 | attributes: 158 | value: "## Closing" 159 | - type: textarea 160 | id: solution 161 | attributes: 162 | label: Suggested solution(s) 163 | description: > 164 | If you have any idea on how the problem could (or should) be solved, 165 | please feel welcome to describe it here. Of course, if your idea is very 166 | concrete, you may as well submit a pull request! 167 | - type: textarea 168 | id: remarks 169 | attributes: 170 | label: Other remarks 171 | description: >- 172 | If there is anything else you would like to say about the issue, you can 173 | do so here. 174 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Documentation.yml: -------------------------------------------------------------------------------- 1 | name: Documentation issue 2 | description: >- 3 | Report information that is missing, incomplete, vague, misleading or plain 4 | wrong in online documentation such as the website, the README, the wiki, 5 | etcetera. 6 | body: 7 | - type: markdown 8 | attributes: 9 | value: >- 10 | Thank you for taking the time to help us improve the documentation. 11 | - type: input 12 | id: reference 13 | attributes: 14 | label: Reference to current documentation 15 | description: >- 16 | If you can identify an existing piece of documentation that is lacking, 17 | please provide a URL (or multiple) below. If your report is about 18 | missing information and there is no single obvious place where it should 19 | be added, you can leave this empty. 20 | placeholder: "https://backbonejs.org/#Model-changedAttributes" 21 | - type: textarea 22 | id: quote 23 | attributes: 24 | label: Quote of current documentation 25 | description: >- 26 | If you provided a URL in the previous field, please quote the 27 | problematic documentation below. This ensures that future readers 28 | understand what you were responding to, in case the referred page 29 | disappears or changes content. 30 | placeholder: " 31 | > Retrieve a hash of only the model's attributes that have changed since 32 | the last 33 | [set](https://backbonejs.org/#Model-set), or `false` if there are none. 34 | Optionally, an external **attributes** hash can be passed in, returning 35 | the attributes in that hash which differ from the model. This can be 36 | used to figure out which portions of a view should be updated, or what 37 | calls need to be made to sync the changes to the server." 38 | - type: textarea 39 | id: effect 40 | attributes: 41 | label: Effect of the problem 42 | description: >- 43 | What did you or someone else not know, misunderstand or falsely believe 44 | due to the current state of the documentation? How has this misguided 45 | your or someone else's behavior? 46 | placeholder: >- 47 | I did not know that I could ..., so I needlessly ... 48 | validations: 49 | required: true 50 | - type: textarea 51 | id: cause 52 | attributes: 53 | label: Cause of the problem 54 | description: >- 55 | What is it about the current documentation that caused your problem? 56 | What is missing, ambiguous or wrong? Pinpoint specific words or phrases 57 | if possible. 58 | placeholder: >- 59 | It says "...", which seems to suggest that ..., while actually, ... 60 | validations: 61 | required: true 62 | - type: textarea 63 | id: suggestion 64 | attributes: 65 | label: Suggestion 66 | description: >- 67 | If you have any idea on how the documentation could be improved, please 68 | share it here. Of course, if your idea is very concrete, you can also 69 | submit a pull request! 70 | - type: textarea 71 | id: remarks 72 | attributes: 73 | label: Other remarks 74 | description: >- 75 | If there is anything else you would like to say about the issue, you can 76 | do so here. 77 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Features.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: >- 3 | Tell us about functionality that you miss in Backbone. 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Thank you for proposing a new feature. 9 | 10 | Let us begin with the end in mind. 11 | - type: textarea 12 | id: goal 13 | attributes: 14 | label: Ultimate goal 15 | description: >- 16 | This first question is not about Backbone but about the mission that you 17 | hope to accomplish with Backbone. What work do you need to get done? 18 | placeholder: | 19 | GOOD: I work on an application that needs to ... 20 | BAD (later question): I think Backbone.Collection should have a method that ... 21 | validations: 22 | required: true 23 | - type: textarea 24 | id: shortcoming 25 | attributes: 26 | label: Shortcomings 27 | description: >- 28 | Working towards your end goal, what task is currently difficult to 29 | achieve with Backbone as it is? Which features in Backbone or other 30 | libraries are currently available to you, which do not quite do what you 31 | need? 32 | placeholder: | 33 | In my application, I need to ..., but when I define a 34 | Backbone.Collection subclass, there does not seem to be any way to ... 35 | 36 | - I could use `Collection.slice`, but ... 37 | - I could use , but ... 38 | validations: 39 | required: true 40 | - type: textarea 41 | id: justification 42 | attributes: 43 | label: Justification 44 | description: >- 45 | Why do you believe that the missing functionality belongs in Backbone 46 | proper? Why could or should it not be provided by another library or 47 | tool? 48 | validations: 49 | required: true 50 | - type: textarea 51 | id: proposal 52 | attributes: 53 | label: Proposal 54 | description: >- 55 | Go ahead, describe your ideal solution. Show what it should look like 56 | and explain how it should behave. 57 | validations: 58 | required: true 59 | - type: textarea 60 | id: alternatives 61 | attributes: 62 | label: Possible alternatives 63 | description: >- 64 | Can you think of other ways in which your desired functionality could be 65 | provided? If they appeal less to you, why is this the case? 66 | - type: textarea 67 | id: remarks 68 | attributes: 69 | label: Other remarks 70 | description: >- 71 | If there is anything else you would like to say about your feature 72 | request, you can do so here. 73 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | contact_links: 2 | - name: Security issue 3 | url: https://github.com/jashkenas/backbone/security/policy 4 | about: Go here if you would like to report a security issue. 5 | - name: Stack Overflow 6 | url: https://stackoverflow.com/questions/tagged/backbone.js 7 | about: The best place to get help making your code work (be sure to include the `backbone.js` tag). 8 | - name: Matrix/Gitter 9 | url: https://matrix.to/#/#jashkenas_backbone:gitter.im 10 | about: Discussions about, and general help with, Backbone. 11 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | paths: 11 | - '.github/workflows/**' 12 | - 'test/**' 13 | - '*.js' 14 | - 'package.json' 15 | 16 | jobs: 17 | tests: 18 | env: 19 | NPM_CONFIG_PROGRESS: "false" 20 | 21 | runs-on: ubuntu-latest 22 | 23 | steps: 24 | - uses: actions/checkout@v4 25 | - uses: actions/setup-node@v4 26 | with: 27 | node-version: 16 28 | cache: 'npm' 29 | - name: Install dependencies 30 | run: | 31 | npm ci 32 | npm install --no-audit karma-cli karma-sauce-launcher 33 | - name: Test in Sauce Labs 34 | run: BUILD_NUMBER="$GITHUB_RUN_NUMBER" BUILD_ID="$GITHUB_RUN_ID" JOB_NUMBER="$GITHUB_JOB" ./node_modules/.bin/karma start karma.conf-sauce.js 35 | env: 36 | SAUCE_USERNAME: ${{ secrets.SauceUsername }} 37 | SAUCE_ACCESS_KEY: ${{ secrets.SauceAccessKey }} 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | raw 2 | *.sw? 3 | .DS_Store 4 | node_modules 5 | bower_components 6 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | backbonejs.org -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, visible or invisible disability, ethnicity, sex characteristics, gender 9 | identity and expression, level of experience, education, socio-economic status, 10 | nationality, personal appearance, race, caste, color, religion, or sexual 11 | identity and orientation. 12 | 13 | We pledge to act and interact in ways that contribute to an open, welcoming, 14 | diverse, inclusive, and healthy community. 15 | 16 | ## Our Standards 17 | 18 | Examples of behavior that contributes to a positive environment for our 19 | community include: 20 | 21 | * Demonstrating empathy and kindness toward other people 22 | * Being respectful of differing opinions, viewpoints, and experiences 23 | * Giving and gracefully accepting constructive feedback 24 | * Accepting responsibility and apologizing to those affected by our mistakes, 25 | and learning from the experience 26 | * Focusing on what is best not just for us as individuals, but for the overall 27 | community 28 | 29 | Examples of unacceptable behavior include: 30 | 31 | * The use of sexualized language or imagery and sexual attention or advances of 32 | any kind 33 | * Trolling, insulting or derogatory comments, and personal or political attacks 34 | * Public or private harassment 35 | * Publishing others' private information, such as a physical or email address, 36 | without their explicit permission 37 | * Other conduct which could reasonably be considered inappropriate in a 38 | professional setting 39 | 40 | ## Enforcement Responsibilities 41 | 42 | Community leaders are responsible for clarifying and enforcing our standards of 43 | acceptable behavior and will take appropriate and fair corrective action in 44 | response to any behavior that they deem inappropriate, threatening, offensive, 45 | or harmful. 46 | 47 | Community leaders have the right and responsibility to remove, edit, or reject 48 | comments, commits, code, wiki edits, issues, and other contributions that are 49 | not aligned to this Code of Conduct, and will communicate reasons for moderation 50 | decisions when appropriate. 51 | 52 | ## Scope 53 | 54 | This Code of Conduct applies within all community spaces, and also applies 55 | when an individual is representing the project or its community. Examples of 56 | representing a project or community include using an official project e-mail 57 | address, posting via an official social media account, or acting as an appointed 58 | representative at an online or offline event. Representation of a project may be 59 | further defined and clarified by project maintainers. 60 | 61 | ## Enforcement 62 | 63 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 64 | reported to the community leaders responsible for enforcement at 65 | jashkenas@gmail.com. 66 | All complaints will be reviewed and investigated promptly and fairly. 67 | 68 | All community leaders are obligated to respect the privacy and security of the 69 | reporter of any incident. 70 | 71 | ## Enforcement Guidelines 72 | 73 | Community leaders will follow these Community Impact Guidelines in determining 74 | the consequences for any action they deem in violation of this Code of Conduct: 75 | 76 | ### 1. Correction 77 | 78 | **Community Impact**: Use of inappropriate language or other behavior deemed 79 | unprofessional or unwelcome in the community. 80 | 81 | **Consequence**: A private, written warning from community leaders, providing 82 | clarity around the nature of the violation and an explanation of why the 83 | behavior was inappropriate. A public apology may be requested. 84 | 85 | ### 2. Warning 86 | 87 | **Community Impact**: A violation through a single incident or series of 88 | actions. 89 | 90 | **Consequence**: A warning with consequences for continued behavior. No 91 | interaction with the people involved, including unsolicited interaction with 92 | those enforcing the Code of Conduct, for a specified period of time. This 93 | includes avoiding interactions in community spaces as well as external channels 94 | like social media. Violating these terms may lead to a temporary or permanent 95 | ban. 96 | 97 | ### 3. Temporary Ban 98 | 99 | **Community Impact**: A serious violation of community standards, including 100 | sustained inappropriate behavior. 101 | 102 | **Consequence**: A temporary ban from any sort of interaction or public 103 | communication with the community for a specified period of time. No public or 104 | private interaction with the people involved, including unsolicited interaction 105 | with those enforcing the Code of Conduct, is allowed during this period. 106 | Violating these terms may lead to a permanent ban. 107 | 108 | ### 4. Permanent Ban 109 | 110 | **Community Impact**: Demonstrating a pattern of violation of community 111 | standards, including sustained inappropriate behavior, harassment of an 112 | individual, or aggression toward or disparagement of classes of individuals. 113 | 114 | **Consequence**: A permanent ban from any sort of public interaction within the 115 | community. 116 | 117 | ## Moderation 118 | 119 | Edits of another user's comment must be clearly marked with "**edit**", the 120 | moderator's username, and a timestamp for each occurrence. The only acceptable 121 | reasons for editing another user's comment are: 122 | 123 | 1. to edit out violations of Our Pledge. These edits must include a rationale. 124 | 2. to direct future readers to a relevant point later in the conversation 125 | (usually the resolution). These edits must be append-only. 126 | 127 | Deletion of another user's comment is only acceptable when the comment includes 128 | no original value, such as "+1", ":+1:", or "me too". 129 | 130 | ## Self-Moderation 131 | 132 | Edits of your own comment after someone has responded must be append-only and 133 | clearly marked with "**edit**". Typographical and formatting fixes to your own 134 | comment which do not affect its meaning are exempt from this requirement. 135 | Deletion of your own comment is only acceptable before any later comments have 136 | been posted. 137 | 138 | ## Attribution 139 | 140 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 141 | version 2.1, available at 142 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. 143 | 144 | Community Impact Guidelines were inspired by 145 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. 146 | 147 | For answers to common questions about this code of conduct, see the FAQ at 148 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at 149 | [https://www.contributor-covenant.org/translations][translations]. 150 | 151 | [homepage]: https://www.contributor-covenant.org 152 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html 153 | [Mozilla CoC]: https://github.com/mozilla/diversity 154 | [FAQ]: https://www.contributor-covenant.org/faq 155 | [translations]: https://www.contributor-covenant.org/translations 156 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## How to Open a Backbone.js Ticket 2 | 3 | * Do not use tickets to ask for help with (debugging) your application. Ask on 4 | the [mailing list](https://groups.google.com/forum/#!forum/backbonejs), 5 | in the IRC channel (`#documentcloud` on Freenode), or if you understand your 6 | specific problem, on [StackOverflow](http://stackoverflow.com/questions/tagged/backbone.js). 7 | 8 | * Before you open a ticket or send a pull request, 9 | [search](https://github.com/jashkenas/backbone/issues) for previous 10 | discussions about the same feature or issue. Add to the earlier ticket if you 11 | find one. 12 | 13 | * Before sending a pull request for a feature or bug fix, be sure to have 14 | [tests](http://backbonejs.org/test/) and to document any new functionality in 15 | the `index.html`. 16 | 17 | * Use the same coding style as the rest of the 18 | [codebase](https://github.com/jashkenas/backbone/blob/master/backbone.js). 19 | 20 | * In your pull request, do not regenerate the annotated sources or rebuild the 21 | minified `backbone-min.js` file. We'll do that before cutting a new release. 22 | 23 | * All pull requests should be made to the `master` branch. 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2024 Jeremy Ashkenas, DocumentCloud 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ____ __ __ 2 | /\ _`\ /\ \ /\ \ __ 3 | \ \ \ \ \ __ ___\ \ \/'\\ \ \____ ___ ___ __ /\_\ ____ 4 | \ \ _ <' /'__`\ /'___\ \ , < \ \ '__`\ / __`\ /' _ `\ /'__`\ \/\ \ /',__\ 5 | \ \ \ \ \/\ \ \.\_/\ \__/\ \ \\`\\ \ \ \ \/\ \ \ \/\ \/\ \/\ __/ __ \ \ \/\__, `\ 6 | \ \____/\ \__/.\_\ \____\\ \_\ \_\ \_,__/\ \____/\ \_\ \_\ \____\/\_\_\ \ \/\____/ 7 | \/___/ \/__/\/_/\/____/ \/_/\/_/\/___/ \/___/ \/_/\/_/\/____/\/_/\ \_\ \/___/ 8 | \ \____/ 9 | \/___/ 10 | (_'_______________________________________________________________________________'_) 11 | (_.———————————————————————————————————————————————————————————————————————————————._) 12 | 13 | 14 | Backbone supplies structure to JavaScript-heavy applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing application over a RESTful JSON interface. 15 | 16 | For Docs, License, Tests, pre-packed downloads, and everything else, really, see: 17 | https://backbonejs.org 18 | 19 | To suggest a feature or report a bug: 20 | https://github.com/jashkenas/backbone/issues 21 | 22 | For questions on working with Backbone or general discussions: 23 | [security policy](SECURITY.md), 24 | https://stackoverflow.com/questions/tagged/backbone.js, 25 | https://matrix.to/#/#jashkenas_backbone:gitter.im or 26 | https://groups.google.com/g/backbonejs 27 | 28 | Backbone is an open-sourced component of DocumentCloud: 29 | https://github.com/documentcloud 30 | 31 | Testing powered by SauceLabs: 32 | https://saucelabs.com 33 | 34 | Many thanks to our contributors: 35 | https://github.com/jashkenas/backbone/graphs/contributors 36 | 37 | Special thanks to Robert Kieffer for the original philosophy behind Backbone. 38 | https://github.com/broofa 39 | 40 | This project adheres to a [code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. 41 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | We currently support the following versions of Backbone with security updates: 6 | 7 | - the latest commit on the `master` branch (published as "edge" on the 8 | [project website][website]); 9 | - the 1.x release tagged as [latest][npm-latest] on npm; 10 | - any release tagged as [preview][npm-preview] on npm, if present. 11 | 12 | [website]: https://backbonejs.org 13 | [npm-latest]: https://www.npmjs.com/package/backbone/v/latest 14 | [npm-preview]: https://www.npmjs.com/package/backbone/v/preview 15 | 16 | ## Reporting a Vulnerability 17 | 18 | Please report security issues by sending an email to 19 | dev@juliangonggrijp.com and jashkenas@gmail.com. 20 | 21 | Do __not__ submit an issue ticket or pull request or otherwise publicly 22 | disclose the issue. 23 | 24 | After receiving your email, we will respond as soon as possible and indicate 25 | what we plan to do. 26 | 27 | ## Disclosure policy 28 | 29 | After confirming a vulnerability, we will generally release a security update 30 | as soon as possible, including the minimum amount of information required for 31 | software maintainers and system administrators to assess the urgency of the 32 | update for their particular situation. 33 | 34 | We postpone the publication of any further details such as code comments, 35 | tests, commit history and diffs, in order to enable a substantial share of the 36 | users to install the security fix before this time. 37 | 38 | Upon publication of full details, we will credit the reporter if the reporter wishes to be publicly identified. 39 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "backbone", 3 | "main" : "backbone.js", 4 | "dependencies" : { 5 | "underscore" : ">=1.8.3" 6 | }, 7 | "ignore" : ["docs", "examples", "test", "*.yml", "*.html", "*.ico", "*.md", "CNAME", ".*", "karma.*", "package.json"] 8 | } 9 | -------------------------------------------------------------------------------- /debug-info.js: -------------------------------------------------------------------------------- 1 | (function (global, factory) { 2 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('backbone')) : 3 | typeof define === 'function' && define.amd ? define(['backbone'], factory) : 4 | (global = typeof globalThis !== 'undefined' ? globalThis : global || self, (global.Backbone = global.Backbone || {}, global.Backbone.debugInfo = factory(global.Backbone))); 5 | })(this, (function (Backbone) { 6 | // Provide useful information when things go wrong. 7 | function debugInfo() { 8 | // Introspect Backbone. 9 | var $ = Backbone.$, _b = Backbone._debug(), _ = _b._, root = _b.root; 10 | // Use the `partialRight` function as a Lodash indicator. It was never in 11 | // Underscore, has been in Lodash at least since version 1.3.1, and is 12 | // unlikely to be mixed into Underscore since nobody needs it. 13 | var lodash = !!_.partialRight; 14 | var info = { 15 | backbone: Backbone.VERSION, 16 | // Is this the exact released version, or a later development version? 17 | /* This is automatically temporarily replaced when publishing a release, 18 | so please don't edit this. */ 19 | distribution: 'MARK_DEVELOPMENT', 20 | _: (lodash ? 'lodash ' : '') + _.VERSION, 21 | $: !$ ? false : $.fn && $.fn.jquery ? $.fn.jquery : 22 | $.zepto ? 'zepto' : $.ender ? 'ender' : true 23 | }; 24 | if (typeof root.Deno !== 'undefined') { 25 | info.deno = _.pick(root.Deno, 'version', 'build'); 26 | } else if (typeof root.process !== 'undefined') { 27 | info.process = _.pick(root.process, 'version', 'platform', 'arch'); 28 | } else if (typeof root.navigator !== 'undefined') { 29 | info.navigator = _.pick(root.navigator, 'userAgent', 'platform', 'webdriver'); 30 | } 31 | /* eslint-disable-next-line no-console */ 32 | console.debug('Backbone debug info: ', JSON.stringify(info, null, 4)); 33 | return info; 34 | } 35 | 36 | return debugInfo; 37 | 38 | })); 39 | -------------------------------------------------------------------------------- /docs/backbone.localStorage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

This annotated source has moved to examples/backbone.localStorage.html. You will be automatically redirected in two seconds.

7 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /docs/docco.css: -------------------------------------------------------------------------------- 1 | /*--------------------- Typography ----------------------------*/ 2 | 3 | @font-face { 4 | font-family: 'aller-light'; 5 | src: url('public/fonts/aller-light.eot'); 6 | src: url('public/fonts/aller-light.eot?#iefix') format('embedded-opentype'), 7 | url('public/fonts/aller-light.woff') format('woff'), 8 | url('public/fonts/aller-light.ttf') format('truetype'); 9 | font-weight: normal; 10 | font-style: normal; 11 | } 12 | 13 | @font-face { 14 | font-family: 'aller-bold'; 15 | src: url('public/fonts/aller-bold.eot'); 16 | src: url('public/fonts/aller-bold.eot?#iefix') format('embedded-opentype'), 17 | url('public/fonts/aller-bold.woff') format('woff'), 18 | url('public/fonts/aller-bold.ttf') format('truetype'); 19 | font-weight: normal; 20 | font-style: normal; 21 | } 22 | 23 | @font-face { 24 | font-family: 'roboto-black'; 25 | src: url('public/fonts/roboto-black.eot'); 26 | src: url('public/fonts/roboto-black.eot?#iefix') format('embedded-opentype'), 27 | url('public/fonts/roboto-black.woff') format('woff'), 28 | url('public/fonts/roboto-black.ttf') format('truetype'); 29 | font-weight: normal; 30 | font-style: normal; 31 | } 32 | 33 | /*--------------------- Layout ----------------------------*/ 34 | html { height: 100%; } 35 | body { 36 | font-family: "aller-light"; 37 | font-size: 14px; 38 | line-height: 18px; 39 | color: #30404f; 40 | margin: 0; padding: 0; 41 | height:100%; 42 | } 43 | #container { min-height: 100%; } 44 | 45 | a { 46 | color: #000; 47 | } 48 | 49 | b, strong { 50 | font-weight: normal; 51 | font-family: "aller-bold"; 52 | } 53 | 54 | p { 55 | margin: 15px 0 0px; 56 | } 57 | .annotation ul, .annotation ol { 58 | margin: 25px 0; 59 | } 60 | .annotation ul li, .annotation ol li { 61 | font-size: 14px; 62 | line-height: 18px; 63 | margin: 10px 0; 64 | } 65 | 66 | h1, h2, h3, h4, h5, h6 { 67 | color: #112233; 68 | line-height: 1em; 69 | font-weight: normal; 70 | font-family: "roboto-black"; 71 | text-transform: uppercase; 72 | margin: 30px 0 15px 0; 73 | } 74 | 75 | h1 { 76 | margin-top: 40px; 77 | } 78 | h2 { 79 | font-size: 1.26em; 80 | } 81 | 82 | hr { 83 | border: 0; 84 | background: 1px #ddd; 85 | height: 1px; 86 | margin: 20px 0; 87 | } 88 | 89 | pre, tt, code { 90 | font-size: 12px; line-height: 16px; 91 | font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; 92 | margin: 0; padding: 0; 93 | } 94 | .annotation pre { 95 | display: block; 96 | margin: 0; 97 | padding: 7px 10px; 98 | background: #fcfcfc; 99 | -moz-box-shadow: inset 0 0 10px rgba(0,0,0,0.1); 100 | -webkit-box-shadow: inset 0 0 10px rgba(0,0,0,0.1); 101 | box-shadow: inset 0 0 10px rgba(0,0,0,0.1); 102 | overflow-x: auto; 103 | } 104 | .annotation pre code { 105 | border: 0; 106 | padding: 0; 107 | background: transparent; 108 | } 109 | 110 | 111 | blockquote { 112 | border-left: 5px solid #ccc; 113 | margin: 0; 114 | padding: 1px 0 1px 1em; 115 | } 116 | .sections blockquote p { 117 | font-family: Menlo, Consolas, Monaco, monospace; 118 | font-size: 12px; line-height: 16px; 119 | color: #999; 120 | margin: 10px 0 0; 121 | white-space: pre-wrap; 122 | } 123 | 124 | ul.sections { 125 | list-style: none; 126 | padding:0 0 5px 0;; 127 | margin:0; 128 | } 129 | 130 | /* 131 | Force border-box so that % widths fit the parent 132 | container without overlap because of margin/padding. 133 | 134 | More Info : http://www.quirksmode.org/css/box.html 135 | */ 136 | ul.sections > li > div { 137 | -moz-box-sizing: border-box; /* firefox */ 138 | -ms-box-sizing: border-box; /* ie */ 139 | -webkit-box-sizing: border-box; /* webkit */ 140 | -khtml-box-sizing: border-box; /* konqueror */ 141 | box-sizing: border-box; /* css3 */ 142 | } 143 | 144 | 145 | /*---------------------- Jump Page -----------------------------*/ 146 | #jump_to, #jump_page { 147 | margin: 0; 148 | background: white; 149 | -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; 150 | -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; 151 | font: 16px Arial; 152 | cursor: pointer; 153 | text-align: right; 154 | list-style: none; 155 | } 156 | 157 | #jump_to a { 158 | text-decoration: none; 159 | } 160 | 161 | #jump_to a.large { 162 | display: none; 163 | } 164 | #jump_to a.small { 165 | font-size: 22px; 166 | font-weight: bold; 167 | color: #676767; 168 | } 169 | 170 | #jump_to, #jump_wrapper { 171 | position: fixed; 172 | right: 0; top: 0; 173 | padding: 10px 15px; 174 | margin:0; 175 | } 176 | 177 | #jump_wrapper { 178 | display: none; 179 | padding:0; 180 | } 181 | 182 | #jump_to:hover #jump_wrapper { 183 | display: block; 184 | } 185 | 186 | #jump_page_wrapper{ 187 | position: fixed; 188 | right: 0; 189 | top: 0; 190 | bottom: 0; 191 | } 192 | 193 | #jump_page { 194 | padding: 5px 0 3px; 195 | margin: 0 0 25px 25px; 196 | max-height: 100%; 197 | overflow: auto; 198 | } 199 | 200 | #jump_page .source { 201 | display: block; 202 | padding: 15px; 203 | text-decoration: none; 204 | border-top: 1px solid #eee; 205 | } 206 | 207 | #jump_page .source:hover { 208 | background: #f5f5ff; 209 | } 210 | 211 | #jump_page .source:first-child { 212 | } 213 | 214 | /*---------------------- Low resolutions (> 320px) ---------------------*/ 215 | @media only screen and (min-width: 320px) { 216 | .sswrap { display: none; } 217 | 218 | ul.sections > li > div { 219 | display: block; 220 | padding:5px 10px 0 10px; 221 | } 222 | 223 | ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol { 224 | padding-left: 30px; 225 | } 226 | 227 | ul.sections > li > div.content { 228 | overflow-x:auto; 229 | -webkit-box-shadow: inset 0 0 5px #e5e5ee; 230 | box-shadow: inset 0 0 5px #e5e5ee; 231 | border: 1px solid #dedede; 232 | margin:5px 10px 5px 10px; 233 | padding-bottom: 5px; 234 | } 235 | 236 | ul.sections > li > div.annotation pre { 237 | margin: 7px 0 7px; 238 | padding-left: 15px; 239 | } 240 | 241 | ul.sections > li > div.annotation p tt, .annotation code { 242 | background: #f8f8ff; 243 | border: 1px solid #dedede; 244 | font-size: 12px; 245 | padding: 0 0.2em; 246 | } 247 | } 248 | 249 | /*---------------------- (> 481px) ---------------------*/ 250 | @media only screen and (min-width: 481px) { 251 | #container { 252 | position: relative; 253 | } 254 | body { 255 | background-color: #F5F5FF; 256 | font-size: 15px; 257 | line-height: 21px; 258 | } 259 | pre, tt, code { 260 | line-height: 18px; 261 | } 262 | p, ul, ol { 263 | margin: 0 0 15px; 264 | } 265 | 266 | 267 | #jump_to { 268 | padding: 5px 10px; 269 | } 270 | #jump_wrapper { 271 | padding: 0; 272 | } 273 | #jump_to, #jump_page { 274 | font: 10px Arial; 275 | text-transform: uppercase; 276 | } 277 | #jump_page .source { 278 | padding: 5px 10px; 279 | } 280 | #jump_to a.large { 281 | display: inline-block; 282 | } 283 | #jump_to a.small { 284 | display: none; 285 | } 286 | 287 | 288 | 289 | #background { 290 | position: absolute; 291 | top: 0; bottom: 0; 292 | width: 350px; 293 | background: #fff; 294 | border-right: 1px solid #e5e5ee; 295 | z-index: -1; 296 | } 297 | 298 | ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol { 299 | padding-left: 40px; 300 | } 301 | 302 | ul.sections > li { 303 | white-space: nowrap; 304 | } 305 | 306 | ul.sections > li > div { 307 | display: inline-block; 308 | } 309 | 310 | ul.sections > li > div.annotation { 311 | max-width: 350px; 312 | min-width: 350px; 313 | min-height: 5px; 314 | padding: 13px; 315 | overflow-x: hidden; 316 | white-space: normal; 317 | vertical-align: top; 318 | text-align: left; 319 | } 320 | ul.sections > li > div.annotation pre { 321 | margin: 15px 0 15px; 322 | padding-left: 15px; 323 | } 324 | 325 | ul.sections > li > div.content { 326 | padding: 13px; 327 | vertical-align: top; 328 | border: none; 329 | -webkit-box-shadow: none; 330 | box-shadow: none; 331 | } 332 | 333 | .sswrap { 334 | position: relative; 335 | display: inline; 336 | } 337 | 338 | .ss { 339 | font: 12px Arial; 340 | text-decoration: none; 341 | color: #454545; 342 | position: absolute; 343 | top: 3px; left: -20px; 344 | padding: 1px 2px; 345 | opacity: 0; 346 | -webkit-transition: opacity 0.2s linear; 347 | } 348 | .for-h1 .ss { 349 | top: 47px; 350 | } 351 | .for-h2 .ss, .for-h3 .ss, .for-h4 .ss { 352 | top: 35px; 353 | } 354 | 355 | ul.sections > li > div.annotation:hover .ss { 356 | opacity: 1; 357 | } 358 | } 359 | 360 | /*---------------------- (> 1025px) ---------------------*/ 361 | @media only screen and (min-width: 1025px) { 362 | 363 | body { 364 | font-size: 16px; 365 | line-height: 24px; 366 | } 367 | 368 | #background { 369 | width: 525px; 370 | } 371 | ul.sections > li > div.annotation { 372 | max-width: 525px; 373 | min-width: 525px; 374 | padding: 10px 25px 1px 50px; 375 | } 376 | ul.sections > li > div.content { 377 | padding: 9px 15px 16px 25px; 378 | } 379 | } 380 | 381 | /*---------------------- Syntax Highlighting -----------------------------*/ 382 | 383 | td.linenos { background-color: #f0f0f0; padding-right: 10px; } 384 | span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } 385 | /* 386 | 387 | github.com style (c) Vasily Polovnyov 388 | 389 | */ 390 | 391 | pre code { 392 | display: block; padding: 0.5em; 393 | color: #000; 394 | background: #f8f8ff 395 | } 396 | 397 | pre .hljs-comment, 398 | pre .hljs-template_comment, 399 | pre .hljs-diff .hljs-header, 400 | pre .hljs-javadoc { 401 | color: #408080; 402 | font-style: italic 403 | } 404 | 405 | pre .hljs-keyword, 406 | pre .hljs-assignment, 407 | pre .hljs-literal, 408 | pre .hljs-css .hljs-rule .hljs-keyword, 409 | pre .hljs-winutils, 410 | pre .hljs-javascript .hljs-title, 411 | pre .hljs-lisp .hljs-title, 412 | pre .hljs-subst { 413 | color: #954121; 414 | /*font-weight: bold*/ 415 | } 416 | 417 | pre .hljs-number, 418 | pre .hljs-hexcolor { 419 | color: #40a070 420 | } 421 | 422 | pre .hljs-string, 423 | pre .hljs-tag .hljs-value, 424 | pre .hljs-phpdoc, 425 | pre .hljs-tex .hljs-formula { 426 | color: #219161; 427 | } 428 | 429 | pre .hljs-title, 430 | pre .hljs-id { 431 | color: #19469D; 432 | } 433 | pre .hljs-params { 434 | color: #00F; 435 | } 436 | 437 | pre .hljs-javascript .hljs-title, 438 | pre .hljs-lisp .hljs-title, 439 | pre .hljs-subst { 440 | font-weight: normal 441 | } 442 | 443 | pre .hljs-class .hljs-title, 444 | pre .hljs-haskell .hljs-label, 445 | pre .hljs-tex .hljs-command { 446 | color: #458; 447 | font-weight: bold 448 | } 449 | 450 | pre .hljs-tag, 451 | pre .hljs-tag .hljs-title, 452 | pre .hljs-rules .hljs-property, 453 | pre .hljs-django .hljs-tag .hljs-keyword { 454 | color: #000080; 455 | font-weight: normal 456 | } 457 | 458 | pre .hljs-attribute, 459 | pre .hljs-variable, 460 | pre .hljs-instancevar, 461 | pre .hljs-lisp .hljs-body { 462 | color: #008080 463 | } 464 | 465 | pre .hljs-regexp { 466 | color: #B68 467 | } 468 | 469 | pre .hljs-class { 470 | color: #458; 471 | font-weight: bold 472 | } 473 | 474 | pre .hljs-symbol, 475 | pre .hljs-ruby .hljs-symbol .hljs-string, 476 | pre .hljs-ruby .hljs-symbol .hljs-keyword, 477 | pre .hljs-ruby .hljs-symbol .hljs-keymethods, 478 | pre .hljs-lisp .hljs-keyword, 479 | pre .hljs-tex .hljs-special, 480 | pre .hljs-input_number { 481 | color: #990073 482 | } 483 | 484 | pre .hljs-builtin, 485 | pre .hljs-constructor, 486 | pre .hljs-built_in, 487 | pre .hljs-lisp .hljs-title { 488 | color: #0086b3 489 | } 490 | 491 | pre .hljs-preprocessor, 492 | pre .hljs-pi, 493 | pre .hljs-doctype, 494 | pre .hljs-shebang, 495 | pre .hljs-cdata { 496 | color: #999; 497 | font-weight: bold 498 | } 499 | 500 | pre .hljs-deletion { 501 | background: #fdd 502 | } 503 | 504 | pre .hljs-addition { 505 | background: #dfd 506 | } 507 | 508 | pre .hljs-diff .hljs-change { 509 | background: #0086b3 510 | } 511 | 512 | pre .hljs-chunk { 513 | color: #aaa 514 | } 515 | 516 | pre .hljs-tex .hljs-formula { 517 | opacity: 0.5; 518 | } 519 | -------------------------------------------------------------------------------- /docs/images/airbnb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/airbnb.png -------------------------------------------------------------------------------- /docs/images/arrows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/arrows.png -------------------------------------------------------------------------------- /docs/images/artsy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/artsy.jpg -------------------------------------------------------------------------------- /docs/images/backbone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/backbone.png -------------------------------------------------------------------------------- /docs/images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/background.png -------------------------------------------------------------------------------- /docs/images/basecamp-calendar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/basecamp-calendar.jpg -------------------------------------------------------------------------------- /docs/images/bitbucket.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/bitbucket.jpg -------------------------------------------------------------------------------- /docs/images/blossom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/blossom.jpg -------------------------------------------------------------------------------- /docs/images/cloudapp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/cloudapp.jpg -------------------------------------------------------------------------------- /docs/images/code-school.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/code-school.jpg -------------------------------------------------------------------------------- /docs/images/dc-workspace.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/dc-workspace.jpg -------------------------------------------------------------------------------- /docs/images/delicious.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/delicious.jpg -------------------------------------------------------------------------------- /docs/images/disqus.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/disqus.jpg -------------------------------------------------------------------------------- /docs/images/earth.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/earth.jpg -------------------------------------------------------------------------------- /docs/images/easel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/easel.jpg -------------------------------------------------------------------------------- /docs/images/enigma.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/enigma.jpg -------------------------------------------------------------------------------- /docs/images/flow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/flow.jpg -------------------------------------------------------------------------------- /docs/images/foursquare.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/foursquare.jpg -------------------------------------------------------------------------------- /docs/images/gawker.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/gawker.jpg -------------------------------------------------------------------------------- /docs/images/gilt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/gilt.jpg -------------------------------------------------------------------------------- /docs/images/groupon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/groupon.jpg -------------------------------------------------------------------------------- /docs/images/hulu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/hulu.jpg -------------------------------------------------------------------------------- /docs/images/inkling.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/inkling.jpg -------------------------------------------------------------------------------- /docs/images/intro-collections.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 36 | 38 | 40 | 42 | 43 | 45 | 46 | 47 | 49 | 50 | 51 | 55 | 63 | 64 | 70 | 72 | 73 | 74 | 75 | 79 | 82 | 83 | 87 | 88 | 89 | 93 | 94 | 95 | 109 | 110 | 111 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 134 | 136 | 138 | 144 | 145 | 146 | 150 | 152 | 153 | 155 | 156 | 157 | 163 | 167 | 169 | 171 | 172 | 174 | 175 | 176 | 178 | 182 | 186 | 187 | 188 | 189 | 191 | 195 | 199 | 200 | 201 | 202 | 206 | 208 | 209 | 213 | 215 | 219 | 220 | 221 | 222 | -------------------------------------------------------------------------------- /docs/images/intro-model-view.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 10 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 26 | 27 | 28 | 29 | 31 | 32 | 36 | 40 | 41 | 45 | 53 | 54 | 59 | 61 | 63 | 65 | 68 | 69 | 79 | 80 | 81 | 87 | 88 | 89 | 93 | 95 | 96 | 98 | 99 | 100 | 101 | 102 | 106 | 109 | 110 | 111 | 112 | 118 | 119 | 121 | 123 | 129 | 131 | 132 | 133 | 137 | 139 | 141 | 145 | 147 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /docs/images/intro-routing.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 9 | 11 | 12 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 24 | 26 | 28 | 29 | 35 | 41 | 43 | 44 | 47 | 48 | 49 | 56 | 62 | 68 | 70 | 80 | 81 | 82 | 83 | 85 | 87 | 89 | 90 | 91 | 93 | 95 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 107 | 108 | 109 | 110 | 112 | 113 | 117 | 118 | 120 | 121 | 125 | 126 | 130 | 131 | 132 | 135 | 136 | -------------------------------------------------------------------------------- /docs/images/intro-views.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 10 | 12 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | 25 | 26 | 27 | 28 | 32 | 36 | 37 | 41 | 49 | 50 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 79 | 81 | 83 | 84 | 85 | 86 | 87 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 97 | 99 | 101 | 104 | 105 | 115 | 117 | 118 | 124 | 125 | 126 | 127 | 129 | 133 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /docs/images/irccloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/irccloud.png -------------------------------------------------------------------------------- /docs/images/jolicloud.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/jolicloud.jpg -------------------------------------------------------------------------------- /docs/images/khan-academy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/khan-academy.jpg -------------------------------------------------------------------------------- /docs/images/newsblur.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/newsblur.jpg -------------------------------------------------------------------------------- /docs/images/pandora.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/pandora.jpg -------------------------------------------------------------------------------- /docs/images/pitchfork.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/pitchfork.jpg -------------------------------------------------------------------------------- /docs/images/quartz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/quartz.jpg -------------------------------------------------------------------------------- /docs/images/rdio.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/rdio.jpg -------------------------------------------------------------------------------- /docs/images/salon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/salon.jpg -------------------------------------------------------------------------------- /docs/images/seatgeek.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/seatgeek.jpg -------------------------------------------------------------------------------- /docs/images/slavery-footprint.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/slavery-footprint.jpg -------------------------------------------------------------------------------- /docs/images/soundcloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/soundcloud.png -------------------------------------------------------------------------------- /docs/images/spin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/spin.jpg -------------------------------------------------------------------------------- /docs/images/stripe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/stripe.png -------------------------------------------------------------------------------- /docs/images/tilemill.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/tilemill.jpg -------------------------------------------------------------------------------- /docs/images/todos.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/todos.jpg -------------------------------------------------------------------------------- /docs/images/trello.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/trello.jpg -------------------------------------------------------------------------------- /docs/images/tzigla.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/tzigla.jpg -------------------------------------------------------------------------------- /docs/images/usa-today.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/usa-today.jpg -------------------------------------------------------------------------------- /docs/images/vox.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/vox.jpg -------------------------------------------------------------------------------- /docs/images/walmart-mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/walmart-mobile.png -------------------------------------------------------------------------------- /docs/images/wpcom-notifications.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/wpcom-notifications.jpg -------------------------------------------------------------------------------- /docs/images/zocdoc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/images/zocdoc.jpg -------------------------------------------------------------------------------- /docs/js/jquery.lazyload.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Lazy Load - jQuery plugin for lazy loading images 3 | * 4 | * Copyright (c) 2007-2012 Mika Tuupola 5 | * 6 | * Licensed under the MIT license: 7 | * http://www.opensource.org/licenses/mit-license.php 8 | * 9 | * Project home: 10 | * http://www.appelsiini.net/projects/lazyload 11 | * 12 | * Version: 1.7.2 13 | * 14 | */ 15 | (function($, window) { 16 | 17 | $window = $(window); 18 | 19 | $.fn.lazyload = function(options) { 20 | var elements = this; 21 | var settings = { 22 | threshold : 0, 23 | failure_limit : 0, 24 | event : "scroll", 25 | effect : "show", 26 | container : window, 27 | data_attribute : "original", 28 | skip_invisible : true, 29 | appear : null, 30 | load : null 31 | }; 32 | 33 | function update() { 34 | var counter = 0; 35 | 36 | elements.each(function() { 37 | var $this = $(this); 38 | if (settings.skip_invisible && !$this.is(":visible")) { 39 | return; 40 | } 41 | if ($.abovethetop(this, settings) || 42 | $.leftofbegin(this, settings)) { 43 | /* Nothing. */ 44 | } else if (!$.belowthefold(this, settings) && 45 | !$.rightoffold(this, settings)) { 46 | $this.trigger("appear"); 47 | } else { 48 | if (++counter > settings.failure_limit) { 49 | return false; 50 | } 51 | } 52 | }); 53 | 54 | } 55 | 56 | if(options) { 57 | /* Maintain BC for a couple of versions. */ 58 | if (undefined !== options.failurelimit) { 59 | options.failure_limit = options.failurelimit; 60 | delete options.failurelimit; 61 | } 62 | if (undefined !== options.effectspeed) { 63 | options.effect_speed = options.effectspeed; 64 | delete options.effectspeed; 65 | } 66 | 67 | $.extend(settings, options); 68 | } 69 | 70 | /* Cache container as jQuery as object. */ 71 | $container = (settings.container === undefined || 72 | settings.container === window) ? $window : $(settings.container); 73 | 74 | /* Fire one scroll event per scroll. Not one scroll event per image. */ 75 | if (0 === settings.event.indexOf("scroll")) { 76 | $container.bind(settings.event, function(event) { 77 | return update(); 78 | }); 79 | } 80 | 81 | this.each(function() { 82 | var self = this; 83 | var $self = $(self); 84 | 85 | self.loaded = false; 86 | 87 | /* When appear is triggered load original image. */ 88 | $self.one("appear", function() { 89 | if (!this.loaded) { 90 | if (settings.appear) { 91 | var elements_left = elements.length; 92 | settings.appear.call(self, elements_left, settings); 93 | } 94 | $("") 95 | .bind("load", function() { 96 | $self 97 | .hide() 98 | .attr("src", $self.data(settings.data_attribute)) 99 | [settings.effect](settings.effect_speed); 100 | self.loaded = true; 101 | 102 | /* Remove image from array so it is not looped next time. */ 103 | var temp = $.grep(elements, function(element) { 104 | return !element.loaded; 105 | }); 106 | elements = $(temp); 107 | 108 | if (settings.load) { 109 | var elements_left = elements.length; 110 | settings.load.call(self, elements_left, settings); 111 | } 112 | }) 113 | .attr("src", $self.data(settings.data_attribute)); 114 | } 115 | }); 116 | 117 | /* When wanted event is triggered load original image */ 118 | /* by triggering appear. */ 119 | if (0 !== settings.event.indexOf("scroll")) { 120 | $self.bind(settings.event, function(event) { 121 | if (!self.loaded) { 122 | $self.trigger("appear"); 123 | } 124 | }); 125 | } 126 | }); 127 | 128 | /* Check if something appears when window is resized. */ 129 | $window.bind("resize", function(event) { 130 | update(); 131 | }); 132 | 133 | /* Force initial check if images should appear. */ 134 | update(); 135 | 136 | return this; 137 | }; 138 | 139 | /* Convenience methods in jQuery namespace. */ 140 | /* Use as $.belowthefold(element, {threshold : 100, container : window}) */ 141 | 142 | $.belowthefold = function(element, settings) { 143 | var fold; 144 | 145 | if (settings.container === undefined || settings.container === window) { 146 | fold = $window.height() + $window.scrollTop(); 147 | } else { 148 | fold = $container.offset().top + $container.height(); 149 | } 150 | 151 | return fold <= $(element).offset().top - settings.threshold; 152 | }; 153 | 154 | $.rightoffold = function(element, settings) { 155 | var fold; 156 | 157 | if (settings.container === undefined || settings.container === window) { 158 | fold = $window.width() + $window.scrollLeft(); 159 | } else { 160 | fold = $container.offset().left + $container.width(); 161 | } 162 | 163 | return fold <= $(element).offset().left - settings.threshold; 164 | }; 165 | 166 | $.abovethetop = function(element, settings) { 167 | var fold; 168 | 169 | if (settings.container === undefined || settings.container === window) { 170 | fold = $window.scrollTop(); 171 | } else { 172 | fold = $container.offset().top; 173 | } 174 | 175 | return fold >= $(element).offset().top + settings.threshold + $(element).height(); 176 | }; 177 | 178 | $.leftofbegin = function(element, settings) { 179 | var fold; 180 | 181 | if (settings.container === undefined || settings.container === window) { 182 | fold = $window.scrollLeft(); 183 | } else { 184 | fold = $container.offset().left; 185 | } 186 | 187 | return fold >= $(element).offset().left + settings.threshold + $(element).width(); 188 | }; 189 | 190 | $.inviewport = function(element, settings) { 191 | return !$.rightofscreen(element, settings) && !$.leftofscreen(element, settings) && 192 | !$.belowthefold(element, settings) && !$.abovethetop(element, settings); 193 | }; 194 | 195 | /* Custom selectors for your convenience. */ 196 | /* Use as $("img:below-the-fold").something() */ 197 | 198 | $.extend($.expr[':'], { 199 | "below-the-fold" : function(a) { return $.belowthefold(a, {threshold : 0, container: window}); }, 200 | "above-the-top" : function(a) { return !$.belowthefold(a, {threshold : 0, container: window}); }, 201 | "right-of-screen": function(a) { return $.rightoffold(a, {threshold : 0, container: window}); }, 202 | "left-of-screen" : function(a) { return !$.rightoffold(a, {threshold : 0, container: window}); }, 203 | "in-viewport" : function(a) { return !$.inviewport(a, {threshold : 0, container: window}); }, 204 | /* Maintain BC for couple of versions. */ 205 | "above-the-fold" : function(a) { return !$.belowthefold(a, {threshold : 0, container: window}); }, 206 | "right-of-fold" : function(a) { return $.rightoffold(a, {threshold : 0, container: window}); }, 207 | "left-of-fold" : function(a) { return !$.rightoffold(a, {threshold : 0, container: window}); } 208 | }); 209 | 210 | })(jQuery, window); 211 | -------------------------------------------------------------------------------- /docs/public/fonts/aller-bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/public/fonts/aller-bold.eot -------------------------------------------------------------------------------- /docs/public/fonts/aller-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/public/fonts/aller-bold.ttf -------------------------------------------------------------------------------- /docs/public/fonts/aller-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/public/fonts/aller-bold.woff -------------------------------------------------------------------------------- /docs/public/fonts/aller-light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/public/fonts/aller-light.eot -------------------------------------------------------------------------------- /docs/public/fonts/aller-light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/public/fonts/aller-light.ttf -------------------------------------------------------------------------------- /docs/public/fonts/aller-light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/public/fonts/aller-light.woff -------------------------------------------------------------------------------- /docs/public/fonts/roboto-black.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/public/fonts/roboto-black.eot -------------------------------------------------------------------------------- /docs/public/fonts/roboto-black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/public/fonts/roboto-black.ttf -------------------------------------------------------------------------------- /docs/public/fonts/roboto-black.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/public/fonts/roboto-black.woff -------------------------------------------------------------------------------- /docs/public/images/grey_@2X.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/docs/public/images/grey_@2X.png -------------------------------------------------------------------------------- /docs/public/stylesheets/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v2.0.1 | MIT License | git.io/normalize */ 2 | 3 | /* ========================================================================== 4 | HTML5 display definitions 5 | ========================================================================== */ 6 | 7 | /* 8 | * Corrects `block` display not defined in IE 8/9. 9 | */ 10 | 11 | article, 12 | aside, 13 | details, 14 | figcaption, 15 | figure, 16 | footer, 17 | header, 18 | hgroup, 19 | nav, 20 | section, 21 | summary { 22 | display: block; 23 | } 24 | 25 | /* 26 | * Corrects `inline-block` display not defined in IE 8/9. 27 | */ 28 | 29 | audio, 30 | canvas, 31 | video { 32 | display: inline-block; 33 | } 34 | 35 | /* 36 | * Prevents modern browsers from displaying `audio` without controls. 37 | * Remove excess height in iOS 5 devices. 38 | */ 39 | 40 | audio:not([controls]) { 41 | display: none; 42 | height: 0; 43 | } 44 | 45 | /* 46 | * Addresses styling for `hidden` attribute not present in IE 8/9. 47 | */ 48 | 49 | [hidden] { 50 | display: none; 51 | } 52 | 53 | /* ========================================================================== 54 | Base 55 | ========================================================================== */ 56 | 57 | /* 58 | * 1. Sets default font family to sans-serif. 59 | * 2. Prevents iOS text size adjust after orientation change, without disabling 60 | * user zoom. 61 | */ 62 | 63 | html { 64 | font-family: sans-serif; /* 1 */ 65 | -webkit-text-size-adjust: 100%; /* 2 */ 66 | -ms-text-size-adjust: 100%; /* 2 */ 67 | } 68 | 69 | /* 70 | * Removes default margin. 71 | */ 72 | 73 | body { 74 | margin: 0; 75 | } 76 | 77 | /* ========================================================================== 78 | Links 79 | ========================================================================== */ 80 | 81 | /* 82 | * Addresses `outline` inconsistency between Chrome and other browsers. 83 | */ 84 | 85 | a:focus { 86 | outline: thin dotted; 87 | } 88 | 89 | /* 90 | * Improves readability when focused and also mouse hovered in all browsers. 91 | */ 92 | 93 | a:active, 94 | a:hover { 95 | outline: 0; 96 | } 97 | 98 | /* ========================================================================== 99 | Typography 100 | ========================================================================== */ 101 | 102 | /* 103 | * Addresses `h1` font sizes within `section` and `article` in Firefox 4+, 104 | * Safari 5, and Chrome. 105 | */ 106 | 107 | h1 { 108 | font-size: 2em; 109 | } 110 | 111 | /* 112 | * Addresses styling not present in IE 8/9, Safari 5, and Chrome. 113 | */ 114 | 115 | abbr[title] { 116 | border-bottom: 1px dotted; 117 | } 118 | 119 | /* 120 | * Addresses style set to `bolder` in Firefox 4+, Safari 5, and Chrome. 121 | */ 122 | 123 | b, 124 | strong { 125 | font-weight: bold; 126 | } 127 | 128 | /* 129 | * Addresses styling not present in Safari 5 and Chrome. 130 | */ 131 | 132 | dfn { 133 | font-style: italic; 134 | } 135 | 136 | /* 137 | * Addresses styling not present in IE 8/9. 138 | */ 139 | 140 | mark { 141 | background: #ff0; 142 | color: #000; 143 | } 144 | 145 | 146 | /* 147 | * Corrects font family set oddly in Safari 5 and Chrome. 148 | */ 149 | 150 | code, 151 | kbd, 152 | pre, 153 | samp { 154 | font-family: monospace, serif; 155 | font-size: 1em; 156 | } 157 | 158 | /* 159 | * Improves readability of pre-formatted text in all browsers. 160 | */ 161 | 162 | pre { 163 | white-space: pre; 164 | white-space: pre-wrap; 165 | word-wrap: break-word; 166 | } 167 | 168 | /* 169 | * Sets consistent quote types. 170 | */ 171 | 172 | q { 173 | quotes: "\201C" "\201D" "\2018" "\2019"; 174 | } 175 | 176 | /* 177 | * Addresses inconsistent and variable font size in all browsers. 178 | */ 179 | 180 | small { 181 | font-size: 80%; 182 | } 183 | 184 | /* 185 | * Prevents `sub` and `sup` affecting `line-height` in all browsers. 186 | */ 187 | 188 | sub, 189 | sup { 190 | font-size: 75%; 191 | line-height: 0; 192 | position: relative; 193 | vertical-align: baseline; 194 | } 195 | 196 | sup { 197 | top: -0.5em; 198 | } 199 | 200 | sub { 201 | bottom: -0.25em; 202 | } 203 | 204 | /* ========================================================================== 205 | Embedded content 206 | ========================================================================== */ 207 | 208 | /* 209 | * Removes border when inside `a` element in IE 8/9. 210 | */ 211 | 212 | img { 213 | border: 0; 214 | } 215 | 216 | /* 217 | * Corrects overflow displayed oddly in IE 9. 218 | */ 219 | 220 | svg:not(:root) { 221 | overflow: hidden; 222 | } 223 | 224 | /* ========================================================================== 225 | Figures 226 | ========================================================================== */ 227 | 228 | /* 229 | * Addresses margin not present in IE 8/9 and Safari 5. 230 | */ 231 | 232 | figure { 233 | margin: 0; 234 | } 235 | 236 | /* ========================================================================== 237 | Forms 238 | ========================================================================== */ 239 | 240 | /* 241 | * Define consistent border, margin, and padding. 242 | */ 243 | 244 | fieldset { 245 | border: 1px solid #c0c0c0; 246 | margin: 0 2px; 247 | padding: 0.35em 0.625em 0.75em; 248 | } 249 | 250 | /* 251 | * 1. Corrects color not being inherited in IE 8/9. 252 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 253 | */ 254 | 255 | legend { 256 | border: 0; /* 1 */ 257 | padding: 0; /* 2 */ 258 | } 259 | 260 | /* 261 | * 1. Corrects font family not being inherited in all browsers. 262 | * 2. Corrects font size not being inherited in all browsers. 263 | * 3. Addresses margins set differently in Firefox 4+, Safari 5, and Chrome 264 | */ 265 | 266 | button, 267 | input, 268 | select, 269 | textarea { 270 | font-family: inherit; /* 1 */ 271 | font-size: 100%; /* 2 */ 272 | margin: 0; /* 3 */ 273 | } 274 | 275 | /* 276 | * Addresses Firefox 4+ setting `line-height` on `input` using `!important` in 277 | * the UA stylesheet. 278 | */ 279 | 280 | button, 281 | input { 282 | line-height: normal; 283 | } 284 | 285 | /* 286 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 287 | * and `video` controls. 288 | * 2. Corrects inability to style clickable `input` types in iOS. 289 | * 3. Improves usability and consistency of cursor style between image-type 290 | * `input` and others. 291 | */ 292 | 293 | button, 294 | html input[type="button"], /* 1 */ 295 | input[type="reset"], 296 | input[type="submit"] { 297 | -webkit-appearance: button; /* 2 */ 298 | cursor: pointer; /* 3 */ 299 | } 300 | 301 | /* 302 | * Re-set default cursor for disabled elements. 303 | */ 304 | 305 | button[disabled], 306 | input[disabled] { 307 | cursor: default; 308 | } 309 | 310 | /* 311 | * 1. Addresses box sizing set to `content-box` in IE 8/9. 312 | * 2. Removes excess padding in IE 8/9. 313 | */ 314 | 315 | input[type="checkbox"], 316 | input[type="radio"] { 317 | box-sizing: border-box; /* 1 */ 318 | padding: 0; /* 2 */ 319 | } 320 | 321 | /* 322 | * 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome. 323 | * 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome 324 | * (include `-moz` to future-proof). 325 | */ 326 | 327 | input[type="search"] { 328 | -webkit-appearance: textfield; /* 1 */ 329 | -moz-box-sizing: content-box; 330 | -webkit-box-sizing: content-box; /* 2 */ 331 | box-sizing: content-box; 332 | } 333 | 334 | /* 335 | * Removes inner padding and search cancel button in Safari 5 and Chrome 336 | * on OS X. 337 | */ 338 | 339 | input[type="search"]::-webkit-search-cancel-button, 340 | input[type="search"]::-webkit-search-decoration { 341 | -webkit-appearance: none; 342 | } 343 | 344 | /* 345 | * Removes inner padding and border in Firefox 4+. 346 | */ 347 | 348 | button::-moz-focus-inner, 349 | input::-moz-focus-inner { 350 | border: 0; 351 | padding: 0; 352 | } 353 | 354 | /* 355 | * 1. Removes default vertical scrollbar in IE 8/9. 356 | * 2. Improves readability and alignment in all browsers. 357 | */ 358 | 359 | textarea { 360 | overflow: auto; /* 1 */ 361 | vertical-align: top; /* 2 */ 362 | } 363 | 364 | /* ========================================================================== 365 | Tables 366 | ========================================================================== */ 367 | 368 | /* 369 | * Remove most spacing between table cells. 370 | */ 371 | 372 | table { 373 | border-collapse: collapse; 374 | border-spacing: 0; 375 | } -------------------------------------------------------------------------------- /docs/search.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var functions = document.querySelectorAll('[data-name]'); 3 | var sections = document.querySelectorAll('.searchable_section'); 4 | var searchInput = document.getElementById('function_filter'); 5 | 6 | function strIn(a, b) { 7 | a = a.toLowerCase(); 8 | b = b.toLowerCase(); 9 | return b.indexOf(a) >= 0; 10 | } 11 | 12 | function doesMatch(element) { 13 | var name = element.getAttribute('data-name'); 14 | var aliases = element.getAttribute('data-aliases') || ''; 15 | return strIn(searchInput.value, name) || strIn(searchInput.value, aliases); 16 | } 17 | 18 | function filterElement(element) { 19 | element.style.display = doesMatch(element) ? '' : 'none'; 20 | } 21 | 22 | function filterToc() { 23 | _.each(functions, filterElement); 24 | 25 | var emptySearch = searchInput.value === ''; 26 | 27 | // Hide the titles of empty sections 28 | _.each(sections, function(section) { 29 | var sectionFunctions = section.querySelectorAll('[data-name]'); 30 | var showSection = emptySearch || _.some(sectionFunctions, doesMatch); 31 | section.style.display = showSection ? '' : 'none'; 32 | }); 33 | } 34 | 35 | function gotoFirst() { 36 | var firstFunction = _.find(functions, doesMatch); 37 | if(firstFunction) { 38 | window.location.hash = firstFunction.lastChild.getAttribute('href'); 39 | searchInput.focus(); 40 | } 41 | } 42 | 43 | searchInput.addEventListener('input', filterToc, false); 44 | 45 | // Press "Enter" to jump to the first matching function 46 | searchInput.addEventListener('keypress', function(e) { 47 | if (e.which === 13) { 48 | gotoFirst(); 49 | } 50 | }); 51 | 52 | // Press "/" to search 53 | document.body.addEventListener('keyup', function(event) { 54 | if (191 === event.which) { 55 | searchInput.focus(); 56 | } 57 | }); 58 | }()); 59 | -------------------------------------------------------------------------------- /docs/todos.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

This annotated source has moved to examples/todos/todos.html. You will be automatically redirected in two seconds.

7 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/backbone.localStorage.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Backbone localStorage Adapter 3 | * Version 1.1.0 4 | * 5 | * https://github.com/jeromegn/Backbone.localStorage 6 | */ 7 | (function (root, factory) { 8 | if (typeof define === "function" && define.amd) { 9 | // AMD. Register as an anonymous module. 10 | define(["underscore","backbone"], function(_, Backbone) { 11 | // Use global variables if the locals are undefined. 12 | return factory(_ || root._, Backbone || root.Backbone); 13 | }); 14 | } else { 15 | // RequireJS isn't being used. Assume underscore and backbone are loaded in script tags 16 | factory(_, Backbone); 17 | } 18 | }(this, function(_, Backbone) { 19 | // A simple module to replace `Backbone.sync` with *localStorage*-based 20 | // persistence. Models are given GUIDS, and saved into a JSON object. Simple 21 | // as that. 22 | 23 | // Hold reference to Underscore.js and Backbone.js in the closure in order 24 | // to make things work even if they are removed from the global namespace 25 | 26 | // Generate four random hex digits. 27 | function S4() { 28 | return (((1+Math.random())*0x10000)|0).toString(16).substring(1); 29 | }; 30 | 31 | // Generate a pseudo-GUID by concatenating random hexadecimal. 32 | function guid() { 33 | return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4()); 34 | }; 35 | 36 | // Our Store is represented by a single JS object in *localStorage*. Create it 37 | // with a meaningful name, like the name you'd give a table. 38 | // window.Store is deprecated, use Backbone.LocalStorage instead 39 | Backbone.LocalStorage = window.Store = function(name) { 40 | this.name = name; 41 | var store = this.localStorage().getItem(this.name); 42 | this.records = (store && store.split(",")) || []; 43 | }; 44 | 45 | _.extend(Backbone.LocalStorage.prototype, { 46 | 47 | // Save the current state of the **Store** to *localStorage*. 48 | save: function() { 49 | this.localStorage().setItem(this.name, this.records.join(",")); 50 | }, 51 | 52 | // Add a model, giving it a (hopefully)-unique GUID, if it doesn't already 53 | // have an id of it's own. 54 | create: function(model) { 55 | if (!model.id) { 56 | model.id = guid(); 57 | model.set(model.idAttribute, model.id); 58 | } 59 | this.localStorage().setItem(this.name+"-"+model.id, JSON.stringify(model)); 60 | this.records.push(model.id.toString()); 61 | this.save(); 62 | return this.find(model); 63 | }, 64 | 65 | // Update a model by replacing its copy in `this.data`. 66 | update: function(model) { 67 | this.localStorage().setItem(this.name+"-"+model.id, JSON.stringify(model)); 68 | if (!_.include(this.records, model.id.toString())) 69 | this.records.push(model.id.toString()); this.save(); 70 | return this.find(model); 71 | }, 72 | 73 | // Retrieve a model from `this.data` by id. 74 | find: function(model) { 75 | return this.jsonData(this.localStorage().getItem(this.name+"-"+model.id)); 76 | }, 77 | 78 | // Return the array of all models currently in storage. 79 | findAll: function() { 80 | return _(this.records).chain() 81 | .map(function(id){ 82 | return this.jsonData(this.localStorage().getItem(this.name+"-"+id)); 83 | }, this) 84 | .compact() 85 | .value(); 86 | }, 87 | 88 | // Delete a model from `this.data`, returning it. 89 | destroy: function(model) { 90 | if (model.isNew()) 91 | return false 92 | this.localStorage().removeItem(this.name+"-"+model.id); 93 | this.records = _.reject(this.records, function(id){ 94 | return id === model.id.toString(); 95 | }); 96 | this.save(); 97 | return model; 98 | }, 99 | 100 | localStorage: function() { 101 | return localStorage; 102 | }, 103 | 104 | // fix for "illegal access" error on Android when JSON.parse is passed null 105 | jsonData: function (data) { 106 | return data && JSON.parse(data); 107 | } 108 | 109 | }); 110 | 111 | // localSync delegate to the model or collection's 112 | // *localStorage* property, which should be an instance of `Store`. 113 | // window.Store.sync and Backbone.localSync is deprecated, use Backbone.LocalStorage.sync instead 114 | Backbone.LocalStorage.sync = window.Store.sync = Backbone.localSync = function(method, model, options) { 115 | var store = model.localStorage || model.collection.localStorage; 116 | 117 | var resp, errorMessage, syncDfd = $.Deferred && $.Deferred(); //If $ is having Deferred - use it. 118 | 119 | try { 120 | 121 | switch (method) { 122 | case "read": 123 | resp = model.id != undefined ? store.find(model) : store.findAll(); 124 | break; 125 | case "create": 126 | resp = store.create(model); 127 | break; 128 | case "update": 129 | resp = store.update(model); 130 | break; 131 | case "delete": 132 | resp = store.destroy(model); 133 | break; 134 | } 135 | 136 | } catch(error) { 137 | if (error.code === DOMException.QUOTA_EXCEEDED_ERR && window.localStorage.length === 0) 138 | errorMessage = "Private browsing is unsupported"; 139 | else 140 | errorMessage = error.message; 141 | } 142 | 143 | if (resp) { 144 | model.trigger("sync", model, resp, options); 145 | if (options && options.success) 146 | options.success(resp); 147 | if (syncDfd) 148 | syncDfd.resolve(resp); 149 | 150 | } else { 151 | errorMessage = errorMessage ? errorMessage 152 | : "Record Not Found"; 153 | 154 | if (options && options.error) 155 | options.error(errorMessage); 156 | if (syncDfd) 157 | syncDfd.reject(errorMessage); 158 | } 159 | 160 | // add compatibility with $.ajax 161 | // always execute callback for success and error 162 | if (options && options.complete) options.complete(resp); 163 | 164 | return syncDfd && syncDfd.promise(); 165 | }; 166 | 167 | Backbone.ajaxSync = Backbone.sync; 168 | 169 | Backbone.getSyncMethod = function(model) { 170 | if(model.localStorage || (model.collection && model.collection.localStorage)) { 171 | return Backbone.localSync; 172 | } 173 | 174 | return Backbone.ajaxSync; 175 | }; 176 | 177 | // Override 'Backbone.sync' to default to localSync, 178 | // the original 'Backbone.sync' is still available in 'Backbone.ajaxSync' 179 | Backbone.sync = function(method, model, options) { 180 | return Backbone.getSyncMethod(model).apply(this, [method, model, options]); 181 | }; 182 | 183 | return Backbone.LocalStorage; 184 | })); 185 | -------------------------------------------------------------------------------- /examples/todos/destroy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jashkenas/backbone/e8bc45acb0a8b035fe5a0d7338e1b2757681564f/examples/todos/destroy.png -------------------------------------------------------------------------------- /examples/todos/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Backbone.js Todos 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 |
15 |

Todos

16 | 17 |
18 | 19 |
20 | 21 | 22 |
    23 |
    24 | 25 | 29 | 30 |
    31 | 32 |
    33 | Double-click to edit a todo. 34 |
    35 | 36 |
    37 | Created by 38 |
    39 | Jérôme Gravel-Niquet. 40 |
    Rewritten by: TodoMVC. 41 |
    42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 60 | 61 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /examples/todos/todos.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | body { 8 | font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif; 9 | line-height: 1.4em; 10 | background: #eeeeee; 11 | color: #333333; 12 | width: 520px; 13 | margin: 0 auto; 14 | -webkit-font-smoothing: antialiased; 15 | } 16 | 17 | #todoapp { 18 | background: #fff; 19 | padding: 20px; 20 | margin-bottom: 40px; 21 | -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; 22 | -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; 23 | -ms-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; 24 | -o-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; 25 | box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0; 26 | -webkit-border-radius: 0 0 5px 5px; 27 | -moz-border-radius: 0 0 5px 5px; 28 | -ms-border-radius: 0 0 5px 5px; 29 | -o-border-radius: 0 0 5px 5px; 30 | border-radius: 0 0 5px 5px; 31 | } 32 | 33 | #todoapp h1 { 34 | font-size: 36px; 35 | font-weight: bold; 36 | text-align: center; 37 | padding: 0 0 10px 0; 38 | } 39 | 40 | #todoapp input[type="text"] { 41 | width: 466px; 42 | font-size: 24px; 43 | font-family: inherit; 44 | line-height: 1.4em; 45 | border: 0; 46 | outline: none; 47 | padding: 6px; 48 | border: 1px solid #999999; 49 | -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; 50 | -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; 51 | -ms-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; 52 | -o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; 53 | box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset; 54 | } 55 | 56 | #todoapp input::-webkit-input-placeholder { 57 | font-style: italic; 58 | } 59 | 60 | #main { 61 | display: none; 62 | } 63 | 64 | #todo-list { 65 | margin: 10px 0; 66 | padding: 0; 67 | list-style: none; 68 | } 69 | 70 | #todo-list li { 71 | padding: 18px 20px 18px 0; 72 | position: relative; 73 | font-size: 24px; 74 | border-bottom: 1px solid #cccccc; 75 | } 76 | 77 | #todo-list li:last-child { 78 | border-bottom: none; 79 | } 80 | 81 | #todo-list li.done label { 82 | color: #777777; 83 | text-decoration: line-through; 84 | } 85 | 86 | #todo-list .destroy { 87 | position: absolute; 88 | right: 5px; 89 | top: 20px; 90 | display: none; 91 | cursor: pointer; 92 | width: 20px; 93 | height: 20px; 94 | background: url(destroy.png) no-repeat; 95 | } 96 | 97 | #todo-list li:hover .destroy { 98 | display: block; 99 | } 100 | 101 | #todo-list .destroy:hover { 102 | background-position: 0 -20px; 103 | } 104 | 105 | #todo-list li.editing { 106 | border-bottom: none; 107 | margin-top: -1px; 108 | padding: 0; 109 | } 110 | 111 | #todo-list li.editing:last-child { 112 | margin-bottom: -1px; 113 | } 114 | 115 | #todo-list li.editing .edit { 116 | display: block; 117 | width: 444px; 118 | padding: 13px 15px 14px 20px; 119 | margin: 0; 120 | } 121 | 122 | #todo-list li.editing .view { 123 | display: none; 124 | } 125 | 126 | #todo-list li .view label { 127 | word-break: break-word; 128 | } 129 | 130 | #todo-list li .edit { 131 | display: none; 132 | } 133 | 134 | #todoapp footer { 135 | display: none; 136 | margin: 0 -20px -20px -20px; 137 | overflow: hidden; 138 | color: #555555; 139 | background: #f4fce8; 140 | border-top: 1px solid #ededed; 141 | padding: 0 20px; 142 | line-height: 37px; 143 | -webkit-border-radius: 0 0 5px 5px; 144 | -moz-border-radius: 0 0 5px 5px; 145 | -ms-border-radius: 0 0 5px 5px; 146 | -o-border-radius: 0 0 5px 5px; 147 | border-radius: 0 0 5px 5px; 148 | } 149 | 150 | #clear-completed { 151 | float: right; 152 | line-height: 20px; 153 | text-decoration: none; 154 | background: rgba(0, 0, 0, 0.1); 155 | color: #555555; 156 | font-size: 11px; 157 | margin-top: 8px; 158 | margin-bottom: 8px; 159 | padding: 0 10px 1px; 160 | cursor: pointer; 161 | -webkit-border-radius: 12px; 162 | -moz-border-radius: 12px; 163 | -ms-border-radius: 12px; 164 | -o-border-radius: 12px; 165 | border-radius: 12px; 166 | -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; 167 | -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; 168 | -ms-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; 169 | -o-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; 170 | box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0; 171 | } 172 | 173 | #clear-completed:hover { 174 | background: rgba(0, 0, 0, 0.15); 175 | -webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; 176 | -moz-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; 177 | -ms-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; 178 | -o-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; 179 | box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0; 180 | } 181 | 182 | #clear-completed:active { 183 | position: relative; 184 | top: 1px; 185 | } 186 | 187 | #todo-count span { 188 | font-weight: bold; 189 | } 190 | 191 | #instructions { 192 | margin: 10px auto; 193 | color: #777777; 194 | text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0; 195 | text-align: center; 196 | } 197 | 198 | #instructions a { 199 | color: #336699; 200 | } 201 | 202 | #credits { 203 | margin: 30px auto; 204 | color: #999; 205 | text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0; 206 | text-align: center; 207 | } 208 | 209 | #credits a { 210 | color: #888; 211 | } 212 | -------------------------------------------------------------------------------- /examples/todos/todos.js: -------------------------------------------------------------------------------- 1 | // An example Backbone application contributed by 2 | // [Jérôme Gravel-Niquet](http://jgn.me/). This demo uses a simple 3 | // [LocalStorage adapter](backbone.localStorage.html) 4 | // to persist Backbone models within your browser. 5 | 6 | // Load the application once the DOM is ready, using `jQuery.ready`: 7 | $(function(){ 8 | 9 | // Todo Model 10 | // ---------- 11 | 12 | // Our basic **Todo** model has `title`, `order`, and `done` attributes. 13 | var Todo = Backbone.Model.extend({ 14 | 15 | // Default attributes for the todo item. 16 | defaults: function() { 17 | return { 18 | title: "empty todo...", 19 | order: Todos.nextOrder(), 20 | done: false 21 | }; 22 | }, 23 | 24 | // Toggle the `done` state of this todo item. 25 | toggle: function() { 26 | this.save({done: !this.get("done")}); 27 | } 28 | 29 | }); 30 | 31 | // Todo Collection 32 | // --------------- 33 | 34 | // The collection of todos is backed by *localStorage* instead of a remote 35 | // server. 36 | var TodoList = Backbone.Collection.extend({ 37 | 38 | // Reference to this collection's model. 39 | model: Todo, 40 | 41 | // Save all of the todo items under the `"todos-backbone"` namespace. 42 | localStorage: new Backbone.LocalStorage("todos-backbone"), 43 | 44 | // Filter down the list of all todo items that are finished. 45 | done: function() { 46 | return this.where({done: true}); 47 | }, 48 | 49 | // Filter down the list to only todo items that are still not finished. 50 | remaining: function() { 51 | return this.where({done: false}); 52 | }, 53 | 54 | // We keep the Todos in sequential order, despite being saved by unordered 55 | // GUID in the database. This generates the next order number for new items. 56 | nextOrder: function() { 57 | if (!this.length) return 1; 58 | return this.last().get('order') + 1; 59 | }, 60 | 61 | // Todos are sorted by their original insertion order. 62 | comparator: 'order' 63 | 64 | }); 65 | 66 | // Create our global collection of **Todos**. 67 | var Todos = new TodoList; 68 | 69 | // Todo Item View 70 | // -------------- 71 | 72 | // The DOM element for a todo item... 73 | var TodoView = Backbone.View.extend({ 74 | 75 | //... is a list tag. 76 | tagName: "li", 77 | 78 | // Cache the template function for a single item. 79 | template: _.template($('#item-template').html()), 80 | 81 | // The DOM events specific to an item. 82 | events: { 83 | "click .toggle" : "toggleDone", 84 | "dblclick .view" : "edit", 85 | "click a.destroy" : "clear", 86 | "keypress .edit" : "updateOnEnter", 87 | "blur .edit" : "close" 88 | }, 89 | 90 | // The TodoView listens for changes to its model, re-rendering. Since there's 91 | // a one-to-one correspondence between a **Todo** and a **TodoView** in this 92 | // app, we set a direct reference on the model for convenience. 93 | initialize: function() { 94 | this.listenTo(this.model, 'change', this.render); 95 | this.listenTo(this.model, 'destroy', this.remove); 96 | }, 97 | 98 | // Re-render the titles of the todo item. 99 | render: function() { 100 | this.$el.html(this.template(this.model.toJSON())); 101 | this.$el.toggleClass('done', this.model.get('done')); 102 | this.input = this.$('.edit'); 103 | return this; 104 | }, 105 | 106 | // Toggle the `"done"` state of the model. 107 | toggleDone: function() { 108 | this.model.toggle(); 109 | }, 110 | 111 | // Switch this view into `"editing"` mode, displaying the input field. 112 | edit: function() { 113 | this.$el.addClass("editing"); 114 | this.input.focus(); 115 | }, 116 | 117 | // Close the `"editing"` mode, saving changes to the todo. 118 | close: function() { 119 | var value = this.input.val(); 120 | if (!value) { 121 | this.clear(); 122 | } else { 123 | this.model.save({title: value}); 124 | this.$el.removeClass("editing"); 125 | } 126 | }, 127 | 128 | // If you hit `enter`, we're through editing the item. 129 | updateOnEnter: function(e) { 130 | if (e.keyCode == 13) this.close(); 131 | }, 132 | 133 | // Remove the item, destroy the model. 134 | clear: function() { 135 | this.model.destroy(); 136 | } 137 | 138 | }); 139 | 140 | // The Application 141 | // --------------- 142 | 143 | // Our overall **AppView** is the top-level piece of UI. 144 | var AppView = Backbone.View.extend({ 145 | 146 | // Instead of generating a new element, bind to the existing skeleton of 147 | // the App already present in the HTML. 148 | el: $("#todoapp"), 149 | 150 | // Our template for the line of statistics at the bottom of the app. 151 | statsTemplate: _.template($('#stats-template').html()), 152 | 153 | // Delegated events for creating new items, and clearing completed ones. 154 | events: { 155 | "keypress #new-todo": "createOnEnter", 156 | "click #clear-completed": "clearCompleted", 157 | "click #toggle-all": "toggleAllComplete" 158 | }, 159 | 160 | // At initialization we bind to the relevant events on the `Todos` 161 | // collection, when items are added or changed. Kick things off by 162 | // loading any preexisting todos that might be saved in *localStorage*. 163 | initialize: function() { 164 | 165 | this.input = this.$("#new-todo"); 166 | this.allCheckbox = this.$("#toggle-all")[0]; 167 | 168 | this.listenTo(Todos, 'add', this.addOne); 169 | this.listenTo(Todos, 'reset', this.addAll); 170 | this.listenTo(Todos, 'all', this.render); 171 | 172 | this.footer = this.$('footer'); 173 | this.main = $('#main'); 174 | 175 | Todos.fetch(); 176 | }, 177 | 178 | // Re-rendering the App just means refreshing the statistics -- the rest 179 | // of the app doesn't change. 180 | render: function() { 181 | var done = Todos.done().length; 182 | var remaining = Todos.remaining().length; 183 | 184 | if (Todos.length) { 185 | this.main.show(); 186 | this.footer.show(); 187 | this.footer.html(this.statsTemplate({done: done, remaining: remaining})); 188 | } else { 189 | this.main.hide(); 190 | this.footer.hide(); 191 | } 192 | 193 | this.allCheckbox.checked = !remaining; 194 | }, 195 | 196 | // Add a single todo item to the list by creating a view for it, and 197 | // appending its element to the `