├── .editorconfig
├── .gitignore
├── README.md
├── chapter10
├── .babelrc
├── .eslintrc
├── .gitignore
├── .jshintrc
├── LICENSE
├── README.md
├── __tests__
│ ├── app-test.js
│ └── response.json
├── index.html
├── package.json
├── server.js
├── src
│ ├── App.js
│ ├── Cats.css
│ ├── Home.js
│ ├── Modal.js
│ ├── Picture.js
│ ├── index.js
│ └── models.js
└── webpack.config.js
├── chapter11
├── .eslintrc
├── .gitignore
├── .jshintrc
├── LICENSE
├── README.md
├── __tests__
│ └── .keep
├── index.html
├── package.json
├── server.js
├── src
│ ├── App.js
│ ├── Cats.css
│ ├── Home.js
│ ├── Modal.js
│ ├── Picture.js
│ ├── index.js
│ └── models.js
└── webpack.config.js
├── chapter12
├── .gitignore
├── README.md
├── config.example.js
├── config.js
├── css
│ └── app.css
├── index.html
├── js
│ ├── actions
│ │ └── SocialActions.js
│ ├── app.js
│ ├── components
│ │ ├── Header.react.js
│ │ ├── MainSection.react.js
│ │ └── SocialTracker.react.js
│ ├── constants
│ │ └── SocialConstants.js
│ ├── dispatcher
│ │ └── AppDispatcher.js
│ ├── stores
│ │ └── SocialStore.js
│ └── utils
│ │ ├── array.js
│ │ └── jsonutil.js
├── package.json
├── screenshot.png
└── server.js
├── chapter13
├── .babelrc
├── .gitignore
├── README.md
├── actions
│ └── social.js
├── components
│ └── SocialTracker.js
├── config.example.js
├── containers
│ └── App.js
├── index.html
├── index.js
├── package.json
├── reducers
│ ├── index.js
│ └── social.js
├── server.js
├── store
│ └── configureStore.js
├── styles
│ └── App.css
├── test
│ ├── .eslintrc
│ ├── actions
│ │ └── counter.spec.js
│ ├── components
│ │ └── Counter.spec.js
│ ├── containers
│ │ └── App.spec.js
│ ├── reducers
│ │ └── counter.spec.js
│ └── setup.js
├── utils
│ ├── array.js
│ └── jsonutil.js
└── webpack.config.js
├── chapter2
├── index.html
└── src
│ ├── App.js
│ └── index.js
├── chapter4
├── .babelrc
├── .eslintrc
├── .gitignore
├── .jshintrc
├── LICENSE
├── README.md
├── index.html
├── package.json
├── server.js
├── src
│ ├── BookStore.js
│ └── index.js
└── webpack.config.js
├── chapter5
├── .babelrc
├── .eslintrc
├── .gitignore
├── .jshintrc
├── LICENSE
├── README.md
├── index.html
├── package.json
├── server.js
├── src
│ ├── App.js
│ ├── booklist.js
│ ├── confirmation.js
│ ├── delivery_details.js
│ ├── index.js
│ ├── mixins
│ │ ├── cart_timeout_mixin.js
│ │ └── set_interval_mixin.js
│ ├── modals
│ │ └── modal_alert_timeout.js
│ ├── shipping_details.js
│ └── success.js
└── webpack.config.js
├── chapter6-iso
├── .babelrc
├── .gitignore
├── .jshintrc
├── LICENSE
├── README.md
├── config
│ └── app.js
├── package.json
├── src
│ ├── app
│ │ ├── __tests__
│ │ │ └── app.spec.js
│ │ ├── app.js
│ │ ├── components
│ │ │ ├── AppRoot.js
│ │ │ ├── SearchPage.js
│ │ │ └── __tests__
│ │ │ │ ├── AppRoot.spec.js
│ │ │ │ ├── Cart.spec.js
│ │ │ │ └── Item.spec.js
│ │ └── index.js
│ ├── client
│ │ ├── index.ejs
│ │ ├── index.html
│ │ ├── scripts
│ │ │ └── client.js
│ │ └── styles
│ │ │ └── main.css
│ └── server
│ │ ├── index.js
│ │ └── server.js
├── tools
│ └── preprocessor.js
└── webpack.js
├── chapter6-rails
├── .eslintrc
├── .gitignore
├── .ruby-version
├── Gemfile
├── Gemfile.lock
├── Procfile
├── README.md
├── Rakefile
├── app
│ ├── admin
│ │ ├── dashboard.rb
│ │ └── user.rb
│ ├── assets
│ │ ├── javascripts
│ │ │ ├── application_common.js
│ │ │ ├── application_desktop.js
│ │ │ ├── application_phone.js
│ │ │ ├── common
│ │ │ │ ├── active_admin.js
│ │ │ │ ├── bootstrap.js
│ │ │ │ ├── fetch.js
│ │ │ │ └── modal_behavior.js
│ │ │ ├── components.js
│ │ │ ├── components
│ │ │ │ ├── .gitkeep
│ │ │ │ └── SearchPage.js.jsx
│ │ │ ├── desktop
│ │ │ │ └── .gitkeep
│ │ │ └── phone
│ │ │ │ └── .gitkeep
│ │ └── stylesheets
│ │ │ ├── application_common.scss
│ │ │ ├── application_desktop.scss
│ │ │ ├── application_phone.scss
│ │ │ ├── bootstrap
│ │ │ ├── custom.scss
│ │ │ └── devise_forms.scss
│ │ │ ├── common
│ │ │ ├── active_admin.scss
│ │ │ ├── alerts.scss
│ │ │ └── base.scss
│ │ │ ├── desktop
│ │ │ └── .gitkeep
│ │ │ ├── environment
│ │ │ └── ribbon.scss
│ │ │ └── phone
│ │ │ └── .gitkeep
│ ├── carriers
│ │ └── layout_carrier.rb
│ ├── controllers
│ │ ├── api
│ │ │ └── v1
│ │ │ │ ├── base_controller.rb
│ │ │ │ ├── sessions_controller.rb
│ │ │ │ └── users_controller.rb
│ │ ├── application_controller.rb
│ │ ├── contacts_controller.rb
│ │ ├── home_controller.rb
│ │ ├── pages_controller.rb
│ │ ├── registrations_controller.rb
│ │ ├── sessions_controller.rb
│ │ └── superadmin
│ │ │ ├── base_controller.rb
│ │ │ └── users_controller.rb
│ ├── helpers
│ │ └── application_helper.rb
│ ├── mailers
│ │ └── mailer.rb
│ ├── middleware
│ │ └── catch_json_parse_errors.rb
│ ├── models
│ │ ├── contact.rb
│ │ └── user.rb
│ ├── services
│ │ └── addition_service.rb
│ ├── uploaders
│ │ └── profile_image_uploader.rb
│ ├── views
│ │ ├── home
│ │ │ └── index.html.haml
│ │ ├── layouts
│ │ │ ├── application.html+phone.haml
│ │ │ ├── application.html.haml
│ │ │ ├── mailer.haml
│ │ │ └── superadmin.html.haml
│ │ ├── mailer
│ │ │ └── contact_us_notification.html.haml
│ │ ├── pages
│ │ │ ├── about.html+phone.haml
│ │ │ ├── about.html.haml
│ │ │ ├── contact_us.html.haml
│ │ │ └── index.html.haml
│ │ ├── shared
│ │ │ ├── _bootstrap_flash.html.haml
│ │ │ ├── _modal.html.haml
│ │ │ ├── _nav.html.haml
│ │ │ ├── _superadmin_nav.html.haml
│ │ │ ├── _user_is_signed_in.html.haml
│ │ │ └── _user_right_nav.html.haml
│ │ ├── superadmin
│ │ │ └── users
│ │ │ │ ├── _edit_modal.html.haml
│ │ │ │ └── index.html.haml
│ │ └── users
│ │ │ ├── confirmations
│ │ │ └── new.html.haml
│ │ │ ├── mailer
│ │ │ ├── confirmation_instructions.html.haml
│ │ │ ├── reset_password_instructions.html.haml
│ │ │ └── unlock_instructions.html.haml
│ │ │ ├── passwords
│ │ │ ├── edit.html.haml
│ │ │ └── new.html.haml
│ │ │ ├── registrations
│ │ │ ├── edit.html.haml
│ │ │ ├── edit_password.html.haml
│ │ │ └── new.html.haml
│ │ │ ├── sessions
│ │ │ └── new.html.haml
│ │ │ ├── shared
│ │ │ └── _links.haml
│ │ │ └── unlocks
│ │ │ └── new.html.haml
│ └── workers
│ │ ├── base_worker.rb
│ │ └── event_notification_worker.rb
├── bin
│ ├── bundle
│ ├── delayed_job
│ ├── honeybadger
│ ├── rails
│ ├── rake
│ ├── setup
│ └── spring
├── circle.yml
├── config.ru
├── config
│ ├── application.rb
│ ├── boot.rb
│ ├── database.yml.ci
│ ├── database.yml.postgresql
│ ├── database.yml.postgresqlapp
│ ├── database.yml.sqlite3
│ ├── environment.rb
│ ├── environments
│ │ ├── development.rb
│ │ ├── production.rb
│ │ ├── staging.rb
│ │ └── test.rb
│ ├── honeybadger.yml
│ ├── initializers
│ │ ├── active_admin.rb
│ │ ├── asset_precompile.rb
│ │ ├── assets.rb
│ │ ├── backtrace_silencers.rb
│ │ ├── catch_json_parser_errors.rb
│ │ ├── cookies_serializer.rb
│ │ ├── delayed_job_config.rb
│ │ ├── delayed_job_invoke_worker_automatically.rb
│ │ ├── devise.rb
│ │ ├── devise_async.rb
│ │ ├── email_interceptor.rb
│ │ ├── email_prefixer.rb
│ │ ├── filter_parameter_logging.rb
│ │ ├── honeybadger.rb
│ │ ├── inflections.rb
│ │ ├── marginalia.rb
│ │ ├── mime_types.rb
│ │ ├── rack_deflater.rb
│ │ ├── session_store.rb
│ │ ├── setup_email.rb
│ │ ├── simple_form.rb
│ │ ├── simple_form_bootstrap.rb
│ │ ├── tagged_logging.rb
│ │ └── wrap_parameters.rb
│ ├── locales
│ │ ├── devise.en.yml
│ │ ├── en.bootstrap.yml
│ │ ├── en.yml
│ │ └── simple_form.en.yml
│ ├── routes.rb
│ ├── secrets.yml
│ └── unicorn.rb
├── db
│ ├── migrate
│ │ ├── 20131112184628_add_devise_to_users.rb
│ │ ├── 20131120170220_create_delayed_jobs.rb
│ │ ├── 20131122045009_add_user_attributes.rb
│ │ ├── 20131213184726_create_active_admin_comments.rb
│ │ ├── 20140220111712_add_authentication_token_to_users.rb
│ │ └── 20140225143027_add_profile_image_to_users.rb
│ ├── schema.rb
│ └── seeds.rb
├── doc
│ ├── api.md
│ └── why_database_name_only_63_characters_long.md
├── lib
│ ├── tasks
│ │ └── setup.rake
│ └── templates
│ │ └── erb
│ │ └── scaffold
│ │ └── _form.html.erb
├── public
│ ├── 404.html
│ ├── 422.html
│ ├── 500.html
│ ├── favicon.ico
│ └── robots.txt
└── test
│ ├── controllers
│ ├── active_admin
│ │ └── dashboard_controller_test.rb
│ ├── api
│ │ └── v1
│ │ │ ├── sessions_controller_test.rb
│ │ │ └── users_controller_test.rb
│ ├── contacts_controller_test.rb
│ ├── home_controller_test.rb
│ ├── pages_controller_test.rb
│ ├── registrations_controller_test.rb
│ └── superadmin
│ │ └── users_controller_test.rb
│ ├── fixtures
│ └── users.yml
│ ├── integration
│ ├── api_invalid_json_data_test.rb
│ └── compression_test.rb
│ ├── models
│ ├── contact_test.rb
│ └── user_test.rb
│ ├── services
│ └── addition_service_test.rb
│ └── test_helper.rb
├── chapter6
├── .babelrc
├── .eslintrc
├── .gitignore
├── .jshintrc
├── LICENSE
├── README.md
├── index.html
├── package.json
├── server.js
├── src
│ ├── App.js
│ └── index.js
└── webpack.config.js
├── chapter7
├── .babelrc
├── .eslintrc
├── .gitignore
├── .jshintrc
├── LICENSE
├── README.md
├── __tests__
│ ├── app-test.js
│ └── response.json
├── bower_components
│ ├── bootstrap
│ │ ├── .bower.json
│ │ ├── Gruntfile.js
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── bower.json
│ │ ├── dist
│ │ │ ├── css
│ │ │ │ ├── bootstrap-theme.css
│ │ │ │ ├── bootstrap-theme.css.map
│ │ │ │ ├── bootstrap-theme.min.css
│ │ │ │ ├── bootstrap.css
│ │ │ │ ├── bootstrap.css.map
│ │ │ │ └── bootstrap.min.css
│ │ │ ├── fonts
│ │ │ │ ├── glyphicons-halflings-regular.eot
│ │ │ │ ├── glyphicons-halflings-regular.svg
│ │ │ │ ├── glyphicons-halflings-regular.ttf
│ │ │ │ ├── glyphicons-halflings-regular.woff
│ │ │ │ └── glyphicons-halflings-regular.woff2
│ │ │ └── js
│ │ │ │ ├── bootstrap.js
│ │ │ │ ├── bootstrap.min.js
│ │ │ │ └── npm.js
│ │ ├── fonts
│ │ │ ├── glyphicons-halflings-regular.eot
│ │ │ ├── glyphicons-halflings-regular.svg
│ │ │ ├── glyphicons-halflings-regular.ttf
│ │ │ ├── glyphicons-halflings-regular.woff
│ │ │ └── glyphicons-halflings-regular.woff2
│ │ ├── grunt
│ │ │ ├── .jshintrc
│ │ │ ├── bs-commonjs-generator.js
│ │ │ ├── bs-glyphicons-data-generator.js
│ │ │ ├── bs-lessdoc-parser.js
│ │ │ ├── bs-raw-files-generator.js
│ │ │ ├── configBridge.json
│ │ │ └── sauce_browsers.yml
│ │ ├── js
│ │ │ ├── .jscsrc
│ │ │ ├── .jshintrc
│ │ │ ├── affix.js
│ │ │ ├── alert.js
│ │ │ ├── button.js
│ │ │ ├── carousel.js
│ │ │ ├── collapse.js
│ │ │ ├── dropdown.js
│ │ │ ├── modal.js
│ │ │ ├── popover.js
│ │ │ ├── scrollspy.js
│ │ │ ├── tab.js
│ │ │ ├── tooltip.js
│ │ │ └── transition.js
│ │ ├── less
│ │ │ ├── .csscomb.json
│ │ │ ├── .csslintrc
│ │ │ ├── alerts.less
│ │ │ ├── badges.less
│ │ │ ├── bootstrap.less
│ │ │ ├── breadcrumbs.less
│ │ │ ├── button-groups.less
│ │ │ ├── buttons.less
│ │ │ ├── carousel.less
│ │ │ ├── close.less
│ │ │ ├── code.less
│ │ │ ├── component-animations.less
│ │ │ ├── dropdowns.less
│ │ │ ├── forms.less
│ │ │ ├── glyphicons.less
│ │ │ ├── grid.less
│ │ │ ├── input-groups.less
│ │ │ ├── jumbotron.less
│ │ │ ├── labels.less
│ │ │ ├── list-group.less
│ │ │ ├── media.less
│ │ │ ├── mixins.less
│ │ │ ├── mixins
│ │ │ │ ├── alerts.less
│ │ │ │ ├── background-variant.less
│ │ │ │ ├── border-radius.less
│ │ │ │ ├── buttons.less
│ │ │ │ ├── center-block.less
│ │ │ │ ├── clearfix.less
│ │ │ │ ├── forms.less
│ │ │ │ ├── gradients.less
│ │ │ │ ├── grid-framework.less
│ │ │ │ ├── grid.less
│ │ │ │ ├── hide-text.less
│ │ │ │ ├── image.less
│ │ │ │ ├── labels.less
│ │ │ │ ├── list-group.less
│ │ │ │ ├── nav-divider.less
│ │ │ │ ├── nav-vertical-align.less
│ │ │ │ ├── opacity.less
│ │ │ │ ├── pagination.less
│ │ │ │ ├── panels.less
│ │ │ │ ├── progress-bar.less
│ │ │ │ ├── reset-filter.less
│ │ │ │ ├── reset-text.less
│ │ │ │ ├── resize.less
│ │ │ │ ├── responsive-visibility.less
│ │ │ │ ├── size.less
│ │ │ │ ├── tab-focus.less
│ │ │ │ ├── table-row.less
│ │ │ │ ├── text-emphasis.less
│ │ │ │ ├── text-overflow.less
│ │ │ │ └── vendor-prefixes.less
│ │ │ ├── modals.less
│ │ │ ├── navbar.less
│ │ │ ├── navs.less
│ │ │ ├── normalize.less
│ │ │ ├── pager.less
│ │ │ ├── pagination.less
│ │ │ ├── panels.less
│ │ │ ├── popovers.less
│ │ │ ├── print.less
│ │ │ ├── progress-bars.less
│ │ │ ├── responsive-embed.less
│ │ │ ├── responsive-utilities.less
│ │ │ ├── scaffolding.less
│ │ │ ├── tables.less
│ │ │ ├── theme.less
│ │ │ ├── thumbnails.less
│ │ │ ├── tooltip.less
│ │ │ ├── type.less
│ │ │ ├── utilities.less
│ │ │ ├── variables.less
│ │ │ └── wells.less
│ │ ├── package.js
│ │ └── package.json
│ └── jquery
│ │ ├── .bower.json
│ │ ├── MIT-LICENSE.txt
│ │ ├── bower.json
│ │ ├── dist
│ │ ├── jquery.js
│ │ ├── jquery.min.js
│ │ └── jquery.min.map
│ │ └── src
│ │ ├── ajax.js
│ │ ├── ajax
│ │ ├── jsonp.js
│ │ ├── load.js
│ │ ├── parseJSON.js
│ │ ├── parseXML.js
│ │ ├── script.js
│ │ ├── var
│ │ │ ├── nonce.js
│ │ │ └── rquery.js
│ │ └── xhr.js
│ │ ├── attributes.js
│ │ ├── attributes
│ │ ├── attr.js
│ │ ├── classes.js
│ │ ├── prop.js
│ │ ├── support.js
│ │ └── val.js
│ │ ├── callbacks.js
│ │ ├── core.js
│ │ ├── core
│ │ ├── access.js
│ │ ├── init.js
│ │ ├── parseHTML.js
│ │ ├── ready.js
│ │ └── var
│ │ │ └── rsingleTag.js
│ │ ├── css.js
│ │ ├── css
│ │ ├── addGetHookIf.js
│ │ ├── curCSS.js
│ │ ├── defaultDisplay.js
│ │ ├── hiddenVisibleSelectors.js
│ │ ├── support.js
│ │ ├── swap.js
│ │ └── var
│ │ │ ├── cssExpand.js
│ │ │ ├── getStyles.js
│ │ │ ├── isHidden.js
│ │ │ ├── rmargin.js
│ │ │ └── rnumnonpx.js
│ │ ├── data.js
│ │ ├── data
│ │ ├── Data.js
│ │ ├── accepts.js
│ │ └── var
│ │ │ ├── data_priv.js
│ │ │ └── data_user.js
│ │ ├── deferred.js
│ │ ├── deprecated.js
│ │ ├── dimensions.js
│ │ ├── effects.js
│ │ ├── effects
│ │ ├── Tween.js
│ │ └── animatedSelector.js
│ │ ├── event.js
│ │ ├── event
│ │ ├── ajax.js
│ │ ├── alias.js
│ │ └── support.js
│ │ ├── exports
│ │ ├── amd.js
│ │ └── global.js
│ │ ├── intro.js
│ │ ├── jquery.js
│ │ ├── manipulation.js
│ │ ├── manipulation
│ │ ├── _evalUrl.js
│ │ ├── support.js
│ │ └── var
│ │ │ └── rcheckableType.js
│ │ ├── offset.js
│ │ ├── outro.js
│ │ ├── queue.js
│ │ ├── queue
│ │ └── delay.js
│ │ ├── selector-native.js
│ │ ├── selector-sizzle.js
│ │ ├── selector.js
│ │ ├── serialize.js
│ │ ├── sizzle
│ │ └── dist
│ │ │ ├── sizzle.js
│ │ │ ├── sizzle.min.js
│ │ │ └── sizzle.min.map
│ │ ├── traversing.js
│ │ ├── traversing
│ │ ├── findFilter.js
│ │ └── var
│ │ │ └── rneedsContext.js
│ │ ├── var
│ │ ├── arr.js
│ │ ├── class2type.js
│ │ ├── concat.js
│ │ ├── hasOwn.js
│ │ ├── indexOf.js
│ │ ├── pnum.js
│ │ ├── push.js
│ │ ├── rnotwhite.js
│ │ ├── slice.js
│ │ ├── strundefined.js
│ │ ├── support.js
│ │ └── toString.js
│ │ └── wrap.js
├── index.html
├── package.json
├── server.js
├── src
│ ├── App.js
│ ├── RowAlternator.js
│ ├── Spinner.js
│ └── index.js
└── webpack.config.js
├── chapter8
├── .babelrc
├── .eslintrc
├── .gitignore
├── .jshintrc
├── LICENSE
├── README.md
├── __tests__
│ ├── app-test.js
│ └── response.json
├── index.html
├── package.json
├── server.js
├── src
│ ├── App.js
│ ├── BookList.js
│ ├── BookListHeader.js
│ ├── BookRow.js
│ ├── BookTableHeader.js
│ ├── Form.js
│ ├── Header.js
│ ├── RowAlternator.js
│ ├── Spinner.js
│ └── index.js
└── webpack.config.js
└── chapter9
├── .babelrc
├── .eslintrc
├── .gitignore
├── .jshintrc
├── LICENSE
├── README.md
├── __tests__
├── app-test.js
└── response.json
├── index.html
├── package.json
├── server.js
├── src
├── App.js
├── Home.js
├── Modal.js
├── Picture.js
├── Sample.js
├── index.js
└── models.js
└── webpack.config.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | end_of_line = lf
7 | indent_size = 2
8 | indent_style = space
9 | max_line_length = 80
10 | trim_trailing_whitespace = true
11 |
12 | [*.md]
13 | max_line_length = 0
14 | trim_trailing_whitespace = false
15 |
16 | [COMMIT_EDITMSG]
17 | max_line_length = 0
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | reactjs-by-example
2 | ===========
3 |
4 | Examples for "ReactJS by Example"
5 |
6 | ### Usage
7 |
8 | See individual directories for usage
9 |
--------------------------------------------------------------------------------
/chapter10/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "stage": 0
3 | }
4 |
--------------------------------------------------------------------------------
/chapter10/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/chapter10/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "browser": true,
4 | "esnext": true,
5 | "newcap": false
6 | }
7 |
--------------------------------------------------------------------------------
/chapter10/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Vipul A M
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/chapter10/README.md:
--------------------------------------------------------------------------------
1 | react-addons
2 | ===========
3 |
4 | Examples of React addons
5 |
6 | ### Usage
7 |
8 | ```
9 | npm install
10 | npm start
11 | open http://localhost:9000
12 | npm test
13 | ```
14 |
--------------------------------------------------------------------------------
/chapter10/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | React Router/ Data Models
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/chapter10/server.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var WebpackDevServer = require('webpack-dev-server');
3 | var config = require('./webpack.config');
4 |
5 | new WebpackDevServer(webpack(config), {
6 | publicPath: config.output.publicPath,
7 | hot: true,
8 | historyApiFallback: true
9 | }).listen(9000, 'localhost', function (err, result) {
10 | if (err) {
11 | console.log(err);
12 | }
13 |
14 | console.log('Listening at localhost:9000');
15 | });
16 |
--------------------------------------------------------------------------------
/chapter10/src/Modal.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Router, Route, IndexRoute, Link } from 'react-router'
3 |
4 | const Modal = React.createClass({
5 | styles: {
6 | position: 'fixed',
7 | top: '20%',
8 | right: '20%',
9 | bottom: '20%',
10 | left: '20%',
11 | padding: 20,
12 | boxShadow: '0px 0px 150px 130px rgba(0, 0, 0, 0.5)',
13 | overflow: 'auto',
14 | background: '#fff'
15 | },
16 |
17 | render() {
18 | return (
19 |
20 |
Back
21 | {this.props.children}
22 |
23 | )
24 | }
25 | })
26 |
27 | export {Modal as default}
28 |
--------------------------------------------------------------------------------
/chapter10/src/Picture.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { PictureModel } from './models';
3 |
4 | const Picture = React.createClass({
5 | render() {
6 | let { location } = this.props;
7 | let cat = location.state.cat;
8 | console.log(this.props);
9 | return (
10 |
11 |
12 |
})
13 |
14 |
15 |
Name: {cat.get('name')}.
16 |
Details: {cat.get('details')}
17 |
18 |
19 | )
20 | }
21 | });
22 |
23 | export {Picture as default}
24 |
--------------------------------------------------------------------------------
/chapter10/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { render } from 'react-dom'
3 | import { createHistory, useBasename } from 'history'
4 | import { Router, Route, IndexRoute, Link } from 'react-router'
5 | import Backbone from 'backbone';
6 | import Modal from './Modal'
7 | import App from './App'
8 | import Picture from './Picture'
9 | import Home from './Home'
10 |
11 | const history = useBasename(createHistory)({
12 | basename: '/pinterest'
13 | });
14 |
15 |
16 | render((
17 |
18 |
19 |
20 |
21 |
22 |
23 | ), document.getElementById('rootElement'));
24 |
--------------------------------------------------------------------------------
/chapter10/src/models.js:
--------------------------------------------------------------------------------
1 | import Backbone from 'backbone';
2 | import Faker from 'faker';
3 | import _ from 'underscore';
4 |
5 | const PictureModel = Backbone.Model.extend({
6 | defaults: {
7 | src: 'http://lorempixel.com/601/600/cats/',
8 | name: 'Pusheen',
9 | details: 'Pusheen is a Cat',
10 | faved: false
11 | }
12 | });
13 |
14 | class CatGenerator {
15 | constructor() {
16 | this.Cats = new Backbone.Collection;
17 | [600, 601, 602, 603, 604, 605].map( (height)=>{
18 | this.createCat(height, 600);
19 | })
20 | }
21 |
22 | createCat(height = _.random(600, 650), width = 600) {
23 | console.log('Adding new cat');
24 | this.Cats.add(new PictureModel({
25 | src: `http://lorempixel.com/${height}/${width}/cats/`,
26 | name: Faker.Name.findName(),
27 | details: Faker.Lorem.paragraph()
28 | }));
29 | }
30 |
31 | randRange() {
32 | return _.random(5000, 10000);
33 | }
34 |
35 | }
36 |
37 | module.exports = {PictureModel, CatGenerator};
38 |
--------------------------------------------------------------------------------
/chapter11/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/chapter11/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "browser": true,
4 | "esnext": true,
5 | "newcap": false
6 | }
7 |
--------------------------------------------------------------------------------
/chapter11/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Vipul A M
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/chapter11/README.md:
--------------------------------------------------------------------------------
1 | react-tools
2 | ===========
3 |
4 | Examples of React Tools
5 |
6 | ### Usage
7 |
8 | ```
9 | npm install
10 | npm start
11 | open http://localhost:9000
12 | npm test
13 | ```
14 |
--------------------------------------------------------------------------------
/chapter11/__tests__/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neerajsingh0101/reactjs-by-example/0fb831f9add41f51480f468cdd7fcf9318161b65/chapter11/__tests__/.keep
--------------------------------------------------------------------------------
/chapter11/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | React Router/ Data Models
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/chapter11/server.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var WebpackDevServer = require('webpack-dev-server');
3 | var config = require('./webpack.config');
4 |
5 | new WebpackDevServer(webpack(config), {
6 | publicPath: config.output.publicPath,
7 | hot: true,
8 | historyApiFallback: true
9 | }).listen(9000, 'localhost', function (err, result) {
10 | if (err) {
11 | console.log(err);
12 | }
13 |
14 | console.log('Listening at localhost:9000');
15 | });
16 |
--------------------------------------------------------------------------------
/chapter11/src/Modal.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Router, Route, IndexRoute, Link } from 'react-router'
3 |
4 | const Modal = React.createClass({
5 | styles: {
6 | position: 'fixed',
7 | top: '20%',
8 | right: '20%',
9 | bottom: '20%',
10 | left: '20%',
11 | padding: 20,
12 | boxShadow: '0px 0px 150px 130px rgba(0, 0, 0, 0.5)',
13 | overflow: 'auto',
14 | background: '#fff'
15 | },
16 |
17 | render() {
18 | return (
19 |
20 |
Back
21 | {this.props.children}
22 |
23 | )
24 | }
25 | })
26 |
27 | export {Modal as default}
28 |
--------------------------------------------------------------------------------
/chapter11/src/Picture.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { PictureModel } from './models';
3 |
4 | const Picture = React.createClass({
5 | render() {
6 | let { location } = this.props;
7 | let cat = location.state.cat;
8 | console.log(this.props);
9 | return (
10 |
11 |
12 |
})
13 |
14 |
15 |
Name: {cat.get('name')}.
16 |
Details: {cat.get('details')}
17 |
18 |
19 | )
20 | }
21 | });
22 |
23 | export {Picture as default}
24 |
--------------------------------------------------------------------------------
/chapter11/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { render } from 'react-dom'
3 | import { createHistory, useBasename } from 'history'
4 | import { Router, Route, IndexRoute, Link } from 'react-router'
5 | import Backbone from 'backbone';
6 | import Modal from './Modal'
7 | import App from './App'
8 | import Picture from './Picture'
9 | import Home from './Home'
10 |
11 | const history = useBasename(createHistory)({
12 | basename: '/pinterest'
13 | });
14 |
15 |
16 | render((
17 |
18 |
19 |
20 |
21 |
22 |
23 | ), document.getElementById('rootElement'));
24 |
--------------------------------------------------------------------------------
/chapter11/src/models.js:
--------------------------------------------------------------------------------
1 | import Backbone from 'backbone';
2 | import Faker from 'faker';
3 | import _ from 'underscore';
4 |
5 | const PictureModel = Backbone.Model.extend({
6 | defaults: {
7 | src: 'http://lorempixel.com/601/600/cats/',
8 | name: 'Pusheen',
9 | details: 'Pusheen is a Cat',
10 | faved: false
11 | }
12 | });
13 |
14 | class CatGenerator {
15 | constructor() {
16 | this.Cats = new Backbone.Collection;
17 | [600, 601, 602, 603, 604, 605].map( (height)=>{
18 | this.createCat(height, 600);
19 | })
20 | }
21 |
22 | createCat(height = _.random(600, 650), width = 600) {
23 | console.log('Adding new cat');
24 | this.Cats.add(new PictureModel({
25 | src: `http://lorempixel.com/${height}/${width}/cats/`,
26 | name: Faker.Name.findName(),
27 | details: Faker.Lorem.paragraph()
28 | }));
29 | }
30 |
31 | randRange() {
32 | return _.random(5000, 10000);
33 | }
34 |
35 | }
36 |
37 | module.exports = {PictureModel, CatGenerator};
38 |
--------------------------------------------------------------------------------
/chapter12/.gitignore:
--------------------------------------------------------------------------------
1 | /js/bundle.js
2 | /js/bundle.min.js
3 | .bundle.js
4 | ./config.js
5 |
--------------------------------------------------------------------------------
/chapter12/config.example.js:
--------------------------------------------------------------------------------
1 | module.exports ={
2 | twitter_consumer_key: '',
3 | twitter_consumer_secret: '',
4 | twitter_access_token_key: '',
5 | twitter_access_token_secret: ''
6 | }
7 |
--------------------------------------------------------------------------------
/chapter12/config.js:
--------------------------------------------------------------------------------
1 | module.exports ={
2 | twitter_consumer_key: 'hRz8HdxVaGtwBhCjzt7pTRZho',
3 | twitter_consumer_secret: 'CtPCwGuSpunUKoJO5PV80H4PBNTKBzyX1DirjgqL5MHmVXjJUw',
4 | twitter_access_token_key: '52653289-DBbudBLcfJFfBRkUnZbuGkYuLLmRqUanfdvIszrKn',
5 | twitter_access_token_secret: 'FUYuoxsM2Et8tCSJzSYQsGiH3xeWbIzgfUQ5zwQLmkOVb'
6 | }
7 |
--------------------------------------------------------------------------------
/chapter12/css/app.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2014-2015, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | *
9 | * base.css overrides
10 | */
11 |
12 | .center-text {
13 | text-align: center;
14 | }
15 |
16 | .grid {
17 | word-wrap: break-word;
18 | }
19 |
20 | .twitter {
21 | border-left: 2px solid #55ACEE;
22 | position: relative;
23 | }
24 | .twitter:before {
25 | content: "\f099";
26 | font: normal normal normal 20px/1 FontAwesome;
27 | position: absolute;
28 | bottom: 10px;
29 | right: 10px;
30 | color: #55ACEE;
31 | opacity: .5;
32 | }
33 |
34 |
35 | .reddit {
36 | border-left: 2px solid #FF4500;
37 | position: relative;
38 | }
39 | .reddit:before {
40 | content: "\f1a1";
41 | font: normal normal normal 20px/1 FontAwesome;
42 | position: absolute;
43 | bottom: 10px;
44 | right: 10px;
45 | color: #FF4500;
46 | opacity: .5;
47 | }
48 |
49 |
--------------------------------------------------------------------------------
/chapter12/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Flux/Social Media Tracker
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/chapter12/js/app.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2014, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | var React = require('react');
11 | var ReactDOM = require('react-dom');
12 | var SocialTracker = require('./components/SocialTracker.react');
13 |
14 | ReactDOM.render(
15 | ,
16 | document.getElementById('container')
17 | );
18 |
--------------------------------------------------------------------------------
/chapter12/js/components/Header.react.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2014-2015, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | var React = require('react');
11 | var ReactBootstrap = require('react-bootstrap');
12 | var Row = ReactBootstrap.Row, Jumbotron = ReactBootstrap.Jumbotron;
13 |
14 | var Header = React.createClass({
15 |
16 | render: function () {
17 | return (
18 |
19 |
20 | Social Media Tracker
21 |
22 |
23 | );
24 | }
25 |
26 | });
27 |
28 | module.exports = Header;
29 |
--------------------------------------------------------------------------------
/chapter12/js/constants/SocialConstants.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2014-2015, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | *
9 | * SocialConstants
10 | */
11 |
12 | var keyMirror = require('keymirror');
13 |
14 | module.exports = keyMirror({
15 | FILTER_BY_TWEETS: null,
16 | FILTER_BY_REDDITS: null,
17 | SYNC_TWEETS: null,
18 | SYNC_REDDITS: null
19 |
20 | });
21 |
22 |
23 |
--------------------------------------------------------------------------------
/chapter12/js/dispatcher/AppDispatcher.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2014-2015, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | *
9 | * AppDispatcher
10 | *
11 | * A singleton that operates as the central hub for application updates.
12 | */
13 |
14 | var Dispatcher = require('flux').Dispatcher;
15 |
16 | module.exports = new Dispatcher();
17 |
--------------------------------------------------------------------------------
/chapter12/js/utils/array.js:
--------------------------------------------------------------------------------
1 | var ArrayUtil = (function () {
2 | function in_groups_of(arr, n) {
3 | var ret = [];
4 | var group = [];
5 | var len = arr.length;
6 |
7 | for (var i = 0; i < len; ++i) {
8 | group.push(arr[i]);
9 | if ((i + 1) % n == 0) {
10 | ret.push(group);
11 | group = [];
12 | }
13 | }
14 |
15 | if (group.length) ret.push(group);
16 |
17 | return ret;
18 | };
19 |
20 |
21 | return {'in_groups_of': in_groups_of}
22 | }());
23 |
24 | module.exports = ArrayUtil;
25 |
--------------------------------------------------------------------------------
/chapter12/js/utils/jsonutil.js:
--------------------------------------------------------------------------------
1 | var JSONUtil = (function () {
2 | function parseJSON(response){
3 | return response.json()
4 | }
5 |
6 | function handleParseException(ex) {
7 | console.log('parsing failed', ex)
8 | }
9 |
10 |
11 | return {'parseJSON': parseJSON, 'handleParseException': handleParseException}
12 | }());
13 |
14 | module.exports = JSONUtil;
15 |
--------------------------------------------------------------------------------
/chapter12/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "reactjs-by-example-flux",
3 | "version": "0.0.1",
4 | "description": "ReactJS with Flux.",
5 | "repository": "https://github.com/bigbinary/reactjs-by-example",
6 | "main": "server.js",
7 | "dependencies": {
8 | "classnames": "^2.1.3",
9 | "express": "^4.13.3",
10 | "flux": "^2.0.1",
11 | "keymirror": "~0.1.0",
12 | "object-assign": "^1.0.0",
13 | "react": "^0.14.6",
14 | "react-bootstrap": "^0.28.2",
15 | "twitter": "^1.2.5",
16 | "underscore": "^1.8.3",
17 | "whatwg-fetch": "^0.10.1"
18 | },
19 | "devDependencies": {
20 | "browserify": "^6.2.0",
21 | "envify": "^3.0.0",
22 | "jest-cli": "^0.4.3",
23 | "reactify": "^0.15.2",
24 | "uglify-js": "~2.4.15",
25 | "watchify": "^2.1.1"
26 | },
27 | "scripts": {
28 | "start": "npm run watch & node server.js",
29 | "watch": "watchify -o js/bundle.js -v -d js/app.js",
30 | "build": "browserify . -t [envify --NODE_ENV production] | uglifyjs -cm > js/bundle.min.js",
31 | "test": "jest"
32 | },
33 | "author": ["Bill Fisher", "Vipul A M"],
34 | "browserify": {
35 | "transform": [
36 | "reactify",
37 | "envify"
38 | ]
39 | },
40 | "jest": {
41 | "rootDir": "./js"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/chapter12/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neerajsingh0101/reactjs-by-example/0fb831f9add41f51480f468cdd7fcf9318161b65/chapter12/screenshot.png
--------------------------------------------------------------------------------
/chapter12/server.js:
--------------------------------------------------------------------------------
1 | var Twitter = require('twitter');
2 | var config = require('./config');
3 |
4 | var client = new Twitter({
5 | consumer_key: config.twitter_consumer_key,
6 | consumer_secret: config.twitter_consumer_secret,
7 | access_token_key: config.twitter_access_token_key,
8 | access_token_secret: config.twitter_access_token_secret
9 | });
10 |
11 | var express= require('express');
12 | var app = new (require('express'))();
13 | var port = 3000
14 |
15 | app.get('/tweets.json', function (req, res) {
16 | console.log(req.query.username);
17 | var params = {screen_name: req.query.username};
18 | client.get('statuses/user_timeline', params, function (error, tweets, response) {
19 | console.log(error);
20 | if (!error) {
21 | res.json(tweets);
22 | } else {
23 | res.json({error: error});
24 | }
25 | });
26 | });
27 |
28 | app.use(express.static(__dirname));
29 |
30 | app.get("/", function (req, res) {
31 | res.sendFile(__dirname + '/index.html')
32 | });
33 |
34 | app.listen(port, function (error) {
35 | if (error) {
36 | console.error(error)
37 | } else {
38 | console.info("==> 🌎 Listening on port %s. Open up http://localhost:%s/ in your browser.", port, port)
39 | }
40 | });
41 |
--------------------------------------------------------------------------------
/chapter13/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "stage": 0,
3 | "env": {
4 | "development": {
5 | "plugins": [
6 | "react-transform"
7 | ],
8 | "extra": {
9 | "react-transform": {
10 | "transforms": [{
11 | "transform": "react-transform-hmr",
12 | "imports": ["react"],
13 | "locals": ["module"]
14 | }]
15 | }
16 | }
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/chapter13/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | .DS_Store
4 | config.js
5 |
--------------------------------------------------------------------------------
/chapter13/README.md:
--------------------------------------------------------------------------------
1 | react-flux
2 | ===========
3 |
4 | Example of Flux, using redux
5 |
6 | ### Usage
7 |
8 | ```
9 | cp config.example.js config.js # Add App credentials
10 | npm install
11 | npm start
12 | open http://localhost:3000
13 | ``
14 |
--------------------------------------------------------------------------------
/chapter13/config.example.js:
--------------------------------------------------------------------------------
1 | module.exports ={
2 | twitter_consumer_key: '',
3 | twitter_consumer_secret: '',
4 | twitter_access_token_key: '',
5 | twitter_access_token_secret: ''
6 | }
7 |
--------------------------------------------------------------------------------
/chapter13/containers/App.js:
--------------------------------------------------------------------------------
1 | import { bindActionCreators } from 'redux'
2 | import { connect } from 'react-redux'
3 | import SocialTracker from '../components/SocialTracker'
4 | import * as SocialActions from '../actions/social'
5 |
6 | function mapStateToProps(state) {
7 | return {
8 | social: state.social
9 | }
10 | }
11 |
12 | function mapDispatchToProps(dispatch) {
13 | return bindActionCreators(SocialActions, dispatch)
14 | }
15 |
16 | export default connect(mapStateToProps, mapDispatchToProps)(SocialTracker)
17 |
--------------------------------------------------------------------------------
/chapter13/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Redux
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/chapter13/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { render } from 'react-dom'
3 | import { Provider } from 'react-redux'
4 | import App from './containers/App'
5 | import configureStore from './store/configureStore'
6 |
7 | const store = configureStore()
8 |
9 | render(
10 |
11 |
12 | ,
13 | document.getElementById('root')
14 | )
15 |
--------------------------------------------------------------------------------
/chapter13/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux'
2 | import social from './social'
3 |
4 | const rootReducer = combineReducers({
5 | social
6 | })
7 |
8 | export default rootReducer
9 |
--------------------------------------------------------------------------------
/chapter13/store/configureStore.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware } from 'redux'
2 | import thunk from 'redux-thunk'
3 | import reducer from '../reducers'
4 |
5 | const createStoreWithMiddleware = applyMiddleware(
6 | thunk
7 | )(createStore)
8 |
9 | export default function configureStore(initialState) {
10 | const store = createStoreWithMiddleware(reducer, initialState)
11 |
12 | if (module.hot) {
13 | // Enable Webpack hot module replacement for reducers
14 | module.hot.accept('../reducers', () => {
15 | const nextReducer = require('../reducers')
16 | store.replaceReducer(nextReducer)
17 | })
18 | }
19 |
20 | return store
21 | }
22 |
--------------------------------------------------------------------------------
/chapter13/styles/App.css:
--------------------------------------------------------------------------------
1 | .center-text {
2 | text-align: center;
3 | }
4 |
5 | .grid {
6 | word-wrap: break-word;
7 | }
8 |
9 | .twitter {
10 | border-left: 2px solid #55ACEE;
11 | position: relative;
12 | }
13 | .twitter:before {
14 | content: "\f099";
15 | font: normal normal normal 20px/1 FontAwesome;
16 | position: absolute;
17 | bottom: 10px;
18 | right: 10px;
19 | color: #55ACEE;
20 | opacity: .5;
21 | }
22 |
23 |
24 | .reddit {
25 | border-left: 2px solid #FF4500;
26 | position: relative;
27 | }
28 | .reddit:before {
29 | content: "\f1a1";
30 | font: normal normal normal 20px/1 FontAwesome;
31 | position: absolute;
32 | bottom: 10px;
33 | right: 10px;
34 | color: #FF4500;
35 | opacity: .5;
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/chapter13/test/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "mocha": true
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/chapter13/test/reducers/counter.spec.js:
--------------------------------------------------------------------------------
1 | import expect from 'expect'
2 | import counter from '../../reducers/counter'
3 | import { INCREMENT_COUNTER, DECREMENT_COUNTER } from '../../actions/counter'
4 |
5 | describe('reducers', () => {
6 | describe('counter', () => {
7 | it('should handle initial state', () => {
8 | expect(counter(undefined, {})).toBe(0)
9 | })
10 |
11 | it('should handle INCREMENT_COUNTER', () => {
12 | expect(counter(1, { type: INCREMENT_COUNTER })).toBe(2)
13 | })
14 |
15 | it('should handle DECREMENT_COUNTER', () => {
16 | expect(counter(1, { type: DECREMENT_COUNTER })).toBe(0)
17 | })
18 |
19 | it('should handle unknown action type', () => {
20 | expect(counter(1, { type: 'unknown' })).toBe(1)
21 | })
22 | })
23 | })
24 |
--------------------------------------------------------------------------------
/chapter13/test/setup.js:
--------------------------------------------------------------------------------
1 | import { jsdom } from 'jsdom'
2 |
3 | global.document = jsdom('')
4 | global.window = document.defaultView
5 | global.navigator = global.window.navigator
6 |
--------------------------------------------------------------------------------
/chapter13/utils/array.js:
--------------------------------------------------------------------------------
1 | class ArrayUtil {
2 | static in_groups_of(arr, n) {
3 | var ret = [];
4 | var group = [];
5 | var len = arr.length;
6 |
7 | for (var i = 0; i < len; ++i) {
8 | group.push(arr[i]);
9 | if ((i + 1) % n == 0) {
10 | ret.push(group);
11 | group = [];
12 | }
13 | }
14 |
15 | if (group.length) ret.push(group);
16 |
17 | return ret;
18 | };
19 |
20 | }
21 |
22 | export {ArrayUtil as default};
23 |
--------------------------------------------------------------------------------
/chapter13/utils/jsonutil.js:
--------------------------------------------------------------------------------
1 | class JSONUtil{
2 | static parseJSON(response){
3 | return response.json()
4 | }
5 |
6 | static handleParseException(ex) {
7 | console.log('parsing failed', ex)
8 | }
9 | }
10 |
11 | export { JSONUtil as default }
12 |
--------------------------------------------------------------------------------
/chapter2/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | JSX in Detail
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/chapter2/src/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | var App = React.createClass({
4 | render: function(){
5 | return(
6 |
7 |
8 | );
9 | }
10 | });
11 |
12 | var RecentChangesTable = React.createClass({
13 | render: function() {
14 | return
15 | {this.props.children}
16 |
;
17 | }
18 | });
19 |
20 | RecentChangesTable.Headings = React.createClass({
21 | render: function() {
22 | var headings = this.props.headings.map(function(name, index) {
23 | return();
24 | });
25 |
26 | return (
27 |
28 | {headings}
29 |
30 | );
31 | }
32 | });
33 |
34 | module.exports = App;
35 |
--------------------------------------------------------------------------------
/chapter2/src/index.js:
--------------------------------------------------------------------------------
1 | import ReactDOM from 'react-dom';
2 | import React from 'react';
3 | import App from './App';
4 |
5 | var data = [{ "when": "2 minutes ago",
6 | "who": "Jilaal Dupre",
7 | "description": "Created new account"
8 | },
9 | {
10 | "when": "1 hour ago",
11 | "who": "Losaae White",
12 | "description": "Added fist chapter"
13 | }];
14 | var headings = ['When', 'Who', 'Description'];
15 |
16 |
17 |
18 | ReactDOM.render(,
20 | document.getElementById('container'));
21 |
--------------------------------------------------------------------------------
/chapter4/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "stage": 0
3 | }
4 |
--------------------------------------------------------------------------------
/chapter4/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "ecmaFeatures": {
3 | "jsx": true,
4 | "modules": true
5 | },
6 | "env": {
7 | "browser": true,
8 | "node": true
9 | },
10 | "parser": "babel-eslint",
11 | "rules": {
12 | "quotes": [2, "single"],
13 | "strict": [2, "never"],
14 | "react/jsx-uses-react": 2,
15 | "react/jsx-uses-vars": 2,
16 | "react/react-in-jsx-scope": 2
17 | },
18 | "plugins": [
19 | "react"
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/chapter4/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/chapter4/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "browser": true,
4 | "esnext": true,
5 | "newcap": false
6 | }
7 |
--------------------------------------------------------------------------------
/chapter4/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Vipul A M
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/chapter4/README.md:
--------------------------------------------------------------------------------
1 | react-forms
2 | ===========
3 |
4 | Examples of Forms in ReactJS
5 |
6 | ### Usage
7 |
8 | ```
9 | npm install
10 | npm start
11 | open http://localhost:9000
12 | ```
13 |
14 |
--------------------------------------------------------------------------------
/chapter4/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Forms in React
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/chapter4/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "reactjs-by-example-react-forms",
3 | "version": "0.0.1",
4 | "description": "ReactJS forms example",
5 | "scripts": {
6 | "start": "node server.js",
7 | "lint": "eslint src"
8 | },
9 | "author": "Vipul A M (http://github.com/vipulnsward)",
10 | "license": "MIT",
11 | "homepage": "https://github.com/bigbinary/reactjs-by-example",
12 | "devDependencies": {
13 | "babel-core": "^5.4.7",
14 | "babel-eslint": "^3.1.9",
15 | "babel-loader": "^5.1.2",
16 | "eslint-plugin-react": "^2.3.0",
17 | "react-hot-loader": "^1.2.7",
18 | "webpack": "^1.9.6",
19 | "webpack-dev-server": "^1.8.2"
20 | },
21 | "dependencies": {
22 | "react": "^0.13.0"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/chapter4/server.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var WebpackDevServer = require('webpack-dev-server');
3 | var config = require('./webpack.config');
4 |
5 | new WebpackDevServer(webpack(config), {
6 | publicPath: config.output.publicPath,
7 | hot: true,
8 | historyApiFallback: true
9 | }).listen(9000, 'localhost', function (err, result) {
10 | if (err) {
11 | console.log(err);
12 | }
13 |
14 | console.log('Listening at localhost:9000');
15 | });
16 |
--------------------------------------------------------------------------------
/chapter4/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import BookStore from './BookStore';
3 |
4 | React.render(, document.getElementById('root'));
5 |
--------------------------------------------------------------------------------
/chapter4/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var webpack = require('webpack');
3 |
4 | module.exports = {
5 | devtool: 'eval',
6 | entry: [
7 | 'webpack-dev-server/client?http://localhost:9000',
8 | 'webpack/hot/only-dev-server',
9 | './src/index'
10 | ],
11 | output: {
12 | path: path.join(__dirname, 'dist'),
13 | filename: 'bundle.js',
14 | publicPath: '/static/'
15 | },
16 | plugins: [
17 | new webpack.HotModuleReplacementPlugin(),
18 | new webpack.NoErrorsPlugin()
19 | ],
20 | resolve: {
21 | extensions: ['', '.js', '.jsx']
22 | },
23 | module: {
24 | loaders: [{
25 | test: /\.jsx?$/,
26 | loaders: ['react-hot', 'babel'],
27 | include: path.join(__dirname, 'src')
28 | }]
29 | }
30 | };
31 |
--------------------------------------------------------------------------------
/chapter5/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "stage": 0
3 | }
4 |
--------------------------------------------------------------------------------
/chapter5/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "ecmaFeatures": {
3 | "jsx": true,
4 | "modules": true
5 | },
6 | "env": {
7 | "browser": true,
8 | "node": true
9 | },
10 | "parser": "babel-eslint",
11 | "rules": {
12 | "quotes": [2, "single"],
13 | "strict": [2, "never"],
14 | "react/jsx-uses-react": 2,
15 | "react/jsx-uses-vars": 2,
16 | "react/react-in-jsx-scope": 2
17 | },
18 | "plugins": [
19 | "react"
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/chapter5/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/chapter5/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "browser": true,
4 | "esnext": true,
5 | "newcap": false
6 | }
7 |
--------------------------------------------------------------------------------
/chapter5/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Vipul A M
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/chapter5/README.md:
--------------------------------------------------------------------------------
1 | react-forms
2 | ===========
3 |
4 | Examples of Forms in ReactJS
5 |
6 | ### Usage
7 |
8 | ```
9 | npm install
10 | npm start
11 | open http://localhost:9000
12 | ```
13 |
14 |
--------------------------------------------------------------------------------
/chapter5/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | React Forms
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/chapter5/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "reactjs-by-example-react-forms",
3 | "version": "0.0.1",
4 | "description": "ReactJS forms example",
5 | "scripts": {
6 | "start": "node server.js",
7 | "lint": "eslint src"
8 | },
9 | "author": "Vipul A M (http://github.com/vipulnsward)",
10 | "license": "MIT",
11 | "homepage": "https://github.com/bigbinary/reactjs-by-example",
12 | "devDependencies": {
13 | "babel-core": "^5.4.7",
14 | "babel-eslint": "^3.1.9",
15 | "babel-loader": "^5.1.2",
16 | "css-loader": "^0.15.5",
17 | "eslint-plugin-react": "^2.3.0",
18 | "file-loader": "^0.8.4",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.8.2"
23 | },
24 | "dependencies": {
25 | "bootstrap": "^3.3.5",
26 | "bootstrap-webpack": "0.0.3",
27 | "file-loader": "^0.8.4",
28 | "object-assign": "^4.0.1",
29 | "react": "^0.13.3",
30 | "url-loader": "^0.5.6"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/chapter5/server.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var WebpackDevServer = require('webpack-dev-server');
3 | var config = require('./webpack.config');
4 |
5 | new WebpackDevServer(webpack(config), {
6 | publicPath: config.output.publicPath,
7 | hot: true,
8 | historyApiFallback: true
9 | }).listen(9000, 'localhost', function (err, result) {
10 | if (err) {
11 | console.log(err);
12 | }
13 |
14 | console.log('Listening at localhost:9000');
15 | });
16 |
--------------------------------------------------------------------------------
/chapter5/src/confirmation.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | var Confirmation = React.createClass({
4 | handleSubmit(event) {
5 | event.preventDefault();
6 | console.log("handleSubmit");
7 | this.props.updateFormData(this.props.data);
8 | },
9 |
10 | render() {
11 | return (
12 |
13 |
Are you sure you want to submit the data?
14 |
31 |
32 | );
33 | }
34 | });
35 |
36 | module.exports = Confirmation;
37 |
--------------------------------------------------------------------------------
/chapter5/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import App from './App';
3 |
4 | React.render(, document.getElementById('rootElement'));
5 |
--------------------------------------------------------------------------------
/chapter5/src/mixins/cart_timeout_mixin.js:
--------------------------------------------------------------------------------
1 | var CartTimeoutMixin = {
2 | componentWillMount: function () {
3 | this.setInterval(this.decrementCartTimer, 1000);
4 | },
5 |
6 | decrementCartTimer(){
7 | if (this.state.cartTimeout == 0) {
8 | this.props.alertCartTimeout();
9 | return;
10 | }
11 | this.setState({cartTimeout: this.state.cartTimeout - 1});
12 | },
13 |
14 | componentWillUnmount(){
15 | this.props.updateCartTimeout(this.state.cartTimeout);
16 | }
17 |
18 | };
19 |
20 |
21 | module.exports = CartTimeoutMixin;
22 |
--------------------------------------------------------------------------------
/chapter5/src/mixins/set_interval_mixin.js:
--------------------------------------------------------------------------------
1 | var SetIntervalMixin = {
2 | componentWillMount: function() {
3 | this.intervals = [];
4 | },
5 | setInterval: function() {
6 | this.intervals.push(setInterval.apply(null, arguments));
7 | },
8 | componentWillUnmount: function() {
9 | this.intervals.map(clearInterval);
10 | }
11 | };
12 |
13 |
14 | module.exports = SetIntervalMixin;
15 |
--------------------------------------------------------------------------------
/chapter5/src/modals/modal_alert_timeout.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 |
4 | var ModalAlertTimeout = React.createClass({
5 | componentDidMount(){
6 | setTimeout(()=> {
7 | let timeoutModal = this.refs.timeoutModal.getDOMNode();
8 | $(timeoutModal).modal('show');
9 | $(timeoutModal).on('hidden.bs.modal', this.unMountComponent);
10 | }, 100);
11 | },
12 |
13 |
14 | unMountComponent () {
15 | React.unmountComponentAtNode(this.getDOMNode().parentNode);
16 | },
17 |
18 | render() {
19 | return (
20 |
21 |
22 |
23 |
24 |
25 |
27 |
Timeout
28 |
29 |
30 |
The cart has timed-out. Please try again!
31 |
32 |
33 |
34 |
35 | );
36 | }
37 | });
38 | module.exports = ModalAlertTimeout;
39 |
--------------------------------------------------------------------------------
/chapter5/src/success.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | var Success = React.createClass({
4 | render() {
5 | var numberOfDays = "1 to 2 ";
6 |
7 | if (this.props.data.deliveryOption === 'Normal') {
8 | numberOfDays = "3 to 4 ";
9 | }
10 | return (
11 |
12 |
13 | Thank you for shopping with us {this.props.data.fullName}.
14 |
15 |
16 | You will soon get {this.props.data.selectedBooks.join(", ")} at {this.props.data.shippingAddress} in approrximately {numberOfDays} days.
17 |
18 |
19 | );
20 | }
21 | });
22 |
23 | module.exports = Success;
24 |
--------------------------------------------------------------------------------
/chapter6-iso/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "stage": 0
3 | }
4 |
--------------------------------------------------------------------------------
/chapter6-iso/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 |
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 |
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 |
19 | # node-waf configuration
20 | .lock-wscript
21 |
22 | # Compiled binary addons (http://nodejs.org/api/addons.html)
23 | build/Release
24 |
25 | # Dependency directory
26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
27 | node_modules
28 | dist
29 |
--------------------------------------------------------------------------------
/chapter6-iso/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "esnext": true,
3 | "node": true,
4 | "browser": true,
5 | "bitwise": true,
6 | "camelcase": false,
7 | "curly": true,
8 | "eqeqeq": true,
9 | "immed": true,
10 | "indent": 2,
11 | "latedef": true,
12 | "newcap": true,
13 | "noarg": true,
14 | "quotmark": "single",
15 | "undef": true,
16 | "unused": true,
17 | "trailing": true,
18 | "smarttabs": true,
19 | "newcap": false,
20 | "globals": {
21 | "jest": false,
22 | "describe": false,
23 | "it": false,
24 | "expect": false
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/chapter6-iso/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Vipul A M, RisingStack
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/chapter6-iso/README.md:
--------------------------------------------------------------------------------
1 | react-isomorphic
2 | ===========
3 |
4 | ## How to start
5 |
6 | Run:
7 | ```
8 | npm install
9 | npm start
10 | ```
11 |
12 | Check your http://localhost:3000/ or `open http://localhost:3000/`
13 |
14 | ## How to start code
15 |
16 | Run:
17 | `npm run webpack-watch`
18 |
--------------------------------------------------------------------------------
/chapter6-iso/config/app.js:
--------------------------------------------------------------------------------
1 | var config = {};
2 |
3 | config.title = 'Isomorphic App';
4 |
5 | module.exports = config;
6 |
--------------------------------------------------------------------------------
/chapter6-iso/src/app/__tests__/app.spec.js:
--------------------------------------------------------------------------------
1 | jest.dontMock('../app');
2 |
3 | var App = require('../app');
4 | var state = {
5 | cart: {
6 | title: 'title',
7 | items: []
8 | }
9 | };
10 |
11 | describe('App', function () {
12 | it('renders to string', function () {
13 | var app = new App({ state: state });
14 |
15 | expect(typeof app.renderToString()).toBe('string');
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/chapter6-iso/src/app/app.js:
--------------------------------------------------------------------------------
1 | import React from 'react/addons';
2 |
3 | import AppRoot from './components/AppRoot';
4 |
5 |
6 | class App {
7 |
8 | constructor(options) {
9 |
10 | this.state = options.state;
11 | }
12 |
13 | render(element) {
14 |
15 |
16 | // would be in JSX:
17 | var appRootElement = ;
18 |
19 | // render to DOM
20 | if (element) {
21 | React.render(appRootElement, element);
22 | return;
23 | }
24 |
25 | // render to string
26 | return React.renderToString(appRootElement);
27 | }
28 |
29 | renderToDOM(element) {
30 | if (!element) {
31 | new Error('App.renderToDOM: element is required');
32 | }
33 |
34 | this.render(element);
35 | }
36 |
37 | renderToString() {
38 | return this.render();
39 | }
40 | }
41 |
42 | export default App;
43 |
--------------------------------------------------------------------------------
/chapter6-iso/src/app/components/AppRoot.js:
--------------------------------------------------------------------------------
1 | require("jquery");
2 | import React from 'react/addons';
3 | import SearchPage from './SearchPage'
4 | import config from '../../../config/app';
5 |
6 | var AppRoot = React.createClass({
7 | propTypes: {
8 | state: React.PropTypes.object.isRequired // We can use state as needed ahead to initialize the App.
9 | },
10 | render()
11 | {
12 | return ;
13 | }
14 | })
15 | ;
16 |
17 | export default AppRoot;
18 |
--------------------------------------------------------------------------------
/chapter6-iso/src/app/components/__tests__/AppRoot.spec.js:
--------------------------------------------------------------------------------
1 | jest.dontMock('../AppRoot');
2 |
3 | import React from 'react/addons';
4 | import AppRoot from '../AppRoot';
5 | import Cart from '../Cart';
6 |
7 | var TestUtils = React.addons.TestUtils;
8 | var state = {
9 | cart: {
10 | title: 'My Cart',
11 | items: [
12 | {
13 | title: 'Item 1',
14 | price: 12
15 | },
16 | {
17 | title: 'Item 2',
18 | price: 21
19 | },
20 | {
21 | title: 'Item 3',
22 | price: 33
23 | }
24 | ]
25 | }
26 | };
27 |
28 | describe('AppRoot', () => {
29 |
30 | it('renders properly', () => {
31 | var appRoot = TestUtils.renderIntoDocument(
32 |
33 | );
34 |
35 | var title = TestUtils.findRenderedDOMComponentWithTag(appRoot, 'h1');
36 | var carts = TestUtils.scryRenderedComponentsWithType(appRoot, Cart);
37 |
38 | expect(title.getDOMNode().textContent).toEqual('My React App');
39 | expect(carts.length).toBe(1);
40 | expect(carts[0].props).toEqual({
41 | cart: state.cart
42 | });
43 | });
44 | });
45 |
--------------------------------------------------------------------------------
/chapter6-iso/src/app/components/__tests__/Cart.spec.js:
--------------------------------------------------------------------------------
1 | jest.dontMock('../Cart');
2 |
3 | import React from 'react/addons';
4 | import Cart from '../Cart';
5 | import Item from '../Item';
6 |
7 | var TestUtils = React.addons.TestUtils;
8 | var cartProp = {
9 | title: 'My Cart',
10 | items: [
11 | {
12 | title: 'Item 1',
13 | price: 12
14 | },
15 | {
16 | title: 'Item 2',
17 | price: 21
18 | },
19 | {
20 | title: 'Item 3',
21 | price: 33
22 | }
23 | ]
24 | };
25 |
26 | describe('Cart', () => {
27 |
28 | it('renders properly', () => {
29 | var cart = TestUtils.renderIntoDocument(
30 |
31 | );
32 |
33 | var title = TestUtils.findRenderedDOMComponentWithTag(cart, 'h2');
34 | var items = TestUtils.scryRenderedComponentsWithType(cart, Item);
35 |
36 | expect(title.getDOMNode().textContent).toEqual('My Cart');
37 | expect(items.length).toBe(3);
38 | expect(items[0].props).toEqual({
39 | item: cartProp.items[0]
40 | });
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/chapter6-iso/src/app/components/__tests__/Item.spec.js:
--------------------------------------------------------------------------------
1 | jest.dontMock('../Item');
2 |
3 | import React from 'react/addons';
4 | import Item from '../Item';
5 |
6 | var TestUtils = React.addons.TestUtils;
7 | var itemProp = {
8 | title: 'Item 1',
9 | price: 12
10 | };
11 |
12 | describe('Item', () => {
13 |
14 | it('renders properly', () => {
15 | var item = TestUtils.renderIntoDocument(
16 |
17 | );
18 |
19 | var li = TestUtils.findRenderedDOMComponentWithTag(item, 'li');
20 |
21 | expect(li.getDOMNode().textContent).toEqual('Item 1 - $12');
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/chapter6-iso/src/app/index.js:
--------------------------------------------------------------------------------
1 | import App from './app';
2 | export default App;
3 |
--------------------------------------------------------------------------------
/chapter6-iso/src/client/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Search
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | <%- reactOutput %>
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/chapter6-iso/src/client/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Search
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/chapter6-iso/src/client/scripts/client.js:
--------------------------------------------------------------------------------
1 | import App from '../../app';
2 |
3 | var attachElement = document.getElementById('app');
4 |
5 | var state = {};
6 |
7 | var app;
8 |
9 |
10 | // Create new app and attach to element
11 | app = new App({
12 | state: state
13 | });
14 |
15 | app.renderToDOM(attachElement);
16 |
--------------------------------------------------------------------------------
/chapter6-iso/src/client/styles/main.css:
--------------------------------------------------------------------------------
1 |
2 | .appRoot {
3 | border: 2px solid blue;
4 | padding: 10px;
5 | }
6 |
7 | .cart {
8 | border: 2px solid red;
9 | padding: 10px;
10 | }
11 | .item {
12 | border: 2px solid green;
13 | padding: 10px;
14 | }
15 |
16 | ul {
17 | list-style: none;
18 | padding: 0;
19 | }
20 |
21 | li {
22 | margin: 5px 0 5px 0;
23 | }
24 |
--------------------------------------------------------------------------------
/chapter6-iso/src/server/index.js:
--------------------------------------------------------------------------------
1 | require('babel/register');
2 |
3 | module.exports = require('./server');
4 |
--------------------------------------------------------------------------------
/chapter6-iso/src/server/server.js:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import Express from 'express';
3 |
4 | import AppRoot from '../app/components/AppRoot'
5 | import React from 'react/addons';
6 |
7 | var app = Express();
8 | var server;
9 |
10 | const PATH_STYLES = path.resolve(__dirname, '../client/styles');
11 | const PATH_DIST = path.resolve(__dirname, '../../dist');
12 |
13 | app.use('/styles', Express.static(PATH_STYLES));
14 | app.use(Express.static(PATH_DIST));
15 |
16 | app.get('/', (req, res) => {
17 | var reactAppContent = React.renderToString();
18 | console.log(reactAppContent);
19 | res.render(path.resolve(__dirname, '../client/index.ejs'), {reactOutput: reactAppContent});
20 | });
21 |
22 | server = app.listen(process.env.PORT || 3000, () => {
23 | var port = server.address().port;
24 |
25 | console.log('Server is listening at %s', port);
26 | });
27 |
--------------------------------------------------------------------------------
/chapter6-iso/tools/preprocessor.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var babel = require('babel-core');
4 |
5 | module.exports = {
6 | process: function(src, filename) {
7 | // Ignore files other than .js, .es, .jsx or .es6
8 | if (!babel.canCompile(filename)) {
9 | return '';
10 | }
11 | // Ignore all files within node_modules
12 | if (filename.indexOf('node_modules') === -1) {
13 | return babel.transform(src, {filename: filename}).code;
14 | }
15 | return src;
16 | }
17 | };
18 |
--------------------------------------------------------------------------------
/chapter6-iso/webpack.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var webpack = require('webpack');
3 |
4 |
5 |
6 | module.exports = {
7 | entry: [path.resolve(__dirname, './src/client/scripts/client.js')],
8 | output: {
9 | path: path.resolve(__dirname, './dist'),
10 | filename: 'bundle.js'
11 | },
12 | resolve: {
13 | extensions: ['', '.js', '.jsx']
14 | },
15 | plugins: [
16 | new webpack.ProvidePlugin({
17 | $: "jquery",
18 | jQuery: "jquery"
19 | }),
20 | new webpack.NoErrorsPlugin()
21 | ],
22 | module: {
23 | loaders: [
24 | {test: /src\/.+.js$/, exclude: /node_modules/, loader: 'babel', include: path.join(__dirname, 'src')},
25 | {test: /\.css$/, loader: "style-loader!css-loader"},
26 | {test: /\.woff(\d+)?$/, loader: 'url?prefix=font/&limit=5000&mimetype=application/font-woff'},
27 | {test: /\.ttf$/, loader: 'file?prefix=font/'},
28 | {test: /\.eot$/, loader: 'file?prefix=font/'},
29 | {test: /\.svg$/, loader: 'file?prefix=font/'},
30 | {test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&minetype=application/font-woff"},
31 | {test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader"}
32 | ]
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/chapter6-rails/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 | #
3 | # If you find yourself ignoring temporary files generated by your text editor
4 | # or operating system, you probably want to add a global ignore instead:
5 | # git config --global core.excludesfile '~/.gitignore_global'
6 |
7 | # Ignore bundler config.
8 | /.bundle
9 |
10 | # Ignore the default SQLite database.
11 | /db/*.sqlite3
12 | /db/*.sqlite3-journal
13 |
14 | # Ignore database.yml file
15 | /config/database.yml
16 |
17 | # Ignore all logfiles and tempfiles.
18 | /log/*.log
19 | /tmp
20 | /db/backups
21 | public/uploads
22 | .idea
23 | *.DS_Store
24 | coverage
25 | .*swp
26 | /uploads/*
27 |
--------------------------------------------------------------------------------
/chapter6-rails/.ruby-version:
--------------------------------------------------------------------------------
1 | 2.2.2
2 |
--------------------------------------------------------------------------------
/chapter6-rails/Procfile:
--------------------------------------------------------------------------------
1 | web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
2 | worker: bundle exec rake jobs:work
3 |
--------------------------------------------------------------------------------
/chapter6-rails/Rakefile:
--------------------------------------------------------------------------------
1 | # Add your own tasks in files placed in lib/tasks ending in .rake,
2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3 |
4 | require File.expand_path('../config/application', __FILE__)
5 |
6 | Search::Application.load_tasks
7 |
--------------------------------------------------------------------------------
/chapter6-rails/app/admin/dashboard.rb:
--------------------------------------------------------------------------------
1 | ActiveAdmin.register_page "Dashboard" do
2 |
3 | menu priority: 1, label: proc { I18n.t("active_admin.dashboard") }
4 |
5 | content :title => proc { I18n.t("active_admin.dashboard") } do
6 | div :class => "blank_slate_container", :id => "dashboard_default_message" do
7 | span :class => "blank_slate" do
8 | span I18n.t("active_admin.dashboard_welcome.welcome")
9 | small I18n.t("active_admin.dashboard_welcome.call_to_action")
10 | end
11 | end
12 |
13 | # Here is an example of a simple dashboard with columns and panels.
14 | #
15 | # columns do
16 | # column do
17 | # panel "Recent Posts" do
18 | # ul do
19 | # Post.recent(5).map do |post|
20 | # li link_to(post.title, admin_post_path(post))
21 | # end
22 | # end
23 | # end
24 | # end
25 |
26 | # column do
27 | # panel "Info" do
28 | # para "Welcome to ActiveAdmin."
29 | # end
30 | # end
31 | # end
32 | end # content
33 | end
34 |
--------------------------------------------------------------------------------
/chapter6-rails/app/admin/user.rb:
--------------------------------------------------------------------------------
1 | ActiveAdmin.register User do
2 |
3 | permit_params :email, :password, :password_confirmation
4 |
5 | index do
6 | column :email
7 | column :current_sign_in_at
8 | column :last_sign_in_at
9 | column :sign_in_count
10 | end
11 |
12 | filter :email
13 |
14 | form do |f|
15 | f.inputs "Admin Details" do
16 | f.input :email
17 | f.input :password
18 | f.input :password_confirmation
19 | end
20 | f.actions
21 | end
22 |
23 | end
24 |
--------------------------------------------------------------------------------
/chapter6-rails/app/assets/javascripts/application_common.js:
--------------------------------------------------------------------------------
1 | //= require jquery
2 | //= require jquery_ujs
3 | //= require bootstrap-sprockets
4 | //
5 | //= require_tree ./common
6 |
--------------------------------------------------------------------------------
/chapter6-rails/app/assets/javascripts/application_desktop.js:
--------------------------------------------------------------------------------
1 | //= require react
2 | //= require react_ujs
3 | //= require components
4 |
5 | //= require ./application_common
6 | //= require_tree ./desktop
7 |
--------------------------------------------------------------------------------
/chapter6-rails/app/assets/javascripts/application_phone.js:
--------------------------------------------------------------------------------
1 | //= require ./application_common
2 | //= require_tree ./phone
3 |
--------------------------------------------------------------------------------
/chapter6-rails/app/assets/javascripts/common/active_admin.js:
--------------------------------------------------------------------------------
1 | #= require active_admin/base
2 |
--------------------------------------------------------------------------------
/chapter6-rails/app/assets/javascripts/common/bootstrap.js:
--------------------------------------------------------------------------------
1 | $(function() {
2 |
3 | $("a[rel~=popover], .has-popover").popover();
4 |
5 | return $("a[rel~=tooltip], .has-tooltip").tooltip();
6 |
7 | });
8 |
--------------------------------------------------------------------------------
/chapter6-rails/app/assets/javascripts/components.js:
--------------------------------------------------------------------------------
1 | //= require_tree ./components
2 |
--------------------------------------------------------------------------------
/chapter6-rails/app/assets/javascripts/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neerajsingh0101/reactjs-by-example/0fb831f9add41f51480f468cdd7fcf9318161b65/chapter6-rails/app/assets/javascripts/components/.gitkeep
--------------------------------------------------------------------------------
/chapter6-rails/app/assets/javascripts/desktop/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neerajsingh0101/reactjs-by-example/0fb831f9add41f51480f468cdd7fcf9318161b65/chapter6-rails/app/assets/javascripts/desktop/.gitkeep
--------------------------------------------------------------------------------
/chapter6-rails/app/assets/javascripts/phone/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neerajsingh0101/reactjs-by-example/0fb831f9add41f51480f468cdd7fcf9318161b65/chapter6-rails/app/assets/javascripts/phone/.gitkeep
--------------------------------------------------------------------------------
/chapter6-rails/app/assets/stylesheets/application_common.scss:
--------------------------------------------------------------------------------
1 | @import "bootstrap-sprockets";
2 | @import "bootstrap/custom";
3 |
4 | @import "common/base";
5 | @import "common/alerts";
6 |
7 | @import "font-awesome-sprockets";
8 | @import "font-awesome";
9 |
10 | @import "bootstrap/devise_forms";
11 | @import "environment/ribbon";
12 |
--------------------------------------------------------------------------------
/chapter6-rails/app/assets/stylesheets/application_desktop.scss:
--------------------------------------------------------------------------------
1 | /*
2 | *= require ./application_common
3 | *= require_tree ./desktop
4 | */
5 |
--------------------------------------------------------------------------------
/chapter6-rails/app/assets/stylesheets/application_phone.scss:
--------------------------------------------------------------------------------
1 | /*
2 | *= require ./application_common
3 | *= require_tree ./phone
4 | */
5 |
--------------------------------------------------------------------------------
/chapter6-rails/app/assets/stylesheets/common/active_admin.scss:
--------------------------------------------------------------------------------
1 | // SASS variable overrides must be declared before loading up Active Admin's styles.
2 | //
3 | // To view the variables that Active Admin provides, take a look at
4 | // `app/assets/stylesheets/active_admin/mixins/_variables.css.scss` in the
5 | // Active Admin source.
6 | //
7 | // For example, to change the sidebar width:
8 | // $sidebar-width: 242px;
9 |
10 | // Active Admin's got SASS!
11 | @import "active_admin/mixins";
12 | @import "active_admin/base";
13 |
14 |
15 | // Overriding any non-variable SASS must be done after the fact.
16 | // For example, to change the default status-tag color:
17 | //
18 | // .status_tag { background: #6090DB; }
19 |
--------------------------------------------------------------------------------
/chapter6-rails/app/assets/stylesheets/common/alerts.scss:
--------------------------------------------------------------------------------
1 | .alert {
2 | margin: 10px 0;
3 | font-weight: bold;
4 | position: relative;
5 | padding-left: 40px;
6 | &:after {
7 | position: absolute;
8 | font: normal normal normal 18px/1 FontAwesome;
9 | left: 16px;
10 | top: 16px;
11 | width: 16px;
12 | height: 16px;
13 | }
14 | }
15 |
16 | .alert-success {
17 | border-color: #98CF6A;
18 | &:after {
19 | color: #48cf36;
20 | content: "\f00c";
21 | text-shadow: 1px 1px 0px #6D924E;
22 | }
23 | }
24 |
25 | .alert-danger {
26 | border-color: #ebb6bf;
27 | color: #CA3532;
28 | &:after {
29 | content: "\f057";
30 | }
31 | }
32 |
33 | .alert-warning {
34 | background-color: #F9F3DD;
35 | border-color: #E9D5AC;
36 | color: #b97a38;
37 | &:after {
38 | content: "\f071";
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/chapter6-rails/app/assets/stylesheets/common/base.scss:
--------------------------------------------------------------------------------
1 | html, body {
2 | min-height: 100%;
3 | height:100%
4 | }
5 |
6 | .navbar {
7 | margin-bottom: 0;
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/chapter6-rails/app/assets/stylesheets/desktop/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neerajsingh0101/reactjs-by-example/0fb831f9add41f51480f468cdd7fcf9318161b65/chapter6-rails/app/assets/stylesheets/desktop/.gitkeep
--------------------------------------------------------------------------------
/chapter6-rails/app/assets/stylesheets/environment/ribbon.scss:
--------------------------------------------------------------------------------
1 | body.orange_ribbon {
2 | &:before {
3 | content: '';
4 | display: block;
5 | width: 100%;
6 | height: 4px;
7 | background: orangered;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/chapter6-rails/app/assets/stylesheets/phone/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neerajsingh0101/reactjs-by-example/0fb831f9add41f51480f468cdd7fcf9318161b65/chapter6-rails/app/assets/stylesheets/phone/.gitkeep
--------------------------------------------------------------------------------
/chapter6-rails/app/carriers/layout_carrier.rb:
--------------------------------------------------------------------------------
1 | class LayoutCarrier
2 |
3 | def class_for_body
4 | if Rails.env.production?
5 | #noop
6 | else
7 | 'orange_ribbon'
8 | end
9 | end
10 |
11 | end
12 |
--------------------------------------------------------------------------------
/chapter6-rails/app/controllers/api/v1/sessions_controller.rb:
--------------------------------------------------------------------------------
1 | class Api::V1::SessionsController < Api::V1::BaseController
2 |
3 | skip_before_action :authenticate_user!
4 | skip_before_action :authenticate_user_using_x_auth_token
5 |
6 | def create
7 | user = User.find_for_database_authentication(email: params[:user] && params[:user][:email])
8 | if invalid_password?(user)
9 | respond_with_error "Incorrect email or password", 401
10 | else
11 | render json: { auth_token: user.authentication_token }, location: root_path, status: :created
12 | end
13 | end
14 |
15 | private
16 |
17 | def invalid_password? user
18 | user.blank? || !user.valid_password?(params[:user][:password])
19 | end
20 |
21 | end
22 |
--------------------------------------------------------------------------------
/chapter6-rails/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | class ApplicationController < ActionController::Base
2 |
3 | # Prevent CSRF attacks by raising an exception.
4 | # For APIs, you may want to use :null_session instead.
5 | protect_from_forgery with: :exception
6 |
7 | before_action :set_honeybadger_context
8 | before_action :set_device_type
9 | before_action :set_layout_carrier
10 |
11 | private
12 |
13 | def ensure_current_user_is_superadmin!
14 | authenticate_user!
15 |
16 | unless current_user.super_admin?
17 | redirect_to root_path, status: :forbidden, alert: "Unauthorized Access!"
18 | end
19 | end
20 |
21 | def set_device_type
22 | request.variant = :phone if browser.mobile?
23 | end
24 |
25 | def set_honeybadger_context
26 | hash = { uuid: request.uuid }
27 | hash.merge!(user_id: current_user.id, user_email: current_user.email) if current_user
28 | Honeybadger.context hash
29 | end
30 |
31 | def set_layout_carrier
32 | @layout_carrier = LayoutCarrier.new
33 | end
34 |
35 | end
36 |
--------------------------------------------------------------------------------
/chapter6-rails/app/controllers/contacts_controller.rb:
--------------------------------------------------------------------------------
1 | class ContactsController < ApplicationController
2 |
3 | def create
4 | @contact = Contact.new(params[:contact])
5 |
6 | if @contact.valid?
7 | Mailer.delay.contact_us_notification(@contact)
8 | flash[:notice] = 'Thank you for your message. We will contact you soon!'
9 | redirect_to pages_contact_us_path
10 | else
11 | render template: 'pages/contact_us'
12 | end
13 | end
14 |
15 | end
16 |
--------------------------------------------------------------------------------
/chapter6-rails/app/controllers/home_controller.rb:
--------------------------------------------------------------------------------
1 | class HomeController < ApplicationController
2 |
3 | def index
4 | render
5 | end
6 |
7 | end
8 |
--------------------------------------------------------------------------------
/chapter6-rails/app/controllers/pages_controller.rb:
--------------------------------------------------------------------------------
1 | class PagesController < ApplicationController
2 |
3 | def index
4 | render
5 | end
6 |
7 | def contact_us
8 | @contact = Contact.new
9 | end
10 |
11 | def about
12 | render
13 | end
14 |
15 | end
16 |
--------------------------------------------------------------------------------
/chapter6-rails/app/controllers/sessions_controller.rb:
--------------------------------------------------------------------------------
1 | class SessionsController < Devise::SessionsController
2 |
3 | def destroy
4 | super
5 | end
6 |
7 | end
8 |
--------------------------------------------------------------------------------
/chapter6-rails/app/controllers/superadmin/base_controller.rb:
--------------------------------------------------------------------------------
1 | class Superadmin::BaseController < ApplicationController
2 |
3 | before_action :ensure_current_user_is_superadmin!
4 |
5 | layout 'superadmin'
6 |
7 | end
8 |
--------------------------------------------------------------------------------
/chapter6-rails/app/controllers/superadmin/users_controller.rb:
--------------------------------------------------------------------------------
1 | class Superadmin::UsersController < Superadmin::BaseController
2 |
3 | before_action :load_user, only: [:edit, :update]
4 |
5 | def index
6 | @users = User.order('id desc')
7 | end
8 |
9 | def edit
10 | @user_name = @user.name
11 |
12 | render partial: 'edit_modal'
13 | end
14 |
15 | def update
16 | @user_name = @user.name
17 | @user.update(user_params)
18 | if @user.valid?
19 | flash[:notice] = "Information for user #{@user.name} successfully updated!"
20 | render json: { redirect_to: superadmin_users_path }
21 | else
22 | render json: { modal_content: render_to_string(partial: 'edit_modal') }
23 | end
24 | end
25 |
26 | private
27 |
28 | def load_user
29 | @user ||= User.find(params[:id])
30 | end
31 |
32 | def user_params
33 | params.require(:user).permit(:first_name, :last_name, :profile_image, :email)
34 | end
35 |
36 | end
37 |
--------------------------------------------------------------------------------
/chapter6-rails/app/helpers/application_helper.rb:
--------------------------------------------------------------------------------
1 | module ApplicationHelper
2 |
3 | def super_admin_signed_in?
4 | user_signed_in? && current_user.super_admin?
5 | end
6 |
7 | def nav_link text, path, condition = false, options = {}
8 | class_name = (current_page?(path) || condition) ? 'active' : ''
9 |
10 | content_tag(:li, class: class_name) do
11 | options[:title] = text unless options.has_key?(:title)
12 | link_to text, path, options
13 | end
14 | end
15 |
16 | end
17 |
--------------------------------------------------------------------------------
/chapter6-rails/app/mailers/mailer.rb:
--------------------------------------------------------------------------------
1 | class Mailer < ActionMailer::Base
2 |
3 | layout 'mailer'
4 |
5 | default from: Rails.application.secrets.mailer_default_from_email
6 |
7 | default_url_options[:host] = Rails.application.secrets.host
8 |
9 | def contact_us_notification(contact)
10 | @email = contact.email
11 | @title = contact.title
12 | @body = contact.body
13 | subject = "Contact us message from #{@email}"
14 |
15 | mail(to: Rails.application.secrets.support_email, from: @email, subject: subject) do |format|
16 | format.html
17 | end
18 | end
19 |
20 | end
21 |
--------------------------------------------------------------------------------
/chapter6-rails/app/middleware/catch_json_parse_errors.rb:
--------------------------------------------------------------------------------
1 | class CatchJsonParseErrors
2 |
3 | def initialize app
4 | @app = app
5 | end
6 |
7 | def call env
8 | begin
9 | @app.call(env)
10 | rescue ActionDispatch::ParamsParser::ParseError => exception
11 | is_content_type_json?(env) ? build_response(exception) : raise(exception)
12 | end
13 | end
14 |
15 | private
16 |
17 | def is_content_type_json? env
18 | env['CONTENT_TYPE'] =~ /application\/json/
19 | end
20 |
21 | def error_message exception
22 | "Payload data is not valid JSON. Error message: #{exception}"
23 | end
24 |
25 | def build_response exception
26 | [ 400, { "Content-Type" => "application/json" }, [ { error: error_message(exception) }.to_json ] ]
27 | end
28 |
29 | end
30 |
--------------------------------------------------------------------------------
/chapter6-rails/app/models/contact.rb:
--------------------------------------------------------------------------------
1 | class Contact
2 | include ActiveModel::Model
3 |
4 | attr_accessor :email, :title, :body
5 |
6 | validates :email, :title, presence: true
7 | validates :email, email: true
8 | end
9 |
--------------------------------------------------------------------------------
/chapter6-rails/app/services/addition_service.rb:
--------------------------------------------------------------------------------
1 | class AdditionService
2 |
3 | attr_reader :number1, :number2
4 |
5 | def initialize number1, number2
6 | @number1 = number1
7 | @number2 = number2
8 | end
9 |
10 | def process
11 | number1 + number2
12 | end
13 |
14 | end
15 |
--------------------------------------------------------------------------------
/chapter6-rails/app/uploaders/profile_image_uploader.rb:
--------------------------------------------------------------------------------
1 | class ProfileImageUploader < CarrierWave::Uploader::Base
2 |
3 | storage :file
4 |
5 | def store_dir
6 | "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
7 | end
8 |
9 | def extension_white_list
10 | %w(jpg jpeg png)
11 | end
12 |
13 | def filename
14 | if original_filename.present?
15 | if model && model.read_attribute(mounted_as).present?
16 | model.read_attribute(mounted_as)
17 | else
18 | "#{secure_token}.#{file.extension}"
19 | end
20 | end
21 | end
22 |
23 | protected
24 |
25 | def secure_token
26 | var = :"@#{mounted_as}_secure_token"
27 | model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid)
28 | end
29 |
30 | end
31 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/home/index.html.haml:
--------------------------------------------------------------------------------
1 | %span.home-message
2 | = react_component 'SearchPage', {}, {prerender: true}
3 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/mailer/contact_us_notification.html.haml:
--------------------------------------------------------------------------------
1 | %h3 New contact
2 | %p
3 | %b Email:
4 | = @email
5 | %p
6 | %b Title:
7 | = @title
8 | %p
9 | %b Message:
10 | = @body
11 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/pages/about.html+phone.haml:
--------------------------------------------------------------------------------
1 | You are seeing the phone version of the about page.
2 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/pages/about.html.haml:
--------------------------------------------------------------------------------
1 | You are seeing the desktop version of the about page.
2 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/pages/contact_us.html.haml:
--------------------------------------------------------------------------------
1 | .row{style: "padding-top: 10px;"}
2 | = simple_form_for @contact, html: { class: 'bootstrap-center-form-medium' } do |f|
3 | %h2 Contact us
4 | .form-controls
5 | = f.input :title, required: true, input_html: { class: 'form-control' }
6 | .form-controls
7 | = f.input :email, required: true, input_html: { class: 'form-control' }
8 | .form-controls
9 | = f.input :body, as: :text, input_html: { class: 'form-control', rows: '3' }
10 | .form-buttons
11 | = f.button :submit, 'Send message', class: "btn btn-primary"
12 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/pages/index.html.haml:
--------------------------------------------------------------------------------
1 | Listing of All Pages
2 | %br/
3 | = link_to "Contact US", pages_contact_us_path
4 | %br/
5 | = link_to "About", pages_about_path
6 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/shared/_bootstrap_flash.html.haml:
--------------------------------------------------------------------------------
1 | - flash.each do |name, message|
2 | - if message.present?
3 | %div{class: "alert alert-#{name.to_s == 'alert' ? "danger" : "success"}"}
4 | %a.close{"data-dismiss" => "alert"} ×
5 | = content_tag :div, message, id: "flash_#{name}" if message.is_a?(String)
6 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/shared/_modal.html.haml:
--------------------------------------------------------------------------------
1 | %div{class: "modal", "data-behavior" => "modal-content"}
2 | .modal-dialog
3 | .modal-content
4 | .modal-header
5 | = button_tag '×', :class => "close btn-close-dialog", "data-behavior" => "modal-close", "aria-hidden" => "true"
6 | %h4.modal-title= yield(:modal_title)
7 | .modal-body
8 | = yield(:modal_body)
9 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/shared/_nav.html.haml:
--------------------------------------------------------------------------------
1 | %ul.nav.navbar-nav
2 | = nav_link 'Home', root_path
3 | = nav_link 'About', pages_about_path
4 | = nav_link 'Contact us', pages_contact_us_path
5 | = render('shared/user_right_nav')
6 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/shared/_superadmin_nav.html.haml:
--------------------------------------------------------------------------------
1 | %ul.nav.navbar-nav
2 | = nav_link('Users', superadmin_users_path)
3 | = nav_link("Active Admin", active_admin_root_path)
4 | = nav_link('DJ', '/delayed_job', false, "target" => '_blank')
5 | = render('shared/user_right_nav')
6 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/shared/_user_is_signed_in.html.haml:
--------------------------------------------------------------------------------
1 | %li.dropdown
2 | %a.dropdown-toggle{"data-toggle" => "dropdown", :href => "#"}
3 | = current_user.name
4 | %b.caret
5 | %ul.dropdown-menu
6 | - if super_admin_signed_in?
7 | = nav_link 'Superadmin', superadmin_root_path
8 | %li.divider
9 | = nav_link 'My account', profile_path
10 | = nav_link 'Change password', password_edit_path
11 | = nav_link 'Logout', destroy_user_session_path, false, method: :delete
12 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/shared/_user_right_nav.html.haml:
--------------------------------------------------------------------------------
1 | %ul.nav.navbar-nav.navbar-right
2 | - if user_signed_in?
3 | = render 'shared/user_is_signed_in'
4 | - else
5 | = nav_link 'Sign in', new_session_path(:user)
6 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/superadmin/users/_edit_modal.html.haml:
--------------------------------------------------------------------------------
1 | = content_for(:modal_title) do
2 | Edit #{@user_name.to_s.humanize}
3 |
4 | = content_for(:modal_body) do
5 | .row{style: "padding-top: 10px;"}
6 | = simple_form_for(@user, url: superadmin_user_path(@user), |
7 | method: :patch, |
8 | wrapper: :bootstrap3, |
9 | html: { method: :put, class: 'bootstrap-center-form-medium' }) do |f| |
10 | .form-controls
11 | = f.input :email, required: true, |
12 | autofocus: true, |
13 | input_html: { class: 'form-control' } |
14 | = f.input :first_name, required: true, input_html: { class: 'form-control' }
15 | = f.input :last_name, required: true, input_html: { class: 'form-control' }
16 | = f.input :profile_image, as: :file
17 | .form-buttons
18 | = f.button :submit, "Update", class: 'btn btn-primary'
19 |
20 |
21 | = render "shared/modal"
22 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/superadmin/users/index.html.haml:
--------------------------------------------------------------------------------
1 | %table.table.table-striped
2 | %thead
3 | %tr
4 | %th Name
5 | %th Email
6 | %th Last signed in
7 | %th
8 | - @users.each do |user|
9 | %tr
10 | %td
11 | = user.name
12 | %td
13 | = user.email
14 | %td
15 | = user.last_sign_in_at
16 | %td
17 | = link_to 'Edit', "#", data: { url: edit_superadmin_user_path(user), behavior: 'display-in-modal' }
18 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/users/confirmations/new.html.haml:
--------------------------------------------------------------------------------
1 | %h2 Resend confirmation instructions
2 | = simple_form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f|
3 | = f.error_notification
4 | = f.full_error :confirmation_token
5 | .form-inputs
6 | = f.input :email, required: true, autofocus: true
7 | .form-actions
8 | = f.button :submit, "Resend confirmation instructions"
9 | = render "users/shared/links"
10 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/users/mailer/confirmation_instructions.html.haml:
--------------------------------------------------------------------------------
1 | %p
2 | Welcome #{@email}!
3 | %p You can confirm your account email through the link below:
4 | %p= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token)
5 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/users/mailer/reset_password_instructions.html.haml:
--------------------------------------------------------------------------------
1 | %p
2 | Hello #{@resource.email}!
3 | %p Someone has requested a link to change your password. You can do this through the link below.
4 | %p= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token)
5 |
6 | %p If you didn't request this, please ignore this email.
7 | %p Your password won't change until you access the link above and create a new one.
8 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/users/mailer/unlock_instructions.html.haml:
--------------------------------------------------------------------------------
1 | %p
2 | Hello #{@resource.email}!
3 | %p Your account has been locked due to an excessive number of unsuccessful sign in attempts.
4 | %p Click the link below to unlock your account:
5 | %p= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token)
6 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/users/passwords/new.html.haml:
--------------------------------------------------------------------------------
1 | .row{style: "padding-top: 10px;"}
2 | = simple_form_for(resource, as: resource_name, |
3 | url: password_path(resource_name), |
4 | wrapper: :bootstrap3, |
5 | html: { method: :post, class: 'bootstrap-center-form-medium' }) do |f| |
6 | %h2 Forgot your password?
7 | .form-controls
8 | = f.input :email, required: true, autofocus: true, input_html: { class: 'form-control' }
9 | .form-buttons
10 | = f.button :submit, "Send me reset password instructions", class: 'btn btn-primary'
11 | .devise-links
12 | = render "users/shared/links"
13 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/users/registrations/new.html.haml:
--------------------------------------------------------------------------------
1 | .row{style: "padding-top: 10px;"}
2 | = simple_form_for(resource, as: resource_name, |
3 | url: registration_path(resource_name), |
4 | wrapper: :bootstrap3, |
5 | html: { class: 'bootstrap-center-form-medium' }) do |f| |
6 | %h2 Sign up
7 | .form-controls
8 | = f.input :email, required: true, autofocus: true, input_html: { class: 'form-control' }
9 | = f.input :first_name, required: true, input_html: { class: 'form-control' }
10 | = f.input :last_name, required: true, input_html: { class: 'form-control' }
11 | = f.input :password, required: true, input_html: { class: 'form-control' }
12 | = f.input :password_confirmation, required: true, input_html: { class: 'form-control' }
13 | .form-buttons
14 | = f.button :submit, "Sign up", class: 'btn btn-primary'
15 | .devise-links
16 | = render "users/shared/links"
17 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/users/sessions/new.html.haml:
--------------------------------------------------------------------------------
1 | .row{style: "padding-top: 10px;"}
2 | = simple_form_for(resource, as: resource_name, |
3 | url: session_path(resource_name), |
4 | wrapper: :bootstrap3, |
5 | html: { class: 'bootstrap-center-form-medium' }) do |f| |
6 | %h2 Please Sign in
7 | .form-controls
8 | = f.input :email, placeholder: 'Email address', label: false, autofocus: true, input_html: { class: 'form-control' }
9 | = f.input :password, placeholder: 'Password', label: false, input_html: { class: 'form-control' }
10 | - if devise_mapping.rememberable?
11 | = f.input :remember_me, as: :boolean, wrapper: :default
12 | .form-buttons
13 | = f.button :submit, "Sign in", class: 'btn btn-primary'
14 | .devise-links
15 | = render "users/shared/links"
16 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/users/shared/_links.haml:
--------------------------------------------------------------------------------
1 | - if controller_name != 'sessions'
2 | = link_to "Sign in", new_session_path(resource_name)
3 | %br/
4 | - if devise_mapping.registerable? && controller_name != 'registrations'
5 | = link_to "Sign up", new_registration_path(resource_name)
6 | %br/
7 | - if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations'
8 | = link_to "Forgot your password?", new_password_path(resource_name)
9 | %br/
10 | - if devise_mapping.confirmable? && controller_name != 'confirmations'
11 | = link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name)
12 | %br/
13 | - if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks'
14 | = link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name)
15 | %br/
16 | - if devise_mapping.omniauthable?
17 | - resource_class.omniauth_providers.each do |provider|
18 | = link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider)
19 | %br/
20 |
--------------------------------------------------------------------------------
/chapter6-rails/app/views/users/unlocks/new.html.haml:
--------------------------------------------------------------------------------
1 | %h2 Resend unlock instructions
2 | = form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f|
3 | = devise_error_messages!
4 | %div
5 | = f.label :email
6 | %br/
7 | = f.email_field :email, autofocus: true
8 | %div
9 | = f.submit "Resend unlock instructions"
10 | = render "users/shared/links"
11 |
--------------------------------------------------------------------------------
/chapter6-rails/app/workers/base_worker.rb:
--------------------------------------------------------------------------------
1 | class BaseWorker
2 |
3 | def perform
4 | Honeybadger.context(job_name: self.class.name, app_name: Rails.application.engine_name)
5 | end
6 |
7 | end
8 |
--------------------------------------------------------------------------------
/chapter6-rails/app/workers/event_notification_worker.rb:
--------------------------------------------------------------------------------
1 | class EventNotificationWorker < BaseWorker
2 |
3 | def perform
4 | super
5 |
6 | # do the business stuff
7 | end
8 |
9 | end
10 |
--------------------------------------------------------------------------------
/chapter6-rails/bin/bundle:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3 | load Gem.bin_path('bundler', 'bundle')
4 |
--------------------------------------------------------------------------------
/chapter6-rails/bin/delayed_job:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
4 | require 'delayed/command'
5 | Delayed::Command.new(ARGV).daemonize
6 |
--------------------------------------------------------------------------------
/chapter6-rails/bin/honeybadger:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
4 | require 'honeybadger/cli'
5 | Honeybadger::CLI.start(ARGV)
6 |
--------------------------------------------------------------------------------
/chapter6-rails/bin/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | APP_PATH = File.expand_path('../../config/application', __FILE__)
3 | require_relative '../config/boot'
4 | require 'rails/commands'
5 |
--------------------------------------------------------------------------------
/chapter6-rails/bin/rake:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require_relative '../config/boot'
3 | require 'rake'
4 | Rake.application.run
5 |
--------------------------------------------------------------------------------
/chapter6-rails/bin/setup:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require 'pathname'
3 |
4 | # path to your application root.
5 | APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
6 |
7 | Dir.chdir APP_ROOT do
8 | # This script is a starting point to setup your application.
9 | # Add necessary setup steps to this file:
10 |
11 | puts "== Installing dependencies =="
12 | system "gem install bundler --conservative"
13 | system "bundle check || bundle install"
14 |
15 | # puts "\n== Copying sample files =="
16 | # unless File.exist?("config/database.yml")
17 | # system "cp config/database.yml.sample config/database.yml"
18 | # end
19 |
20 | puts "\n== Preparing database =="
21 | system "bin/rake db:setup"
22 |
23 | puts "\n== Removing old logs and tempfiles =="
24 | system "rm -f log/*"
25 | system "rm -rf tmp/cache"
26 |
27 | puts "\n== Restarting application server =="
28 | system "touch tmp/restart.txt"
29 | end
30 |
--------------------------------------------------------------------------------
/chapter6-rails/bin/spring:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | # This file loads spring without using Bundler, in order to be fast
4 | # It gets overwritten when you run the `spring binstub` command
5 |
6 | unless defined?(Spring)
7 | require "rubygems"
8 | require "bundler"
9 |
10 | if match = Bundler.default_lockfile.read.match(/^GEM$.*?^ spring \((.*?)\)$.*?^$/m)
11 | ENV["GEM_PATH"] = ([Bundler.bundle_path.to_s] + Gem.path).join(File::PATH_SEPARATOR)
12 | ENV["GEM_HOME"] = ""
13 | Gem.paths = ENV
14 |
15 | gem "spring", match[1]
16 | require "spring/binstub"
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/chapter6-rails/circle.yml:
--------------------------------------------------------------------------------
1 | ## Customize the test machine
2 | machine:
3 |
4 | timezone:
5 | America/New_York # List of timezones http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
6 |
7 | # Version of ruby to use
8 | ruby:
9 | version:
10 | 2.2.2
11 |
12 | ## Customize database setup
13 | database:
14 | override:
15 | # replace Circle's generated database.yml
16 | - cp config/database.yml.ci config/database.yml
17 | - bundle exec rake db:create db:schema:load --trace
18 |
19 | test:
20 | minitest_globs:
21 | - test/**/*_test.rb
22 |
--------------------------------------------------------------------------------
/chapter6-rails/config.ru:
--------------------------------------------------------------------------------
1 | # This file is used by Rack-based servers to start the application.
2 |
3 | require ::File.expand_path('../config/environment', __FILE__)
4 | run Rails.application
5 |
--------------------------------------------------------------------------------
/chapter6-rails/config/boot.rb:
--------------------------------------------------------------------------------
1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
2 |
3 | require 'bundler/setup' # Set up gems listed in the Gemfile.
4 |
--------------------------------------------------------------------------------
/chapter6-rails/config/database.yml.ci:
--------------------------------------------------------------------------------
1 | test:
2 | host: localhost
3 | username: ubuntu
4 | database: circle_ruby_test
5 | adapter: postgresql
6 |
--------------------------------------------------------------------------------
/chapter6-rails/config/database.yml.postgresql:
--------------------------------------------------------------------------------
1 | <% branch_name = `git symbolic-ref HEAD 2>/dev/null`.chomp.sub('refs/heads/', '') %>
2 | <% repository_name = `git rev-parse --show-toplevel`.split('/').last.strip %>
3 |
4 | development:
5 | adapter: postgresql
6 | encoding: unicode
7 | database: <%= repository_name %>_development
8 | pool: 5
9 | username: postgres
10 | password:
11 |
12 | test:
13 | adapter: postgresql
14 | encoding: unicode
15 | database: <%= repository_name %>_test
16 | pool: 5
17 | username: postgres
18 | password:
19 |
--------------------------------------------------------------------------------
/chapter6-rails/config/database.yml.postgresqlapp:
--------------------------------------------------------------------------------
1 | <% branch_name = `git symbolic-ref HEAD 2>/dev/null`.chomp.sub('refs/heads/', '') %>
2 | <% repository_name = `git rev-parse --show-toplevel`.split('/').last.strip %>
3 |
4 | # Check doc/why_database_name_only_63_characters_long.md to see
5 | # details about the restriction on database name
6 |
7 | # If you prefer to have branch name in the database name then use following
8 | # database: <%= "#{repository_name}_development_#{branch_name}"[0...63] %>
9 |
10 | development:
11 | adapter: postgresql
12 | database: <%= "#{repository_name}_development"[0...63] %>
13 | host: localhost
14 |
15 | test:
16 | adapter: postgresql
17 | database: <%= "#{repository_name}_test"[0...63] %>
18 | host: localhost
19 |
--------------------------------------------------------------------------------
/chapter6-rails/config/database.yml.sqlite3:
--------------------------------------------------------------------------------
1 | # SQLite version 3.x
2 | # gem install sqlite3
3 | #
4 | # Ensure the SQLite 3 gem is defined in your Gemfile
5 | # gem 'sqlite3'
6 | #
7 | default: &default
8 | adapter: sqlite3
9 | pool: 5
10 | timeout: 5000
11 |
12 | development:
13 | <<: *default
14 | database: db/development.sqlite3
15 |
16 | # Warning: The database defined as "test" will be erased and
17 | # re-generated from your development database when you run "rake".
18 | # Do not set this db to the same as development or production.
19 | test:
20 | <<: *default
21 | database: db/test.sqlite3
22 |
23 | production:
24 | <<: *default
25 | database: db/production.sqlite3
26 |
--------------------------------------------------------------------------------
/chapter6-rails/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the Rails application.
2 | require File.expand_path('../application', __FILE__)
3 |
4 | # Initialize the Rails application.
5 | Rails.application.initialize!
6 |
--------------------------------------------------------------------------------
/chapter6-rails/config/honeybadger.yml:
--------------------------------------------------------------------------------
1 | ---
2 | api_key: <%= Rails.application.secrets.honeybadger_api_key %>
3 |
--------------------------------------------------------------------------------
/chapter6-rails/config/initializers/asset_precompile.rb:
--------------------------------------------------------------------------------
1 | Rails.application.config.assets.precompile += [ 'application_desktop.css',
2 | 'application_phone.css',
3 | 'application_desktop.js',
4 | 'application_phone.js']
5 |
--------------------------------------------------------------------------------
/chapter6-rails/config/initializers/assets.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Version of your assets, change this if you want to expire all your assets.
4 | Rails.application.config.assets.version = '1.0'
5 |
6 | # Precompile additional assets.
7 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
8 | Rails.application.config.assets.precompile += %w( common/active_admin.css )
9 |
--------------------------------------------------------------------------------
/chapter6-rails/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5 |
6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7 | # Rails.backtrace_cleaner.remove_silencers!
8 |
--------------------------------------------------------------------------------
/chapter6-rails/config/initializers/catch_json_parser_errors.rb:
--------------------------------------------------------------------------------
1 | unless Rails.env.development?
2 | Rails.application.config.middleware.insert_before ActionDispatch::ParamsParser, "CatchJsonParseErrors"
3 | end
4 |
--------------------------------------------------------------------------------
/chapter6-rails/config/initializers/cookies_serializer.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | Rails.application.config.action_dispatch.cookies_serializer = :json
4 |
--------------------------------------------------------------------------------
/chapter6-rails/config/initializers/delayed_job_config.rb:
--------------------------------------------------------------------------------
1 | Delayed::Worker.destroy_failed_jobs = false
2 |
3 | # Amount of time to sleep when no jobs are found. You can easily set it to 5 seconds or less.
4 | Delayed::Worker.sleep_delay = 5
5 |
6 | # If the work takes more than x minutes then DJ will abort
7 | Delayed::Worker.max_run_time = 5.minutes
8 |
9 | Delayed::Worker.read_ahead = 10
10 |
11 | Delayed::Worker.delay_jobs = !Rails.env.test?
12 |
13 | # In production have default number of attempts ( which I think is 30 )
14 | if !Rails.env.production?
15 | Delayed::Worker.max_attempts = 3
16 | end
17 |
--------------------------------------------------------------------------------
/chapter6-rails/config/initializers/devise_async.rb:
--------------------------------------------------------------------------------
1 | Devise::Async.setup do |config|
2 | config.backend = :delayed_job
3 | config.priority = -1
4 | end
--------------------------------------------------------------------------------
/chapter6-rails/config/initializers/email_interceptor.rb:
--------------------------------------------------------------------------------
1 | if Rails.application.secrets.intercept_and_forward_emails_to.present?
2 | options = { forward_emails_to: Rails.application.secrets.intercept_and_forward_emails_to,
3 | deliver_emails_to: ['@example.com'] }
4 |
5 | interceptor = MailInterceptor::Interceptor.new(options)
6 | ActionMailer::Base.register_interceptor(interceptor)
7 | end
8 |
--------------------------------------------------------------------------------
/chapter6-rails/config/initializers/email_prefixer.rb:
--------------------------------------------------------------------------------
1 | EmailPrefixer.configure do |config|
2 | config.stage_name = 'Search'
3 | end
4 |
--------------------------------------------------------------------------------
/chapter6-rails/config/initializers/filter_parameter_logging.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Configure sensitive parameters which will be filtered from the log file.
4 | Rails.application.config.filter_parameters += [:password]
5 |
--------------------------------------------------------------------------------
/chapter6-rails/config/initializers/honeybadger.rb:
--------------------------------------------------------------------------------
1 | # When a DelayedJob operation fails then honeybadger should collect
2 | # contextual information like job name and the host.
3 | class HoneybadgerDelayedJobPlugin < Delayed::Plugin
4 | callbacks do |lifecycle|
5 | lifecycle.before(:invoke_job) do |job, *args, &block|
6 | Honeybadger.context(job_name: job.name, host: Rails.application.secrets.host)
7 | end
8 | end
9 | end
10 |
11 | Delayed::Worker.plugins << HoneybadgerDelayedJobPlugin
12 |
--------------------------------------------------------------------------------
/chapter6-rails/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format. Inflections
4 | # are locale specific, and you may define rules for as many different
5 | # locales as you wish. All of these examples are active by default:
6 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
7 | # inflect.plural /^(ox)$/i, '\1en'
8 | # inflect.singular /^(ox)en/i, '\1'
9 | # inflect.irregular 'person', 'people'
10 | # inflect.uncountable %w( fish sheep )
11 | # end
12 |
13 | # These inflection rules are supported but not enabled by default:
14 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
15 | # inflect.acronym 'RESTful'
16 | # end
17 |
--------------------------------------------------------------------------------
/chapter6-rails/config/initializers/marginalia.rb:
--------------------------------------------------------------------------------
1 | Marginalia.application_name = 'Search'
2 |
--------------------------------------------------------------------------------
/chapter6-rails/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new mime types for use in respond_to blocks:
4 | # Mime::Type.register "text/richtext", :rtf
5 |
--------------------------------------------------------------------------------
/chapter6-rails/config/initializers/rack_deflater.rb:
--------------------------------------------------------------------------------
1 | Rails.application.config.middleware.use Rack::Deflater
2 |
--------------------------------------------------------------------------------
/chapter6-rails/config/initializers/session_store.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | Rails.application.config.session_store :cookie_store, key: '_Search_session'
4 |
--------------------------------------------------------------------------------
/chapter6-rails/config/initializers/setup_email.rb:
--------------------------------------------------------------------------------
1 | ActionMailer::Base.default_url_options[:host] = Rails.application.secrets.host
2 |
3 | ActionMailer::Base.delivery_method = Rails.application.secrets.mailer_delivery_method
4 |
5 | if ActionMailer::Base.delivery_method == :smtp
6 | ActionMailer::Base.smtp_settings = Rails.application.secrets.mailer['smtp_settings'].symbolize_keys
7 | end
8 |
--------------------------------------------------------------------------------
/chapter6-rails/config/initializers/tagged_logging.rb:
--------------------------------------------------------------------------------
1 | Rails.application.config.log_tags = [ :subdomain, :uuid ]
2 |
--------------------------------------------------------------------------------
/chapter6-rails/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # This file contains settings for ActionController::ParamsWrapper which
4 | # is enabled by default.
5 |
6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7 | ActiveSupport.on_load(:action_controller) do
8 | wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
9 | end
10 |
11 | # To enable root element in JSON for ActiveRecord objects.
12 | # ActiveSupport.on_load(:active_record) do
13 | # self.include_root_in_json = true
14 | # end
15 |
--------------------------------------------------------------------------------
/chapter6-rails/config/locales/en.bootstrap.yml:
--------------------------------------------------------------------------------
1 | # Sample localization file for English. Add more files in this directory for other locales.
2 | # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3 |
4 | en:
5 | helpers:
6 | actions: "Actions"
7 | links:
8 | back: "Back"
9 | cancel: "Cancel"
10 | confirm: "Are you sure?"
11 | destroy: "Delete"
12 | new: "New"
13 | edit: "Edit"
14 | titles:
15 | edit: "Edit %{model}"
16 | save: "Save %{model}"
17 | new: "New %{model}"
18 | delete: "Delete %{model}"
19 |
--------------------------------------------------------------------------------
/chapter6-rails/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Files in the config/locales directory are used for internationalization
2 | # and are automatically loaded by Rails. If you want to use locales other
3 | # than English, add the necessary files in this directory.
4 | #
5 | # To use the locales, use `I18n.t`:
6 | #
7 | # I18n.t 'hello'
8 | #
9 | # In views, this is aliased to just `t`:
10 | #
11 | # <%= t('hello') %>
12 | #
13 | # To use a different locale, set it with `I18n.locale`:
14 | #
15 | # I18n.locale = :es
16 | #
17 | # This would use the information in config/locales/es.yml.
18 | #
19 | # To learn more, please read the Rails Internationalization guide
20 | # available at http://guides.rubyonrails.org/i18n.html.
21 |
22 | en:
23 | hello: "Hello world"
24 |
--------------------------------------------------------------------------------
/chapter6-rails/config/locales/simple_form.en.yml:
--------------------------------------------------------------------------------
1 | en:
2 | simple_form:
3 | "yes": 'Yes'
4 | "no": 'No'
5 | required:
6 | text: 'required'
7 | mark: '*'
8 | # You can uncomment the line below if you need to overwrite the whole required html.
9 | # When using html, text and mark won't be used.
10 | # html: '*'
11 | error_notification:
12 | default_message: "Please review the problems below:"
13 | # Labels and hints examples
14 | # labels:
15 | # defaults:
16 | # password: 'Password'
17 | # user:
18 | # new:
19 | # email: 'E-mail to sign in.'
20 | # edit:
21 | # email: 'E-mail.'
22 | # hints:
23 | # defaults:
24 | # username: 'User name to sign in.'
25 | # password: 'No special characters, please.'
26 |
27 |
--------------------------------------------------------------------------------
/chapter6-rails/config/unicorn.rb:
--------------------------------------------------------------------------------
1 | # this template has been picked up from
2 | # https://devcenter.heroku.com/articles/rails-unicorn
3 |
4 | worker_processes Integer(ENV["WEB_CONCURRENCY"] || 2)
5 |
6 | # 30 seconds is the timeout for heroku. If it is not
7 | # deployed on heroku then it can be bumped up.
8 | timeout 30
9 |
10 | preload_app true
11 |
12 | before_fork do |server, worker|
13 | Signal.trap 'TERM' do
14 | puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
15 | Process.kill 'QUIT', Process.pid
16 | end
17 |
18 | defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
19 | end
20 |
21 | after_fork do |server, worker|
22 | Signal.trap 'TERM' do
23 | puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
24 | end
25 |
26 | defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
27 | end
28 |
--------------------------------------------------------------------------------
/chapter6-rails/db/migrate/20131112184628_add_devise_to_users.rb:
--------------------------------------------------------------------------------
1 | class AddDeviseToUsers < ActiveRecord::Migration
2 | def self.up
3 | create_table(:users) do |t|
4 | ## Database authenticatable
5 | t.string :email, :null => false, :default => ""
6 | t.string :encrypted_password, :null => false, :default => ""
7 |
8 | ## Recoverable
9 | t.string :reset_password_token
10 | t.datetime :reset_password_sent_at
11 |
12 | ## Rememberable
13 | t.datetime :remember_created_at
14 |
15 | ## Trackable
16 | t.integer :sign_in_count, :default => 0, :null => false
17 | t.datetime :current_sign_in_at
18 | t.datetime :last_sign_in_at
19 | t.string :current_sign_in_ip
20 | t.string :last_sign_in_ip
21 |
22 | t.timestamps
23 | end
24 |
25 | add_index :users, :email, :unique => true
26 | add_index :users, :reset_password_token, :unique => true
27 | # add_index :users, :confirmation_token, :unique => true
28 | # add_index :users, :unlock_token, :unique => true
29 | end
30 |
31 | def self.down
32 | drop_table :users
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/chapter6-rails/db/migrate/20131122045009_add_user_attributes.rb:
--------------------------------------------------------------------------------
1 | class AddUserAttributes < ActiveRecord::Migration
2 | def change
3 | add_column :users, :last_name, :string
4 | add_column :users, :first_name, :string
5 | add_column :users, :role, :string, default: 'standard'
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/chapter6-rails/db/migrate/20131213184726_create_active_admin_comments.rb:
--------------------------------------------------------------------------------
1 | class CreateActiveAdminComments < ActiveRecord::Migration
2 | def self.up
3 | create_table :active_admin_comments do |t|
4 | t.string :namespace
5 | t.text :body
6 | t.string :resource_id, :null => false
7 | t.string :resource_type, :null => false
8 | t.references :author, :polymorphic => true
9 | t.timestamps
10 | end
11 | add_index :active_admin_comments, [:namespace]
12 | add_index :active_admin_comments, [:author_type, :author_id]
13 | add_index :active_admin_comments, [:resource_type, :resource_id]
14 | end
15 |
16 | def self.down
17 | drop_table :active_admin_comments
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/chapter6-rails/db/migrate/20140220111712_add_authentication_token_to_users.rb:
--------------------------------------------------------------------------------
1 | class AddAuthenticationTokenToUsers < ActiveRecord::Migration
2 | def change
3 | add_column :users, :authentication_token, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/chapter6-rails/db/migrate/20140225143027_add_profile_image_to_users.rb:
--------------------------------------------------------------------------------
1 | class AddProfileImageToUsers < ActiveRecord::Migration
2 | def change
3 | add_column :users, :profile_image, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/chapter6-rails/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # This file should contain all the record creation needed to seed the database with its default values.
2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
3 | #
4 | # Examples:
5 | #
6 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
7 | # Mayor.create(name: 'Emanuel', city: cities.first)
8 |
--------------------------------------------------------------------------------
/chapter6-rails/doc/why_database_name_only_63_characters_long.md:
--------------------------------------------------------------------------------
1 | ### Why length of table name is limited to 63 characters long?
2 |
3 | The default limit on length of identifiers in PostGreSQL is 63 because
4 | value of `NAMEDATALEN` constant is 64 by default. The length of identifiers
5 | is `NAMEDATALEN - 1` which becomes `64 - 1` equal to 63.
6 |
7 | This configuration can't be changed without compiling PostGreSQL again.
8 | We use name of the repository and name of branch to dynamically
9 | calculate database name for every branch. But if the length of this
10 | combination becomes greater than 63 then it gives error:
11 |
12 | ```
13 | Input string is longer than NAMEDATALEN-1 (63)
14 | ```
15 |
16 | To avoid this, we have restricted the length of the database name to
17 | maximum 63 characters. This has a possible side-effect that 2 branches with long names and
18 | similar characters upto length 63 will have same database name. But
19 | it is very unlikely.
20 |
--------------------------------------------------------------------------------
/chapter6-rails/lib/templates/erb/scaffold/_form.html.erb:
--------------------------------------------------------------------------------
1 | <%%= simple_form_for(@<%= singular_table_name %>) do |f| %>
2 | <%%= f.error_notification %>
3 |
4 |
5 | <%- attributes.each do |attribute| -%>
6 | <%%= f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %> %>
7 | <%- end -%>
8 |
9 |
10 |
11 | <%%= f.button :submit %>
12 |
13 | <%% end %>
14 |
--------------------------------------------------------------------------------
/chapter6-rails/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neerajsingh0101/reactjs-by-example/0fb831f9add41f51480f468cdd7fcf9318161b65/chapter6-rails/public/favicon.ico
--------------------------------------------------------------------------------
/chapter6-rails/public/robots.txt:
--------------------------------------------------------------------------------
1 | # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
2 | #
3 | # To ban all spiders from the entire site uncomment the next two lines:
4 | # User-agent: *
5 | # Disallow: /
6 |
--------------------------------------------------------------------------------
/chapter6-rails/test/controllers/active_admin/dashboard_controller_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class ActiveAdmin::DashboardControllerTest < ActionController::TestCase
4 | fixtures :all
5 |
6 | def setup
7 | sign_in users(:admin)
8 | end
9 |
10 | def test_index_success_for_super_admin
11 | get :index
12 | assert_response :success
13 | end
14 |
15 | def test_index_redirects_for_non_super_admin
16 | sign_in users(:nancy)
17 | get :index
18 | assert_response :forbidden
19 | end
20 |
21 | end
22 |
--------------------------------------------------------------------------------
/chapter6-rails/test/controllers/api/v1/sessions_controller_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class Api::V1::SessionsControllerTest < ActionController::TestCase
4 |
5 | def test_valid_email_and_password_should_be_able_to_log_in
6 | admin = users :admin
7 | post :create, user: { email: admin.email, password: 'welcome' }
8 | assert_response :success
9 | end
10 |
11 | def test_wrong_combination_of_email_and_password_should_not_be_able_to_log_in
12 | non_existent_email = 'this_email_does_not_exist_in_db@example.email'
13 | post :create, user: { email: non_existent_email, password: 'welcome' }
14 | assert_response 401
15 | assert_equal 'Incorrect email or password', JSON.parse(response.body)['error']
16 | end
17 |
18 | def test_should_return_auth_token
19 | admin = users :admin
20 |
21 | post :create, user: { email: admin.email, password: 'welcome' }
22 |
23 | assert_response :success
24 | assert JSON.parse(response.body)['auth_token']
25 | end
26 |
27 | end
28 |
--------------------------------------------------------------------------------
/chapter6-rails/test/controllers/home_controller_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class HomeControllerTest < ActionController::TestCase
4 |
5 | def test_index_renders_message
6 | admin = users :admin
7 | sign_in admin
8 |
9 | get :index
10 |
11 | assert_response :success
12 | end
13 |
14 | end
15 |
--------------------------------------------------------------------------------
/chapter6-rails/test/controllers/pages_controller_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class PagesControllerTest < ActionController::TestCase
4 |
5 | def test_index_success
6 | get :index
7 |
8 | assert_response :success
9 | end
10 |
11 | def test_contact_us_success
12 | get :contact_us
13 |
14 | assert_response :success
15 | end
16 |
17 | def test_about_success
18 | get :about
19 |
20 | assert_response :success
21 | end
22 |
23 | end
24 |
--------------------------------------------------------------------------------
/chapter6-rails/test/controllers/superadmin/users_controller_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class Superadmin::UsersControllerTest < ActionController::TestCase
4 |
5 | def test_index_when_user_is_superadmin
6 | user = users :admin
7 | sign_in user
8 | get :index
9 | assert_response :success
10 | end
11 |
12 | def test_index_when_user_is_not_superadmin
13 | user = users :nancy
14 | sign_in user
15 | get :index
16 | assert_response :forbidden
17 | end
18 |
19 | def test_edit_user_modal_success_response
20 | user = users :admin
21 | sign_in user
22 | get :edit, id: users(:nancy)
23 | assert_response :success
24 | end
25 |
26 | def test_user_update_success
27 | admin = users :admin
28 | sign_in admin
29 | nancy = users :nancy
30 |
31 | post :update, id: nancy, user: {first_name: 'Jane'}
32 | nancy.reload
33 |
34 | assert 'Jane', nancy.first_name
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/chapter6-rails/test/fixtures/users.yml:
--------------------------------------------------------------------------------
1 | admin:
2 | email: 'admin@example.com'
3 | first_name: 'Adam'
4 | last_name: 'Smith'
5 | encrypted_password: '$2a$10$3OF9YyLG6D8P8EqFFdudmeIUtIlnX2usIFYhAJ77pep5y93BLuSuu' #welcome
6 | reset_password_token: 5h632xrnASqFanDhKQsB8
7 | role: 'super_admin'
8 | authentication_token: 5h632xrnASqFanDhKQsB8
9 |
10 | nancy:
11 | email: nancy.smith@example.com
12 | first_name: 'Nancy'
13 | last_name: 'Smith'
14 | encrypted_password: '$2a$10$3OF9YyLG6D8P8EqFFdudmeIUtIlnX2usIFYhAJ77pep5y93BLuSuu' #welcome
15 | reset_password_token: 5h632xrnASsFanDhKQsB7
16 | authentication_token: 5h632xrnASqFanDhKQsB8
17 |
--------------------------------------------------------------------------------
/chapter6-rails/test/integration/api_invalid_json_data_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class ApiInvalidJsonDataTest < ActionDispatch::IntegrationTest
4 |
5 | def test_invalid_payload_responds_with_message
6 | invalid_json = %Q{ { "foo":'bar' } }
7 |
8 | post "/v1/users", invalid_json , "CONTENT_TYPE" => 'application/json'
9 |
10 | assert_response 400
11 | assert response.body.include?("Payload data is not valid JSON"), response.body
12 | end
13 |
14 | end
15 |
--------------------------------------------------------------------------------
/chapter6-rails/test/integration/compression_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class CompressionTest < ActionDispatch::IntegrationTest
4 | def test_a_visitor_browser_that_supports_compression
5 | ['deflate','gzip', 'deflate,gzip','gzip,deflate'].each do|compression_method|
6 | get root_path, {}, {'HTTP_ACCEPT_ENCODING' => compression_method }
7 | assert response.headers['Content-Encoding']
8 | end
9 | end
10 |
11 | def test_a_visitor_browser_does_not_support_compression
12 | get root_path
13 | assert_not response.headers['Content-Encoding']
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/chapter6-rails/test/models/contact_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class ContactTest < ActiveSupport::TestCase
4 |
5 | def test_valid_contact
6 | valid_contact = { email: 'bob@exmaple.com',
7 | title: 'need help',
8 | body: 'some message' }
9 |
10 | contact = Contact.new(valid_contact)
11 |
12 | assert contact.valid?
13 | end
14 |
15 | def test_invalid_contact
16 | invalid_contact = { email: 'bob',
17 | title: '',
18 | body: 'some message' }
19 |
20 | contact = Contact.new(invalid_contact)
21 |
22 | assert_not contact.valid?
23 | assert_includes contact.errors.full_messages, "Title can't be blank"
24 | assert_includes contact.errors.full_messages, "Email is invalid"
25 | end
26 |
27 | end
28 |
--------------------------------------------------------------------------------
/chapter6-rails/test/models/user_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class UserTest < ActiveSupport::TestCase
4 |
5 | def test_admin_is_indeed_super_admin
6 | user = users :admin
7 | assert user.super_admin?
8 | end
9 |
10 | def test_first_name_is_blank
11 | user = users :admin
12 | user.first_name = nil
13 | assert_equal 'Smith', user.name
14 | end
15 |
16 | def test_last_name_is_blank
17 | user = users :admin
18 | user.last_name = nil
19 | assert_equal 'Adam', user.name
20 | end
21 |
22 | def test_as_json
23 | user = users :admin
24 |
25 | expected = {"email"=>"admin@example.com", "current_sign_in_at"=>nil, "last_name"=>"Smith", "first_name"=>"Adam"}
26 | assert_equal expected, user.as_json
27 | end
28 |
29 | end
30 |
--------------------------------------------------------------------------------
/chapter6-rails/test/services/addition_service_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class AdditonServiceTest < ActiveSupport::TestCase
4 |
5 | def test_addition
6 | service = AdditionService.new 5, 10
7 | assert_equal 15, service.process
8 | end
9 |
10 | end
11 |
--------------------------------------------------------------------------------
/chapter6/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "stage": 0
3 | }
4 |
--------------------------------------------------------------------------------
/chapter6/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "ecmaFeatures": {
3 | "jsx": true,
4 | "modules": true
5 | },
6 | "env": {
7 | "browser": true,
8 | "node": true
9 | },
10 | "parser": "babel-eslint",
11 | "rules": {
12 | "quotes": [2, "single"],
13 | "strict": [2, "never"],
14 | "react/jsx-uses-react": 2,
15 | "react/jsx-uses-vars": 2,
16 | "react/react-in-jsx-scope": 2
17 | },
18 | "plugins": [
19 | "react"
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/chapter6/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/chapter6/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "browser": true,
4 | "esnext": true,
5 | "newcap": false
6 | }
7 |
--------------------------------------------------------------------------------
/chapter6/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Vipul A M
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/chapter6/README.md:
--------------------------------------------------------------------------------
1 | react-forms
2 | ===========
3 |
4 | Examples of Forms in ReactJS
5 |
6 | ### Usage
7 |
8 | ```
9 | npm install
10 | npm start
11 | open http://localhost:9000
12 | ```
13 |
14 |
--------------------------------------------------------------------------------
/chapter6/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | React Forms
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/chapter6/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-forms",
3 | "version": "0.0.1",
4 | "description": "ReactJS forms example",
5 | "scripts": {
6 | "start": "node server.js",
7 | "lint": "eslint src"
8 | },
9 | "author": "Vipul A M (http://github.com/vipulnsward)",
10 | "license": "MIT",
11 | "homepage": "https://github.com/bigbinary/reactjs-by-example",
12 | "devDependencies": {
13 | "babel-core": "^5.4.7",
14 | "babel-eslint": "^3.1.9",
15 | "babel-loader": "^5.1.2",
16 | "css-loader": "^0.15.5",
17 | "eslint-plugin-react": "^2.3.0",
18 | "file-loader": "^0.8.4",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.8.2"
23 | },
24 | "dependencies": {
25 | "bootstrap-webpack": "0.0.3",
26 | "font-awesome-webpack": "0.0.3",
27 | "react": "^0.13.3",
28 | "url-loader": "^0.5.6",
29 | "whatwg-fetch": "^0.9.0"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/chapter6/server.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var WebpackDevServer = require('webpack-dev-server');
3 | var config = require('./webpack.config');
4 |
5 | new WebpackDevServer(webpack(config), {
6 | publicPath: config.output.publicPath,
7 | hot: true,
8 | historyApiFallback: true
9 | }).listen(9000, 'localhost', function (err, result) {
10 | if (err) {
11 | console.log(err);
12 | }
13 |
14 | console.log('Listening at localhost:9000');
15 | });
16 |
--------------------------------------------------------------------------------
/chapter6/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import App from './App';
3 |
4 | React.render(, document.getElementById('rootElement'));
5 |
--------------------------------------------------------------------------------
/chapter7/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "stage": 0
3 | }
4 |
--------------------------------------------------------------------------------
/chapter7/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/chapter7/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "browser": true,
4 | "esnext": true,
5 | "newcap": false
6 | }
7 |
--------------------------------------------------------------------------------
/chapter7/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Vipul A M
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/chapter7/README.md:
--------------------------------------------------------------------------------
1 | react-addons
2 | ===========
3 |
4 | Examples of React addons
5 |
6 | ### Usage
7 |
8 | ```
9 | npm install
10 | npm start
11 | open http://localhost:9000
12 | npm test
13 | ```
14 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/.bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bootstrap",
3 | "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.",
4 | "keywords": [
5 | "css",
6 | "js",
7 | "less",
8 | "mobile-first",
9 | "responsive",
10 | "front-end",
11 | "framework",
12 | "web"
13 | ],
14 | "homepage": "http://getbootstrap.com",
15 | "license": "MIT",
16 | "moduleType": "globals",
17 | "main": [
18 | "less/bootstrap.less",
19 | "dist/js/bootstrap.js"
20 | ],
21 | "ignore": [
22 | "/.*",
23 | "_config.yml",
24 | "CNAME",
25 | "composer.json",
26 | "CONTRIBUTING.md",
27 | "docs",
28 | "js/tests",
29 | "test-infra"
30 | ],
31 | "dependencies": {
32 | "jquery": ">= 1.9.1"
33 | },
34 | "version": "3.3.5",
35 | "_release": "3.3.5",
36 | "_resolution": {
37 | "type": "version",
38 | "tag": "v3.3.5",
39 | "commit": "16b48259a62f576e52c903c476bd42b90ab22482"
40 | },
41 | "_source": "git://github.com/twbs/bootstrap.git",
42 | "_target": "~3.3.5",
43 | "_originalSource": "bootstrap",
44 | "_direct": true
45 | }
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2011-2015 Twitter, Inc
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bootstrap",
3 | "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.",
4 | "keywords": [
5 | "css",
6 | "js",
7 | "less",
8 | "mobile-first",
9 | "responsive",
10 | "front-end",
11 | "framework",
12 | "web"
13 | ],
14 | "homepage": "http://getbootstrap.com",
15 | "license": "MIT",
16 | "moduleType": "globals",
17 | "main": [
18 | "less/bootstrap.less",
19 | "dist/js/bootstrap.js"
20 | ],
21 | "ignore": [
22 | "/.*",
23 | "_config.yml",
24 | "CNAME",
25 | "composer.json",
26 | "CONTRIBUTING.md",
27 | "docs",
28 | "js/tests",
29 | "test-infra"
30 | ],
31 | "dependencies": {
32 | "jquery": ">= 1.9.1"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neerajsingh0101/reactjs-by-example/0fb831f9add41f51480f468cdd7fcf9318161b65/chapter7/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neerajsingh0101/reactjs-by-example/0fb831f9add41f51480f468cdd7fcf9318161b65/chapter7/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neerajsingh0101/reactjs-by-example/0fb831f9add41f51480f468cdd7fcf9318161b65/chapter7/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neerajsingh0101/reactjs-by-example/0fb831f9add41f51480f468cdd7fcf9318161b65/chapter7/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/dist/js/npm.js:
--------------------------------------------------------------------------------
1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
2 | require('../../js/transition.js')
3 | require('../../js/alert.js')
4 | require('../../js/button.js')
5 | require('../../js/carousel.js')
6 | require('../../js/collapse.js')
7 | require('../../js/dropdown.js')
8 | require('../../js/modal.js')
9 | require('../../js/tooltip.js')
10 | require('../../js/popover.js')
11 | require('../../js/scrollspy.js')
12 | require('../../js/tab.js')
13 | require('../../js/affix.js')
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neerajsingh0101/reactjs-by-example/0fb831f9add41f51480f468cdd7fcf9318161b65/chapter7/bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neerajsingh0101/reactjs-by-example/0fb831f9add41f51480f468cdd7fcf9318161b65/chapter7/bower_components/bootstrap/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neerajsingh0101/reactjs-by-example/0fb831f9add41f51480f468cdd7fcf9318161b65/chapter7/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/neerajsingh0101/reactjs-by-example/0fb831f9add41f51480f468cdd7fcf9318161b65/chapter7/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/grunt/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends" : "../js/.jshintrc",
3 | "asi" : false,
4 | "browser" : false,
5 | "es3" : false,
6 | "node" : true
7 | }
8 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/grunt/bs-commonjs-generator.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Grunt task for the CommonJS module generation
3 | * http://getbootstrap.com
4 | * Copyright 2014-2015 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6 | */
7 |
8 | 'use strict';
9 |
10 | var fs = require('fs');
11 | var path = require('path');
12 |
13 | var COMMONJS_BANNER = '// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.\n';
14 |
15 | module.exports = function generateCommonJSModule(grunt, srcFiles, destFilepath) {
16 | var destDir = path.dirname(destFilepath);
17 |
18 | function srcPathToDestRequire(srcFilepath) {
19 | var requirePath = path.relative(destDir, srcFilepath).replace(/\\/g, '/');
20 | return 'require(\'' + requirePath + '\')';
21 | }
22 |
23 | var moduleOutputJs = COMMONJS_BANNER + srcFiles.map(srcPathToDestRequire).join('\n');
24 | try {
25 | fs.writeFileSync(destFilepath, moduleOutputJs);
26 | } catch (err) {
27 | grunt.fail.warn(err);
28 | }
29 | grunt.log.writeln('File ' + destFilepath.cyan + ' created.');
30 | };
31 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/js/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "asi" : true,
3 | "browser" : true,
4 | "eqeqeq" : false,
5 | "eqnull" : true,
6 | "es3" : true,
7 | "expr" : true,
8 | "jquery" : true,
9 | "latedef" : true,
10 | "laxbreak" : true,
11 | "nonbsp" : true,
12 | "strict" : true,
13 | "undef" : true,
14 | "unused" : true
15 | }
16 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/.csslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "adjoining-classes": false,
3 | "box-sizing": false,
4 | "box-model": false,
5 | "compatible-vendor-prefixes": false,
6 | "floats": false,
7 | "font-sizes": false,
8 | "gradients": false,
9 | "important": false,
10 | "known-properties": false,
11 | "outline-none": false,
12 | "qualified-headings": false,
13 | "regex-selectors": false,
14 | "shorthand": false,
15 | "text-indent": false,
16 | "unique-headings": false,
17 | "universal-selector": false,
18 | "unqualified-attributes": false
19 | }
20 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/breadcrumbs.less:
--------------------------------------------------------------------------------
1 | //
2 | // Breadcrumbs
3 | // --------------------------------------------------
4 |
5 |
6 | .breadcrumb {
7 | padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;
8 | margin-bottom: @line-height-computed;
9 | list-style: none;
10 | background-color: @breadcrumb-bg;
11 | border-radius: @border-radius-base;
12 |
13 | > li {
14 | display: inline-block;
15 |
16 | + li:before {
17 | content: "@{breadcrumb-separator}\00a0"; // Unicode space added since inline-block means non-collapsing white-space
18 | padding: 0 5px;
19 | color: @breadcrumb-color;
20 | }
21 | }
22 |
23 | > .active {
24 | color: @breadcrumb-active-color;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/close.less:
--------------------------------------------------------------------------------
1 | //
2 | // Close icons
3 | // --------------------------------------------------
4 |
5 |
6 | .close {
7 | float: right;
8 | font-size: (@font-size-base * 1.5);
9 | font-weight: @close-font-weight;
10 | line-height: 1;
11 | color: @close-color;
12 | text-shadow: @close-text-shadow;
13 | .opacity(.2);
14 |
15 | &:hover,
16 | &:focus {
17 | color: @close-color;
18 | text-decoration: none;
19 | cursor: pointer;
20 | .opacity(.5);
21 | }
22 |
23 | // Additional properties for button version
24 | // iOS requires the button element instead of an anchor tag.
25 | // If you want the anchor version, it requires `href="#"`.
26 | // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile
27 | button& {
28 | padding: 0;
29 | cursor: pointer;
30 | background: transparent;
31 | border: 0;
32 | -webkit-appearance: none;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/component-animations.less:
--------------------------------------------------------------------------------
1 | //
2 | // Component animations
3 | // --------------------------------------------------
4 |
5 | // Heads up!
6 | //
7 | // We don't use the `.opacity()` mixin here since it causes a bug with text
8 | // fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552.
9 |
10 | .fade {
11 | opacity: 0;
12 | .transition(opacity .15s linear);
13 | &.in {
14 | opacity: 1;
15 | }
16 | }
17 |
18 | .collapse {
19 | display: none;
20 |
21 | &.in { display: block; }
22 | tr&.in { display: table-row; }
23 | tbody&.in { display: table-row-group; }
24 | }
25 |
26 | .collapsing {
27 | position: relative;
28 | height: 0;
29 | overflow: hidden;
30 | .transition-property(~"height, visibility");
31 | .transition-duration(.35s);
32 | .transition-timing-function(ease);
33 | }
34 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/media.less:
--------------------------------------------------------------------------------
1 | .media {
2 | // Proper spacing between instances of .media
3 | margin-top: 15px;
4 |
5 | &:first-child {
6 | margin-top: 0;
7 | }
8 | }
9 |
10 | .media,
11 | .media-body {
12 | zoom: 1;
13 | overflow: hidden;
14 | }
15 |
16 | .media-body {
17 | width: 10000px;
18 | }
19 |
20 | .media-object {
21 | display: block;
22 |
23 | // Fix collapse in webkit from max-width: 100% and display: table-cell.
24 | &.img-thumbnail {
25 | max-width: none;
26 | }
27 | }
28 |
29 | .media-right,
30 | .media > .pull-right {
31 | padding-left: 10px;
32 | }
33 |
34 | .media-left,
35 | .media > .pull-left {
36 | padding-right: 10px;
37 | }
38 |
39 | .media-left,
40 | .media-right,
41 | .media-body {
42 | display: table-cell;
43 | vertical-align: top;
44 | }
45 |
46 | .media-middle {
47 | vertical-align: middle;
48 | }
49 |
50 | .media-bottom {
51 | vertical-align: bottom;
52 | }
53 |
54 | // Reset margins on headings for tighter default spacing
55 | .media-heading {
56 | margin-top: 0;
57 | margin-bottom: 5px;
58 | }
59 |
60 | // Media list variation
61 | //
62 | // Undo default ul/ol styles
63 | .media-list {
64 | padding-left: 0;
65 | list-style: none;
66 | }
67 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/alerts.less:
--------------------------------------------------------------------------------
1 | // Alerts
2 |
3 | .alert-variant(@background; @border; @text-color) {
4 | background-color: @background;
5 | border-color: @border;
6 | color: @text-color;
7 |
8 | hr {
9 | border-top-color: darken(@border, 5%);
10 | }
11 | .alert-link {
12 | color: darken(@text-color, 10%);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/background-variant.less:
--------------------------------------------------------------------------------
1 | // Contextual backgrounds
2 |
3 | .bg-variant(@color) {
4 | background-color: @color;
5 | a&:hover,
6 | a&:focus {
7 | background-color: darken(@color, 10%);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/border-radius.less:
--------------------------------------------------------------------------------
1 | // Single side border-radius
2 |
3 | .border-top-radius(@radius) {
4 | border-top-right-radius: @radius;
5 | border-top-left-radius: @radius;
6 | }
7 | .border-right-radius(@radius) {
8 | border-bottom-right-radius: @radius;
9 | border-top-right-radius: @radius;
10 | }
11 | .border-bottom-radius(@radius) {
12 | border-bottom-right-radius: @radius;
13 | border-bottom-left-radius: @radius;
14 | }
15 | .border-left-radius(@radius) {
16 | border-bottom-left-radius: @radius;
17 | border-top-left-radius: @radius;
18 | }
19 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/center-block.less:
--------------------------------------------------------------------------------
1 | // Center-align a block level element
2 |
3 | .center-block() {
4 | display: block;
5 | margin-left: auto;
6 | margin-right: auto;
7 | }
8 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/clearfix.less:
--------------------------------------------------------------------------------
1 | // Clearfix
2 | //
3 | // For modern browsers
4 | // 1. The space content is one way to avoid an Opera bug when the
5 | // contenteditable attribute is included anywhere else in the document.
6 | // Otherwise it causes space to appear at the top and bottom of elements
7 | // that are clearfixed.
8 | // 2. The use of `table` rather than `block` is only necessary if using
9 | // `:before` to contain the top-margins of child elements.
10 | //
11 | // Source: http://nicolasgallagher.com/micro-clearfix-hack/
12 |
13 | .clearfix() {
14 | &:before,
15 | &:after {
16 | content: " "; // 1
17 | display: table; // 2
18 | }
19 | &:after {
20 | clear: both;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/hide-text.less:
--------------------------------------------------------------------------------
1 | // CSS image replacement
2 | //
3 | // Heads up! v3 launched with only `.hide-text()`, but per our pattern for
4 | // mixins being reused as classes with the same name, this doesn't hold up. As
5 | // of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`.
6 | //
7 | // Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757
8 |
9 | // Deprecated as of v3.0.1 (will be removed in v4)
10 | .hide-text() {
11 | font: ~"0/0" a;
12 | color: transparent;
13 | text-shadow: none;
14 | background-color: transparent;
15 | border: 0;
16 | }
17 |
18 | // New mixin to use as of v3.0.1
19 | .text-hide() {
20 | .hide-text();
21 | }
22 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/image.less:
--------------------------------------------------------------------------------
1 | // Image Mixins
2 | // - Responsive image
3 | // - Retina image
4 |
5 |
6 | // Responsive image
7 | //
8 | // Keep images from scaling beyond the width of their parents.
9 | .img-responsive(@display: block) {
10 | display: @display;
11 | max-width: 100%; // Part 1: Set a maximum relative to the parent
12 | height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching
13 | }
14 |
15 |
16 | // Retina image
17 | //
18 | // Short retina mixin for setting background-image and -size. Note that the
19 | // spelling of `min--moz-device-pixel-ratio` is intentional.
20 | .img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {
21 | background-image: url("@{file-1x}");
22 |
23 | @media
24 | only screen and (-webkit-min-device-pixel-ratio: 2),
25 | only screen and ( min--moz-device-pixel-ratio: 2),
26 | only screen and ( -o-min-device-pixel-ratio: 2/1),
27 | only screen and ( min-device-pixel-ratio: 2),
28 | only screen and ( min-resolution: 192dpi),
29 | only screen and ( min-resolution: 2dppx) {
30 | background-image: url("@{file-2x}");
31 | background-size: @width-1x @height-1x;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/labels.less:
--------------------------------------------------------------------------------
1 | // Labels
2 |
3 | .label-variant(@color) {
4 | background-color: @color;
5 |
6 | &[href] {
7 | &:hover,
8 | &:focus {
9 | background-color: darken(@color, 10%);
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/list-group.less:
--------------------------------------------------------------------------------
1 | // List Groups
2 |
3 | .list-group-item-variant(@state; @background; @color) {
4 | .list-group-item-@{state} {
5 | color: @color;
6 | background-color: @background;
7 |
8 | a&,
9 | button& {
10 | color: @color;
11 |
12 | .list-group-item-heading {
13 | color: inherit;
14 | }
15 |
16 | &:hover,
17 | &:focus {
18 | color: @color;
19 | background-color: darken(@background, 5%);
20 | }
21 | &.active,
22 | &.active:hover,
23 | &.active:focus {
24 | color: #fff;
25 | background-color: @color;
26 | border-color: @color;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/nav-divider.less:
--------------------------------------------------------------------------------
1 | // Horizontal dividers
2 | //
3 | // Dividers (basically an hr) within dropdowns and nav lists
4 |
5 | .nav-divider(@color: #e5e5e5) {
6 | height: 1px;
7 | margin: ((@line-height-computed / 2) - 1) 0;
8 | overflow: hidden;
9 | background-color: @color;
10 | }
11 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/nav-vertical-align.less:
--------------------------------------------------------------------------------
1 | // Navbar vertical align
2 | //
3 | // Vertically center elements in the navbar.
4 | // Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.
5 |
6 | .navbar-vertical-align(@element-height) {
7 | margin-top: ((@navbar-height - @element-height) / 2);
8 | margin-bottom: ((@navbar-height - @element-height) / 2);
9 | }
10 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/opacity.less:
--------------------------------------------------------------------------------
1 | // Opacity
2 |
3 | .opacity(@opacity) {
4 | opacity: @opacity;
5 | // IE8 filter
6 | @opacity-ie: (@opacity * 100);
7 | filter: ~"alpha(opacity=@{opacity-ie})";
8 | }
9 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/pagination.less:
--------------------------------------------------------------------------------
1 | // Pagination
2 |
3 | .pagination-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {
4 | > li {
5 | > a,
6 | > span {
7 | padding: @padding-vertical @padding-horizontal;
8 | font-size: @font-size;
9 | line-height: @line-height;
10 | }
11 | &:first-child {
12 | > a,
13 | > span {
14 | .border-left-radius(@border-radius);
15 | }
16 | }
17 | &:last-child {
18 | > a,
19 | > span {
20 | .border-right-radius(@border-radius);
21 | }
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/panels.less:
--------------------------------------------------------------------------------
1 | // Panels
2 |
3 | .panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border) {
4 | border-color: @border;
5 |
6 | & > .panel-heading {
7 | color: @heading-text-color;
8 | background-color: @heading-bg-color;
9 | border-color: @heading-border;
10 |
11 | + .panel-collapse > .panel-body {
12 | border-top-color: @border;
13 | }
14 | .badge {
15 | color: @heading-bg-color;
16 | background-color: @heading-text-color;
17 | }
18 | }
19 | & > .panel-footer {
20 | + .panel-collapse > .panel-body {
21 | border-bottom-color: @border;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/progress-bar.less:
--------------------------------------------------------------------------------
1 | // Progress bars
2 |
3 | .progress-bar-variant(@color) {
4 | background-color: @color;
5 |
6 | // Deprecated parent class requirement as of v3.2.0
7 | .progress-striped & {
8 | #gradient > .striped();
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/reset-filter.less:
--------------------------------------------------------------------------------
1 | // Reset filters for IE
2 | //
3 | // When you need to remove a gradient background, do not forget to use this to reset
4 | // the IE filter for IE9 and below.
5 |
6 | .reset-filter() {
7 | filter: e(%("progid:DXImageTransform.Microsoft.gradient(enabled = false)"));
8 | }
9 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/reset-text.less:
--------------------------------------------------------------------------------
1 | .reset-text() {
2 | font-family: @font-family-base;
3 | // We deliberately do NOT reset font-size.
4 | font-style: normal;
5 | font-weight: normal;
6 | letter-spacing: normal;
7 | line-break: auto;
8 | line-height: @line-height-base;
9 | text-align: left; // Fallback for where `start` is not supported
10 | text-align: start;
11 | text-decoration: none;
12 | text-shadow: none;
13 | text-transform: none;
14 | white-space: normal;
15 | word-break: normal;
16 | word-spacing: normal;
17 | word-wrap: normal;
18 | }
19 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/resize.less:
--------------------------------------------------------------------------------
1 | // Resize anything
2 |
3 | .resizable(@direction) {
4 | resize: @direction; // Options: horizontal, vertical, both
5 | overflow: auto; // Per CSS3 UI, `resize` only applies when `overflow` isn't `visible`
6 | }
7 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/responsive-visibility.less:
--------------------------------------------------------------------------------
1 | // Responsive utilities
2 |
3 | //
4 | // More easily include all the states for responsive-utilities.less.
5 | .responsive-visibility() {
6 | display: block !important;
7 | table& { display: table !important; }
8 | tr& { display: table-row !important; }
9 | th&,
10 | td& { display: table-cell !important; }
11 | }
12 |
13 | .responsive-invisibility() {
14 | display: none !important;
15 | }
16 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/size.less:
--------------------------------------------------------------------------------
1 | // Sizing shortcuts
2 |
3 | .size(@width; @height) {
4 | width: @width;
5 | height: @height;
6 | }
7 |
8 | .square(@size) {
9 | .size(@size; @size);
10 | }
11 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/tab-focus.less:
--------------------------------------------------------------------------------
1 | // WebKit-style focus
2 |
3 | .tab-focus() {
4 | // Default
5 | outline: thin dotted;
6 | // WebKit
7 | outline: 5px auto -webkit-focus-ring-color;
8 | outline-offset: -2px;
9 | }
10 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/table-row.less:
--------------------------------------------------------------------------------
1 | // Tables
2 |
3 | .table-row-variant(@state; @background) {
4 | // Exact selectors below required to override `.table-striped` and prevent
5 | // inheritance to nested tables.
6 | .table > thead > tr,
7 | .table > tbody > tr,
8 | .table > tfoot > tr {
9 | > td.@{state},
10 | > th.@{state},
11 | &.@{state} > td,
12 | &.@{state} > th {
13 | background-color: @background;
14 | }
15 | }
16 |
17 | // Hover states for `.table-hover`
18 | // Note: this is not available for cells or rows within `thead` or `tfoot`.
19 | .table-hover > tbody > tr {
20 | > td.@{state}:hover,
21 | > th.@{state}:hover,
22 | &.@{state}:hover > td,
23 | &:hover > .@{state},
24 | &.@{state}:hover > th {
25 | background-color: darken(@background, 5%);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/text-emphasis.less:
--------------------------------------------------------------------------------
1 | // Typography
2 |
3 | .text-emphasis-variant(@color) {
4 | color: @color;
5 | a&:hover,
6 | a&:focus {
7 | color: darken(@color, 10%);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/mixins/text-overflow.less:
--------------------------------------------------------------------------------
1 | // Text overflow
2 | // Requires inline-block or block for proper styling
3 |
4 | .text-overflow() {
5 | overflow: hidden;
6 | text-overflow: ellipsis;
7 | white-space: nowrap;
8 | }
9 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/pager.less:
--------------------------------------------------------------------------------
1 | //
2 | // Pager pagination
3 | // --------------------------------------------------
4 |
5 |
6 | .pager {
7 | padding-left: 0;
8 | margin: @line-height-computed 0;
9 | list-style: none;
10 | text-align: center;
11 | &:extend(.clearfix all);
12 | li {
13 | display: inline;
14 | > a,
15 | > span {
16 | display: inline-block;
17 | padding: 5px 14px;
18 | background-color: @pager-bg;
19 | border: 1px solid @pager-border;
20 | border-radius: @pager-border-radius;
21 | }
22 |
23 | > a:hover,
24 | > a:focus {
25 | text-decoration: none;
26 | background-color: @pager-hover-bg;
27 | }
28 | }
29 |
30 | .next {
31 | > a,
32 | > span {
33 | float: right;
34 | }
35 | }
36 |
37 | .previous {
38 | > a,
39 | > span {
40 | float: left;
41 | }
42 | }
43 |
44 | .disabled {
45 | > a,
46 | > a:hover,
47 | > a:focus,
48 | > span {
49 | color: @pager-disabled-color;
50 | background-color: @pager-bg;
51 | cursor: @cursor-disabled;
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/responsive-embed.less:
--------------------------------------------------------------------------------
1 | // Embeds responsive
2 | //
3 | // Credit: Nicolas Gallagher and SUIT CSS.
4 |
5 | .embed-responsive {
6 | position: relative;
7 | display: block;
8 | height: 0;
9 | padding: 0;
10 | overflow: hidden;
11 |
12 | .embed-responsive-item,
13 | iframe,
14 | embed,
15 | object,
16 | video {
17 | position: absolute;
18 | top: 0;
19 | left: 0;
20 | bottom: 0;
21 | height: 100%;
22 | width: 100%;
23 | border: 0;
24 | }
25 | }
26 |
27 | // Modifier class for 16:9 aspect ratio
28 | .embed-responsive-16by9 {
29 | padding-bottom: 56.25%;
30 | }
31 |
32 | // Modifier class for 4:3 aspect ratio
33 | .embed-responsive-4by3 {
34 | padding-bottom: 75%;
35 | }
36 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/thumbnails.less:
--------------------------------------------------------------------------------
1 | //
2 | // Thumbnails
3 | // --------------------------------------------------
4 |
5 |
6 | // Mixin and adjust the regular image class
7 | .thumbnail {
8 | display: block;
9 | padding: @thumbnail-padding;
10 | margin-bottom: @line-height-computed;
11 | line-height: @line-height-base;
12 | background-color: @thumbnail-bg;
13 | border: 1px solid @thumbnail-border;
14 | border-radius: @thumbnail-border-radius;
15 | .transition(border .2s ease-in-out);
16 |
17 | > img,
18 | a > img {
19 | &:extend(.img-responsive);
20 | margin-left: auto;
21 | margin-right: auto;
22 | }
23 |
24 | // Add a hover state for linked versions only
25 | a&:hover,
26 | a&:focus,
27 | a&.active {
28 | border-color: @link-color;
29 | }
30 |
31 | // Image captions
32 | .caption {
33 | padding: @thumbnail-caption-padding;
34 | color: @thumbnail-caption-color;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/utilities.less:
--------------------------------------------------------------------------------
1 | //
2 | // Utility classes
3 | // --------------------------------------------------
4 |
5 |
6 | // Floats
7 | // -------------------------
8 |
9 | .clearfix {
10 | .clearfix();
11 | }
12 | .center-block {
13 | .center-block();
14 | }
15 | .pull-right {
16 | float: right !important;
17 | }
18 | .pull-left {
19 | float: left !important;
20 | }
21 |
22 |
23 | // Toggling content
24 | // -------------------------
25 |
26 | // Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1
27 | .hide {
28 | display: none !important;
29 | }
30 | .show {
31 | display: block !important;
32 | }
33 | .invisible {
34 | visibility: hidden;
35 | }
36 | .text-hide {
37 | .text-hide();
38 | }
39 |
40 |
41 | // Hide from screenreaders and browsers
42 | //
43 | // Credit: HTML5 Boilerplate
44 |
45 | .hidden {
46 | display: none !important;
47 | }
48 |
49 |
50 | // For Affix plugin
51 | // -------------------------
52 |
53 | .affix {
54 | position: fixed;
55 | }
56 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/less/wells.less:
--------------------------------------------------------------------------------
1 | //
2 | // Wells
3 | // --------------------------------------------------
4 |
5 |
6 | // Base class
7 | .well {
8 | min-height: 20px;
9 | padding: 19px;
10 | margin-bottom: 20px;
11 | background-color: @well-bg;
12 | border: 1px solid @well-border;
13 | border-radius: @border-radius-base;
14 | .box-shadow(inset 0 1px 1px rgba(0,0,0,.05));
15 | blockquote {
16 | border-color: #ddd;
17 | border-color: rgba(0,0,0,.15);
18 | }
19 | }
20 |
21 | // Sizes
22 | .well-lg {
23 | padding: 24px;
24 | border-radius: @border-radius-large;
25 | }
26 | .well-sm {
27 | padding: 9px;
28 | border-radius: @border-radius-small;
29 | }
30 |
--------------------------------------------------------------------------------
/chapter7/bower_components/bootstrap/package.js:
--------------------------------------------------------------------------------
1 | // package metadata file for Meteor.js
2 |
3 | /* jshint strict:false */
4 | /* global Package:true */
5 |
6 | Package.describe({
7 | name: 'twbs:bootstrap', // http://atmospherejs.com/twbs/bootstrap
8 | summary: 'The most popular front-end framework for developing responsive, mobile first projects on the web.',
9 | version: '3.3.5',
10 | git: 'https://github.com/twbs/bootstrap.git'
11 | });
12 |
13 | Package.onUse(function (api) {
14 | api.versionsFrom('METEOR@1.0');
15 | api.use('jquery', 'client');
16 | api.addFiles([
17 | 'dist/fonts/glyphicons-halflings-regular.eot',
18 | 'dist/fonts/glyphicons-halflings-regular.svg',
19 | 'dist/fonts/glyphicons-halflings-regular.ttf',
20 | 'dist/fonts/glyphicons-halflings-regular.woff',
21 | 'dist/fonts/glyphicons-halflings-regular.woff2',
22 | 'dist/css/bootstrap.css',
23 | 'dist/js/bootstrap.js'
24 | ], 'client');
25 | });
26 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/.bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jquery",
3 | "version": "2.1.4",
4 | "main": "dist/jquery.js",
5 | "license": "MIT",
6 | "ignore": [
7 | "**/.*",
8 | "build",
9 | "dist/cdn",
10 | "speed",
11 | "test",
12 | "*.md",
13 | "AUTHORS.txt",
14 | "Gruntfile.js",
15 | "package.json"
16 | ],
17 | "devDependencies": {
18 | "sizzle": "2.1.1-jquery.2.1.2",
19 | "requirejs": "2.1.10",
20 | "qunit": "1.14.0",
21 | "sinon": "1.8.1"
22 | },
23 | "keywords": [
24 | "jquery",
25 | "javascript",
26 | "library"
27 | ],
28 | "homepage": "https://github.com/jquery/jquery",
29 | "_release": "2.1.4",
30 | "_resolution": {
31 | "type": "version",
32 | "tag": "2.1.4",
33 | "commit": "7751e69b615c6eca6f783a81e292a55725af6b85"
34 | },
35 | "_source": "git://github.com/jquery/jquery.git",
36 | "_target": ">= 1.9.1",
37 | "_originalSource": "jquery"
38 | }
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/MIT-LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright 2014 jQuery Foundation and other contributors
2 | http://jquery.com/
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining
5 | a copy of this software and associated documentation files (the
6 | "Software"), to deal in the Software without restriction, including
7 | without limitation the rights to use, copy, modify, merge, publish,
8 | distribute, sublicense, and/or sell copies of the Software, and to
9 | permit persons to whom the Software is furnished to do so, subject to
10 | the following 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 OF
17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jquery",
3 | "version": "2.1.4",
4 | "main": "dist/jquery.js",
5 | "license": "MIT",
6 | "ignore": [
7 | "**/.*",
8 | "build",
9 | "dist/cdn",
10 | "speed",
11 | "test",
12 | "*.md",
13 | "AUTHORS.txt",
14 | "Gruntfile.js",
15 | "package.json"
16 | ],
17 | "devDependencies": {
18 | "sizzle": "2.1.1-jquery.2.1.2",
19 | "requirejs": "2.1.10",
20 | "qunit": "1.14.0",
21 | "sinon": "1.8.1"
22 | },
23 | "keywords": [
24 | "jquery",
25 | "javascript",
26 | "library"
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/ajax/parseJSON.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../core"
3 | ], function( jQuery ) {
4 |
5 | // Support: Android 2.3
6 | // Workaround failure to string-cast null input
7 | jQuery.parseJSON = function( data ) {
8 | return JSON.parse( data + "" );
9 | };
10 |
11 | return jQuery.parseJSON;
12 |
13 | });
14 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/ajax/parseXML.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../core"
3 | ], function( jQuery ) {
4 |
5 | // Cross-browser xml parsing
6 | jQuery.parseXML = function( data ) {
7 | var xml, tmp;
8 | if ( !data || typeof data !== "string" ) {
9 | return null;
10 | }
11 |
12 | // Support: IE9
13 | try {
14 | tmp = new DOMParser();
15 | xml = tmp.parseFromString( data, "text/xml" );
16 | } catch ( e ) {
17 | xml = undefined;
18 | }
19 |
20 | if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
21 | jQuery.error( "Invalid XML: " + data );
22 | }
23 | return xml;
24 | };
25 |
26 | return jQuery.parseXML;
27 |
28 | });
29 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/ajax/var/nonce.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../../core"
3 | ], function( jQuery ) {
4 | return jQuery.now();
5 | });
6 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/ajax/var/rquery.js:
--------------------------------------------------------------------------------
1 | define(function() {
2 | return (/\?/);
3 | });
4 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/attributes.js:
--------------------------------------------------------------------------------
1 | define([
2 | "./core",
3 | "./attributes/attr",
4 | "./attributes/prop",
5 | "./attributes/classes",
6 | "./attributes/val"
7 | ], function( jQuery ) {
8 |
9 | // Return jQuery for attributes-only inclusion
10 | return jQuery;
11 | });
12 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/attributes/support.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../var/support"
3 | ], function( support ) {
4 |
5 | (function() {
6 | var input = document.createElement( "input" ),
7 | select = document.createElement( "select" ),
8 | opt = select.appendChild( document.createElement( "option" ) );
9 |
10 | input.type = "checkbox";
11 |
12 | // Support: iOS<=5.1, Android<=4.2+
13 | // Default value for a checkbox should be "on"
14 | support.checkOn = input.value !== "";
15 |
16 | // Support: IE<=11+
17 | // Must access selectedIndex to make default options select
18 | support.optSelected = opt.selected;
19 |
20 | // Support: Android<=2.3
21 | // Options inside disabled selects are incorrectly marked as disabled
22 | select.disabled = true;
23 | support.optDisabled = !opt.disabled;
24 |
25 | // Support: IE<=11+
26 | // An input loses its value after becoming a radio
27 | input = document.createElement( "input" );
28 | input.value = "t";
29 | input.type = "radio";
30 | support.radioValue = input.value === "t";
31 | })();
32 |
33 | return support;
34 |
35 | });
36 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/core/parseHTML.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../core",
3 | "./var/rsingleTag",
4 | "../manipulation" // buildFragment
5 | ], function( jQuery, rsingleTag ) {
6 |
7 | // data: string of html
8 | // context (optional): If specified, the fragment will be created in this context, defaults to document
9 | // keepScripts (optional): If true, will include scripts passed in the html string
10 | jQuery.parseHTML = function( data, context, keepScripts ) {
11 | if ( !data || typeof data !== "string" ) {
12 | return null;
13 | }
14 | if ( typeof context === "boolean" ) {
15 | keepScripts = context;
16 | context = false;
17 | }
18 | context = context || document;
19 |
20 | var parsed = rsingleTag.exec( data ),
21 | scripts = !keepScripts && [];
22 |
23 | // Single tag
24 | if ( parsed ) {
25 | return [ context.createElement( parsed[1] ) ];
26 | }
27 |
28 | parsed = jQuery.buildFragment( [ data ], context, scripts );
29 |
30 | if ( scripts && scripts.length ) {
31 | jQuery( scripts ).remove();
32 | }
33 |
34 | return jQuery.merge( [], parsed.childNodes );
35 | };
36 |
37 | return jQuery.parseHTML;
38 |
39 | });
40 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/core/var/rsingleTag.js:
--------------------------------------------------------------------------------
1 | define(function() {
2 | // Match a standalone tag
3 | return (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
4 | });
5 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/css/addGetHookIf.js:
--------------------------------------------------------------------------------
1 | define(function() {
2 |
3 | function addGetHookIf( conditionFn, hookFn ) {
4 | // Define the hook, we'll check on the first run if it's really needed.
5 | return {
6 | get: function() {
7 | if ( conditionFn() ) {
8 | // Hook not needed (or it's not possible to use it due
9 | // to missing dependency), remove it.
10 | delete this.get;
11 | return;
12 | }
13 |
14 | // Hook needed; redefine it so that the support test is not executed again.
15 | return (this.get = hookFn).apply( this, arguments );
16 | }
17 | };
18 | }
19 |
20 | return addGetHookIf;
21 |
22 | });
23 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/css/hiddenVisibleSelectors.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../core",
3 | "../selector"
4 | ], function( jQuery ) {
5 |
6 | jQuery.expr.filters.hidden = function( elem ) {
7 | // Support: Opera <= 12.12
8 | // Opera reports offsetWidths and offsetHeights less than zero on some elements
9 | return elem.offsetWidth <= 0 && elem.offsetHeight <= 0;
10 | };
11 | jQuery.expr.filters.visible = function( elem ) {
12 | return !jQuery.expr.filters.hidden( elem );
13 | };
14 |
15 | });
16 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/css/swap.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../core"
3 | ], function( jQuery ) {
4 |
5 | // A method for quickly swapping in/out CSS properties to get correct calculations.
6 | jQuery.swap = function( elem, options, callback, args ) {
7 | var ret, name,
8 | old = {};
9 |
10 | // Remember the old values, and insert the new ones
11 | for ( name in options ) {
12 | old[ name ] = elem.style[ name ];
13 | elem.style[ name ] = options[ name ];
14 | }
15 |
16 | ret = callback.apply( elem, args || [] );
17 |
18 | // Revert the old values
19 | for ( name in options ) {
20 | elem.style[ name ] = old[ name ];
21 | }
22 |
23 | return ret;
24 | };
25 |
26 | return jQuery.swap;
27 |
28 | });
29 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/css/var/cssExpand.js:
--------------------------------------------------------------------------------
1 | define(function() {
2 | return [ "Top", "Right", "Bottom", "Left" ];
3 | });
4 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/css/var/getStyles.js:
--------------------------------------------------------------------------------
1 | define(function() {
2 | return function( elem ) {
3 | // Support: IE<=11+, Firefox<=30+ (#15098, #14150)
4 | // IE throws on elements created in popups
5 | // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
6 | if ( elem.ownerDocument.defaultView.opener ) {
7 | return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
8 | }
9 |
10 | return window.getComputedStyle( elem, null );
11 | };
12 | });
13 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/css/var/isHidden.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../../core",
3 | "../../selector"
4 | // css is assumed
5 | ], function( jQuery ) {
6 |
7 | return function( elem, el ) {
8 | // isHidden might be called from jQuery#filter function;
9 | // in that case, element will be second argument
10 | elem = el || elem;
11 | return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
12 | };
13 | });
14 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/css/var/rmargin.js:
--------------------------------------------------------------------------------
1 | define(function() {
2 | return (/^margin/);
3 | });
4 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/css/var/rnumnonpx.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../../var/pnum"
3 | ], function( pnum ) {
4 | return new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
5 | });
6 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/data/accepts.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../core"
3 | ], function( jQuery ) {
4 |
5 | /**
6 | * Determines whether an object can have data
7 | */
8 | jQuery.acceptData = function( owner ) {
9 | // Accepts only:
10 | // - Node
11 | // - Node.ELEMENT_NODE
12 | // - Node.DOCUMENT_NODE
13 | // - Object
14 | // - Any
15 | /* jshint -W018 */
16 | return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
17 | };
18 |
19 | return jQuery.acceptData;
20 | });
21 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/data/var/data_priv.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../Data"
3 | ], function( Data ) {
4 | return new Data();
5 | });
6 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/data/var/data_user.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../Data"
3 | ], function( Data ) {
4 | return new Data();
5 | });
6 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/deprecated.js:
--------------------------------------------------------------------------------
1 | define([
2 | "./core",
3 | "./traversing"
4 | ], function( jQuery ) {
5 |
6 | // The number of elements contained in the matched element set
7 | jQuery.fn.size = function() {
8 | return this.length;
9 | };
10 |
11 | jQuery.fn.andSelf = jQuery.fn.addBack;
12 |
13 | });
14 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/effects/animatedSelector.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../core",
3 | "../selector",
4 | "../effects"
5 | ], function( jQuery ) {
6 |
7 | jQuery.expr.filters.animated = function( elem ) {
8 | return jQuery.grep(jQuery.timers, function( fn ) {
9 | return elem === fn.elem;
10 | }).length;
11 | };
12 |
13 | });
14 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/event/ajax.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../core",
3 | "../event"
4 | ], function( jQuery ) {
5 |
6 | // Attach a bunch of functions for handling common AJAX events
7 | jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
8 | jQuery.fn[ type ] = function( fn ) {
9 | return this.on( type, fn );
10 | };
11 | });
12 |
13 | });
14 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/event/support.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../var/support"
3 | ], function( support ) {
4 |
5 | support.focusinBubbles = "onfocusin" in window;
6 |
7 | return support;
8 |
9 | });
10 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/exports/amd.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../core"
3 | ], function( jQuery ) {
4 |
5 | // Register as a named AMD module, since jQuery can be concatenated with other
6 | // files that may use define, but not via a proper concatenation script that
7 | // understands anonymous AMD modules. A named AMD is safest and most robust
8 | // way to register. Lowercase jquery is used because AMD module names are
9 | // derived from file names, and jQuery is normally delivered in a lowercase
10 | // file name. Do this after creating the global so that if an AMD module wants
11 | // to call noConflict to hide this version of jQuery, it will work.
12 |
13 | // Note that for maximum portability, libraries that are not jQuery should
14 | // declare themselves as anonymous modules, and avoid setting a global if an
15 | // AMD loader is present. jQuery is a special case. For more information, see
16 | // https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
17 |
18 | if ( typeof define === "function" && define.amd ) {
19 | define( "jquery", [], function() {
20 | return jQuery;
21 | });
22 | }
23 |
24 | });
25 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/exports/global.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../core",
3 | "../var/strundefined"
4 | ], function( jQuery, strundefined ) {
5 |
6 | var
7 | // Map over jQuery in case of overwrite
8 | _jQuery = window.jQuery,
9 |
10 | // Map over the $ in case of overwrite
11 | _$ = window.$;
12 |
13 | jQuery.noConflict = function( deep ) {
14 | if ( window.$ === jQuery ) {
15 | window.$ = _$;
16 | }
17 |
18 | if ( deep && window.jQuery === jQuery ) {
19 | window.jQuery = _jQuery;
20 | }
21 |
22 | return jQuery;
23 | };
24 |
25 | // Expose jQuery and $ identifiers, even in AMD
26 | // (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
27 | // and CommonJS for browser emulators (#13566)
28 | if ( typeof noGlobal === strundefined ) {
29 | window.jQuery = window.$ = jQuery;
30 | }
31 |
32 | });
33 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/jquery.js:
--------------------------------------------------------------------------------
1 | define([
2 | "./core",
3 | "./selector",
4 | "./traversing",
5 | "./callbacks",
6 | "./deferred",
7 | "./core/ready",
8 | "./data",
9 | "./queue",
10 | "./queue/delay",
11 | "./attributes",
12 | "./event",
13 | "./event/alias",
14 | "./manipulation",
15 | "./manipulation/_evalUrl",
16 | "./wrap",
17 | "./css",
18 | "./css/hiddenVisibleSelectors",
19 | "./serialize",
20 | "./ajax",
21 | "./ajax/xhr",
22 | "./ajax/script",
23 | "./ajax/jsonp",
24 | "./ajax/load",
25 | "./event/ajax",
26 | "./effects",
27 | "./effects/animatedSelector",
28 | "./offset",
29 | "./dimensions",
30 | "./deprecated",
31 | "./exports/amd",
32 | "./exports/global"
33 | ], function( jQuery ) {
34 |
35 | return jQuery;
36 |
37 | });
38 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/manipulation/_evalUrl.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../ajax"
3 | ], function( jQuery ) {
4 |
5 | jQuery._evalUrl = function( url ) {
6 | return jQuery.ajax({
7 | url: url,
8 | type: "GET",
9 | dataType: "script",
10 | async: false,
11 | global: false,
12 | "throws": true
13 | });
14 | };
15 |
16 | return jQuery._evalUrl;
17 |
18 | });
19 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/manipulation/support.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../var/support"
3 | ], function( support ) {
4 |
5 | (function() {
6 | var fragment = document.createDocumentFragment(),
7 | div = fragment.appendChild( document.createElement( "div" ) ),
8 | input = document.createElement( "input" );
9 |
10 | // Support: Safari<=5.1
11 | // Check state lost if the name is set (#11217)
12 | // Support: Windows Web Apps (WWA)
13 | // `name` and `type` must use .setAttribute for WWA (#14901)
14 | input.setAttribute( "type", "radio" );
15 | input.setAttribute( "checked", "checked" );
16 | input.setAttribute( "name", "t" );
17 |
18 | div.appendChild( input );
19 |
20 | // Support: Safari<=5.1, Android<4.2
21 | // Older WebKit doesn't clone checked state correctly in fragments
22 | support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
23 |
24 | // Support: IE<=11+
25 | // Make sure textarea (and checkbox) defaultValue is properly cloned
26 | div.innerHTML = "";
27 | support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
28 | })();
29 |
30 | return support;
31 |
32 | });
33 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/manipulation/var/rcheckableType.js:
--------------------------------------------------------------------------------
1 | define(function() {
2 | return (/^(?:checkbox|radio)$/i);
3 | });
4 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/outro.js:
--------------------------------------------------------------------------------
1 | }));
2 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/queue/delay.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../core",
3 | "../queue",
4 | "../effects" // Delay is optional because of this dependency
5 | ], function( jQuery ) {
6 |
7 | // Based off of the plugin by Clint Helfers, with permission.
8 | // http://blindsignals.com/index.php/2009/07/jquery-delay/
9 | jQuery.fn.delay = function( time, type ) {
10 | time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
11 | type = type || "fx";
12 |
13 | return this.queue( type, function( next, hooks ) {
14 | var timeout = setTimeout( next, time );
15 | hooks.stop = function() {
16 | clearTimeout( timeout );
17 | };
18 | });
19 | };
20 |
21 | return jQuery.fn.delay;
22 | });
23 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/selector-sizzle.js:
--------------------------------------------------------------------------------
1 | define([
2 | "./core",
3 | "sizzle"
4 | ], function( jQuery, Sizzle ) {
5 |
6 | jQuery.find = Sizzle;
7 | jQuery.expr = Sizzle.selectors;
8 | jQuery.expr[":"] = jQuery.expr.pseudos;
9 | jQuery.unique = Sizzle.uniqueSort;
10 | jQuery.text = Sizzle.getText;
11 | jQuery.isXMLDoc = Sizzle.isXML;
12 | jQuery.contains = Sizzle.contains;
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/selector.js:
--------------------------------------------------------------------------------
1 | define([ "./selector-sizzle" ]);
2 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/traversing/var/rneedsContext.js:
--------------------------------------------------------------------------------
1 | define([
2 | "../../core",
3 | "../../selector"
4 | ], function( jQuery ) {
5 | return jQuery.expr.match.needsContext;
6 | });
7 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/var/arr.js:
--------------------------------------------------------------------------------
1 | define(function() {
2 | return [];
3 | });
4 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/var/class2type.js:
--------------------------------------------------------------------------------
1 | define(function() {
2 | // [[Class]] -> type pairs
3 | return {};
4 | });
5 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/var/concat.js:
--------------------------------------------------------------------------------
1 | define([
2 | "./arr"
3 | ], function( arr ) {
4 | return arr.concat;
5 | });
6 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/var/hasOwn.js:
--------------------------------------------------------------------------------
1 | define([
2 | "./class2type"
3 | ], function( class2type ) {
4 | return class2type.hasOwnProperty;
5 | });
6 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/var/indexOf.js:
--------------------------------------------------------------------------------
1 | define([
2 | "./arr"
3 | ], function( arr ) {
4 | return arr.indexOf;
5 | });
6 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/var/pnum.js:
--------------------------------------------------------------------------------
1 | define(function() {
2 | return (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
3 | });
4 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/var/push.js:
--------------------------------------------------------------------------------
1 | define([
2 | "./arr"
3 | ], function( arr ) {
4 | return arr.push;
5 | });
6 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/var/rnotwhite.js:
--------------------------------------------------------------------------------
1 | define(function() {
2 | return (/\S+/g);
3 | });
4 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/var/slice.js:
--------------------------------------------------------------------------------
1 | define([
2 | "./arr"
3 | ], function( arr ) {
4 | return arr.slice;
5 | });
6 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/var/strundefined.js:
--------------------------------------------------------------------------------
1 | define(function() {
2 | return typeof undefined;
3 | });
4 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/var/support.js:
--------------------------------------------------------------------------------
1 | define(function() {
2 | // All support tests are defined in their respective modules.
3 | return {};
4 | });
5 |
--------------------------------------------------------------------------------
/chapter7/bower_components/jquery/src/var/toString.js:
--------------------------------------------------------------------------------
1 | define([
2 | "./class2type"
3 | ], function( class2type ) {
4 | return class2type.toString;
5 | });
6 |
--------------------------------------------------------------------------------
/chapter7/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | React Addons
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/chapter7/server.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var WebpackDevServer = require('webpack-dev-server');
3 | var config = require('./webpack.config');
4 |
5 | new WebpackDevServer(webpack(config), {
6 | publicPath: config.output.publicPath,
7 | hot: true,
8 | historyApiFallback: true
9 | }).listen(9000, 'localhost', function (err, result) {
10 | if (err) {
11 | console.log(err);
12 | }
13 |
14 | console.log('Listening at localhost:9000');
15 | });
16 |
--------------------------------------------------------------------------------
/chapter7/src/RowAlternator.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | var RowAlternator = React.createClass({
4 | propTypes: {
5 | firstColor: React.PropTypes.string,
6 | secondColor: React.PropTypes.string
7 | },
8 |
9 | render() {
10 | return (
11 |
12 | { this.props.children.map((row, idx) => {
13 | if (idx %2 == 0) {
14 | return React.cloneElement(row, { style: { background: this.props.firstColor }});
15 | } else {
16 | return React.cloneElement(row, { style: { background: this.props.secondColor }});
17 | }
18 | })
19 | }
20 |
21 | )
22 | }
23 | });
24 |
25 | module.exports = RowAlternator;
26 |
--------------------------------------------------------------------------------
/chapter7/src/Spinner.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | var Spinner = React.createClass({
4 | render() {
5 | return(
6 |
11 | );
12 | }
13 | });
14 |
15 | module.exports = Spinner;
16 |
--------------------------------------------------------------------------------
/chapter7/src/index.js:
--------------------------------------------------------------------------------
1 | import ReactDOM from 'react-dom';
2 | import React from 'react';
3 | import App from './App';
4 |
5 | ReactDOM.render(, document.getElementById('rootElement'));
6 |
--------------------------------------------------------------------------------
/chapter7/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var webpack = require('webpack');
3 |
4 | module.exports = {
5 | devtool: 'eval',
6 | entry: [
7 | 'webpack-dev-server/client?http://localhost:9000',
8 | 'webpack/hot/only-dev-server',
9 | './src/index'
10 | ],
11 | output: {
12 | path: path.join(__dirname, 'dist'),
13 | filename: 'bundle.js',
14 | publicPath: '/static/'
15 | },
16 | plugins: [
17 | new webpack.HotModuleReplacementPlugin(),
18 | new webpack.NoErrorsPlugin()
19 | ],
20 | resolve: {
21 | extensions: ['', '.js', '.jsx']
22 | },
23 | module: {
24 | loaders: [{
25 | test: /\.jsx?$/,
26 | loaders: ['react-hot', 'babel'],
27 | include: path.join(__dirname, 'src')
28 | },
29 | {test: /\.woff(\d+)?$/, loader: 'url?prefix=font/&limit=5000&mimetype=application/font-woff'},
30 | {test: /\.ttf$/, loader: 'file?prefix=font/'},
31 | {test: /\.eot$/, loader: 'file?prefix=font/'},
32 | {test: /\.svg$/, loader: 'file?prefix=font/'},
33 | {test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&minetype=application/font-woff"},
34 | {test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader"}
35 | ]
36 | }
37 | };
38 |
--------------------------------------------------------------------------------
/chapter8/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "stage": 0
3 | }
4 |
--------------------------------------------------------------------------------
/chapter8/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/chapter8/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "browser": true,
4 | "esnext": true,
5 | "newcap": false
6 | }
7 |
--------------------------------------------------------------------------------
/chapter8/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Vipul A M
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/chapter8/README.md:
--------------------------------------------------------------------------------
1 | react-perf-tools
2 | ===========
3 |
4 | Examples of React Perf tools
5 |
6 | ### Usage
7 |
8 | ```
9 | npm install
10 | npm start
11 | open http://localhost:9000
12 | npm test
13 | ```
14 |
--------------------------------------------------------------------------------
/chapter8/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | React PERF tools
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/chapter8/server.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var WebpackDevServer = require('webpack-dev-server');
3 | var config = require('./webpack.config');
4 |
5 | new WebpackDevServer(webpack(config), {
6 | publicPath: config.output.publicPath,
7 | hot: true,
8 | historyApiFallback: true
9 | }).listen(9000, 'localhost', function (err, result) {
10 | if (err) {
11 | console.log(err);
12 | }
13 |
14 | console.log('Listening at localhost:9000');
15 | });
16 |
--------------------------------------------------------------------------------
/chapter8/src/BookListHeader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default React.createClass({
4 | shouldComponentUpdate(nextProps, nextState) {
5 | return nextProps.searchCount !== this.props.searchCount;
6 | },
7 |
8 | render() {
9 | return (
10 |
11 | Total Results: {this.props.searchCount}
12 |
13 | );
14 | }
15 | })
16 |
--------------------------------------------------------------------------------
/chapter8/src/BookRow.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PureRenderMixin from 'react-addons-pure-render-mixin';
3 |
4 | export default React.createClass({
5 | shouldComponentUpdate(nextProps, nextState) {
6 | return nextProps.title !== this.props.title ||
7 | nextProps.author_name !== this.props.author_name ||
8 | nextProps.edition_count !== this.props.edition_count;
9 | },
10 |
11 | render() {
12 | return(
13 |
14 | #{this.props.index} |
15 | {this.props.title} |
16 | {(this.props.author_name || []).join(', ')} |
17 | {this.props.edition_count} |
18 |
19 | );
20 | }
21 | });
22 |
--------------------------------------------------------------------------------
/chapter8/src/BookTableHeader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default React.createClass({
4 | shouldComponentUpdate() {
5 | return false;
6 | },
7 |
8 | render() {
9 | return (
10 |
11 |
12 | |
13 | |
14 | Author |
15 | No. of Editions |
16 |
17 |
18 | );
19 | }
20 | })
21 |
--------------------------------------------------------------------------------
/chapter8/src/Header.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PureRenderMixin from 'react-addons-pure-render-mixin';
3 |
4 | export default React.createClass({
5 | mixins: [PureRenderMixin],
6 |
7 | // shouldComponentUpdate(nextProps, nextState) {
8 | // return false;
9 | // },
10 |
11 | render() {
12 | return (
13 |
14 |
15 |
Open Library | Search any book you want!
16 |
17 |
18 | )
19 | }
20 | })
21 |
--------------------------------------------------------------------------------
/chapter8/src/RowAlternator.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | var RowAlternator = React.createClass({
4 | propTypes: {
5 | firstColor: React.PropTypes.string,
6 | secondColor: React.PropTypes.string
7 | },
8 |
9 | render() {
10 | return (
11 |
12 | { this.props.children.map((row, idx) => {
13 | if (idx %2 == 0) {
14 | return React.cloneElement(row, { style: { background: this.props.firstColor }});
15 | } else {
16 | return React.cloneElement(row, { style: { background: this.props.secondColor }});
17 | }
18 | })
19 | }
20 |
21 | )
22 | }
23 | });
24 |
25 | module.exports = RowAlternator;
26 |
--------------------------------------------------------------------------------
/chapter8/src/Spinner.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default React.createClass({
4 | shouldComponentUpdate() {
5 | return false;
6 | },
7 |
8 | render() {
9 | return(
10 |
16 | );
17 | }
18 | });
19 |
--------------------------------------------------------------------------------
/chapter8/src/index.js:
--------------------------------------------------------------------------------
1 | import ReactDOM from 'react-dom';
2 | import React from 'react';
3 | import App from './App';
4 | import Perf from 'react-addons-perf';
5 |
6 | window.Perf = Perf;
7 | window.Perf.start();
8 |
9 | ReactDOM.render(, document.getElementById('rootElement'));
10 |
--------------------------------------------------------------------------------
/chapter9/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "stage": 0
3 | }
4 |
--------------------------------------------------------------------------------
/chapter9/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/chapter9/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "browser": true,
4 | "esnext": true,
5 | "newcap": false
6 | }
7 |
--------------------------------------------------------------------------------
/chapter9/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Vipul A M
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/chapter9/README.md:
--------------------------------------------------------------------------------
1 | react-addons
2 | ===========
3 |
4 | Examples of React addons
5 |
6 | ### Usage
7 |
8 | ```
9 | npm install
10 | npm start
11 | open http://localhost:9000
12 | npm test
13 | ```
14 |
--------------------------------------------------------------------------------
/chapter9/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | React Router/ Data Models
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/chapter9/server.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var WebpackDevServer = require('webpack-dev-server');
3 | var config = require('./webpack.config');
4 |
5 | new WebpackDevServer(webpack(config), {
6 | publicPath: config.output.publicPath,
7 | hot: true,
8 | historyApiFallback: true
9 | }).listen(9000, 'localhost', function (err, result) {
10 | if (err) {
11 | console.log(err);
12 | }
13 |
14 | console.log('Listening at localhost:9000');
15 | });
16 |
--------------------------------------------------------------------------------
/chapter9/src/Home.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Cats, PictureModel } from './models';
3 | import { createHistory, useBasename } from 'history'
4 | import { Router, Route, IndexRoute, Link } from 'react-router'
5 |
6 |
7 | const Home = React.createClass({
8 | render() {
9 | let sampleCat = Cats.sample();
10 | return (
11 |
12 |
13 | {Cats.map(cat => (
14 |
15 |
})
16 |
17 | ))}
18 |
19 |
{`Interesting Details about ${sampleCat.get('name')}`}
20 |
21 | )
22 | }
23 | });
24 |
25 |
26 | export {Home as default}
27 |
--------------------------------------------------------------------------------
/chapter9/src/Modal.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Router, Route, IndexRoute, Link } from 'react-router'
3 |
4 | const Modal = React.createClass({
5 | styles: {
6 | position: 'fixed',
7 | top: '20%',
8 | right: '20%',
9 | bottom: '20%',
10 | left: '20%',
11 | padding: 20,
12 | boxShadow: '0px 0px 150px 130px rgba(0, 0, 0, 0.5)',
13 | overflow: 'auto',
14 | background: '#fff'
15 | },
16 |
17 | render() {
18 | return (
19 |
20 |
Back
21 | {this.props.children}
22 |
23 | )
24 | }
25 | })
26 |
27 | export {Modal as default}
28 |
--------------------------------------------------------------------------------
/chapter9/src/Picture.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Cats, PictureModel } from './models';
3 |
4 | const Picture = React.createClass({
5 | render() {
6 | return (
7 |
8 |
.get('src')})
9 |
10 | )
11 | }
12 | });
13 |
14 | export {Picture as default}
15 |
--------------------------------------------------------------------------------
/chapter9/src/Sample.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Cats, PictureModel } from './models';
3 | import { createHistory, useBasename } from 'history'
4 | import { Router, Route, IndexRoute, Link } from 'react-router'
5 |
6 | const Sample = React.createClass({
7 | render() {
8 | let cat = Cats.get(this.props.params.cid);
9 | return (
10 |
11 |
CID for the Cat: {this.props.params.cid}, and Random ID: {this.props.params.randomId}
12 |
Name of this Cat is: {cat.get('name')}
13 |
Some interesting details about this Cat:
14 |
{cat.get('details')}
15 |
16 |
17 | Link to picture with Modal
18 |
19 |
20 | Without modal
21 |
22 |
23 |
24 | )
25 | }
26 | });
27 |
28 |
29 | export {Sample as default};
30 |
--------------------------------------------------------------------------------
/chapter9/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { render } from 'react-dom'
3 | import { createHistory, useBasename } from 'history'
4 | import { Router, Route, IndexRoute, Link } from 'react-router'
5 | import Backbone from 'backbone';
6 | import Modal from './Modal'
7 | import App from './App'
8 | import { Cats, PictureModel } from './models';
9 | import Picture from './Picture'
10 | import Sample from './Sample'
11 | import Home from './Home'
12 |
13 | const history = useBasename(createHistory)({
14 | basename: '/pinterest'
15 | });
16 |
17 |
18 | render((
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | ), document.getElementById('rootElement'));
27 |
--------------------------------------------------------------------------------