snapdrop

A Progressive Web App for local file sharing
git clone http://git.hanabi.in/repos/snapdrop.git
Log | Files | Refs | README | LICENSE

commit f5b2b47136f9903373661cb04a19c275dfbb9f12
Author: Robin Linus <robin_woll@capira.de>
Date:   Fri, 18 Dec 2015 16:50:36 +0100

initial commit

Diffstat:
A.bowerrc | 3+++
A.editorconfig | 21+++++++++++++++++++++
A.gitattributes | 2++
A.gitignore | 5+++++
A.jscsrc | 8++++++++
A.jshintrc | 24++++++++++++++++++++++++
A.travis.yml | 26++++++++++++++++++++++++++
ACONTRIBUTING.md | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ALICENSE.md | 20++++++++++++++++++++
AREADME.md | 379+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapp/cache-config.json | 4++++
Aapp/elements/elements.html | 41+++++++++++++++++++++++++++++++++++++++++
Aapp/elements/my-greeting/my-greeting.html | 45+++++++++++++++++++++++++++++++++++++++++++++
Aapp/elements/my-list/my-list.html | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapp/elements/routing.html | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapp/favicon.ico | 0
Aapp/images/touch/apple-touch-icon.png | 0
Aapp/images/touch/chrome-splashscreen-icon-384x384.png | 0
Aapp/images/touch/chrome-touch-icon-192x192.png | 0
Aapp/images/touch/icon-128x128.png | 0
Aapp/images/touch/ms-icon-144x144.png | 0
Aapp/images/touch/ms-touch-icon-144x144-precomposed.png | 0
Aapp/index.html | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapp/manifest.json | 28++++++++++++++++++++++++++++
Aapp/robots.txt | 4++++
Aapp/scripts/app.js | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapp/styles/app-theme.html | 214+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapp/styles/main.css | 14++++++++++++++
Aapp/styles/shared-styles.html | 23+++++++++++++++++++++++
Aapp/sw-import.js | 10++++++++++
Aapp/test/index.html | 32++++++++++++++++++++++++++++++++
Aapp/test/my-greeting-basic.html | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Aapp/test/my-list-basic.html | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abower.json | 20++++++++++++++++++++
Adocs/README.md | 8++++++++
Adocs/add-es2015-support-babel.md | 129+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adocs/chrome-dev-editor.md | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Adocs/deploy-to-firebase-pretty-urls.md | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adocs/deploy-to-github-pages.md | 23+++++++++++++++++++++++
Adocs/mobile-chrome-apps.md | 131+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adocs/polymer-perf.md | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Agulpfile.js | 330+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apackage.json | 43+++++++++++++++++++++++++++++++++++++++++++
Atasks/ensure-files.js | 34++++++++++++++++++++++++++++++++++
Atravis-runner.sh | 18++++++++++++++++++
Awct.conf.js | 18++++++++++++++++++
46 files changed, 2354 insertions(+), 0 deletions(-)

diff --git a/.bowerrc b/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory": "app/bower_components" +} diff --git a/.editorconfig b/.editorconfig @@ -0,0 +1,21 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + + +[*] + +# Change these settings to your own preference +indent_style = space +indent_size = 2 + +# We recommend you to keep these unchanged +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes @@ -0,0 +1 @@ +* text=auto +\ No newline at end of file diff --git a/.gitignore b/.gitignore @@ -0,0 +1,5 @@ +node_modules +dist +bower_components +.tmp +.publish/ diff --git a/.jscsrc b/.jscsrc @@ -0,0 +1,8 @@ +{ + "preset": "google", + "disallowSpacesInAnonymousFunctionExpression": null, + "disallowTrailingWhitespace": null, + "validateIndentation": null, + "maximumLineLength": 100, + "excludeFiles": ["node_modules/**"] +} diff --git a/.jshintrc b/.jshintrc @@ -0,0 +1,24 @@ +{ + "node": true, + "browser": true, + "bitwise": true, + "camelcase": true, + "curly": true, + "eqeqeq": true, + "immed": true, + "indent": 2, + "latedef": true, + "noarg": true, + "quotmark": "single", + "undef": true, + "unused": true, + "newcap": false, + "globals": { + "wrap": true, + "unwrap": true, + "Polymer": true, + "Platform": true, + "page": true, + "app": true + } +} diff --git a/.travis.yml b/.travis.yml @@ -0,0 +1,26 @@ +language: node_js +sudo: false +addons: + firefox: latest + apt: + sources: + - google-chrome + - ubuntu-toolchain-r-test + packages: + - google-chrome-stable + - g++-4.8 +node_js: + - '4.2' + - '5.1' +before_script: + - 'export DISPLAY=:99.0' + - sh -e /etc/init.d/xvfb start + - sleep 3 + - npm i -g bower gulp + - bower i +script: + - ./travis-runner.sh +env: + global: + - "CXX='g++-4.8'" + - secure: SbcQ7plU7aRGQlaAG2ffMhSvEs84073YSljOQ62DZAjRxgizMhF4xM7H2mPrmac9YRM4IBrQRvBKMMZy3L6OhN8gwpm8o+w2zV+5Q1fwpY9V8bilznnhp1JUY6jrB2l7aLTOFxt/cG+5ABxiupwWz/n+I7BaByYhBiHWntIBgDc528eecRNDYI5R36KWjLO/yr+SdElvyxDlDOdJGaluPvgMItbinFGcE1hYb/Jqrkkw8zpE6CTDmvMOq1aRBWSo9afgh2zDeKc02lTYP/4N0xcn8CqzHF7k5zGWHjN9DR8Ep8Bp1ff/sM7zHGZBqgVhn5WGv305jBQY6eOxiTp5cDP0WVIOjgJeM5rBu9hBQxhZSaMKBPr2B1NYUjIwTVQkBsnR4sr095Ugjg8JCZAmEevf/Ysl4CzQyW3gT+WcEluqjxUuicQWDclH6L/kOVPBJ+Eqdo/LY3G1tpLcc6fsvj4FlVO6LPTrbMyCagwQvnjX3uIdFyuthqtWWrHKQMGx2Ow9suNUi8Hyvk7WboS1Z6jrLIcs1rvXSX8rQmlMR5vJBK3Ejg6fS1OHxn/lrtLhj4lDLB9r/Fcu2PEHT1lcvQqsTa3W+t4Fk1qaShUlBDiwMbZWZgmlf1SdG5OzK1yrPLjTTdRFdqJGgb6TANCdetgczRWynvjIhr5IDMxvfJg= diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md @@ -0,0 +1,72 @@ + +<!-- +This file is autogenerated based on +https://github.com/PolymerElements/ContributionGuide/blob/master/CONTRIBUTING.md + +If you edit that file, it will get updated everywhere else. +If you edit this file, your changes will get overridden :) +--> +# Polymer Elements +## Guide for Contributors + +Polymer Elements are built in the open, and the Polymer authors eagerly encourage any and all forms of community contribution. When contributing, please follow these guidelines: + +### Filing Issues + +**If you are filing an issue to request a feature**, please provide a clear description of the feature. It can be helpful to describe answers to the following questions: + + 1. **Who will use the feature?** _“As someone filling out a form…”_ + 2. **When will they use the feature?** _“When I enter an invalid value…”_ + 3. **What is the user’s goal?** _“I want to be visually notified that the value needs to be corrected…”_ + +**If you are filing an issue to report a bug**, please provide: + + 1. **A clear description of the bug and related expectations.** Consider using the following example template for reporting a bug: + + ```markdown + The `paper-foo` element causes the page to turn pink when clicked. + + ## Expected outcome + + The page stays the same color. + + ## Actual outcome + + The page turns pink. + + ## Steps to reproduce + + 1. Put a `paper-foo` element in the page. + 2. Open the page in a web browser. + 3. Click the `paper-foo` element. + ``` + + 2. **A reduced test case that demonstrates the problem.** If possible, please include the test case as a JSBin. Start with this template to easily import and use relevant Polymer Elements: [http://jsbin.com/cagaye](http://jsbin.com/cagaye/edit?html,output). + + 3. **A list of browsers where the problem occurs.** This can be skipped if the problem is the same across all browsers. + +### Submitting Pull Requests + +**Before creating a pull request**, please ensure that an issue exists for the corresponding change in the pull request that you intend to make. **If an issue does not exist, please create one per the guidelines above**. The goal is to discuss the design and necessity of the proposed change with Polymer authors and community before diving into a pull request. + +When submitting pull requests, please provide: + + 1. **A reference to the corresponding issue** or issues that will be closed by the pull request. Please refer to these issues using the following syntax: + + ```markdown + (For a single issue) + Fixes #20 + + (For multiple issues) + Fixes #32, #40 + ``` + + 2. **A succinct description of the design** used to fix any related issues. For example: + + ```markdown + This fixes #20 by removing styles that leaked which would cause the page to turn pink whenever `paper-foo` is clicked. + ``` + + 3. **At least one test for each bug fixed or feature added** as part of the pull request. Pull requests that fix bugs or add features without accompanying tests will not be considered. + +If a proposed change contains multiple commits, please [squash commits](https://www.google.com/url?q=http://blog.steveklabnik.com/posts/2012-11-08-how-to-squash-commits-in-a-github-pull-request) to as few as is necessary to succinctly express the change. A Polymer author can help you squash commits, so don’t be afraid to ask us if you need help with that! diff --git a/LICENSE.md b/LICENSE.md @@ -0,0 +1,19 @@ +# License + +Everything in this repo is BSD style license unless otherwise specified. + +Copyright (c) 2015 The Polymer Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. +* Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\ No newline at end of file diff --git a/README.md b/README.md @@ -0,0 +1,379 @@ +![](https://cloud.githubusercontent.com/assets/110953/7877439/6a69d03e-0590-11e5-9fac-c614246606de.png) +## Polymer Starter Kit + +> A starting point for building web applications with Polymer 1.0 + +### Included out of the box: + +* [Polymer](https://www.polymer-project.org/), [Paper](https://elements.polymer-project.org/browse?package=paper-elements), [Iron](https://elements.polymer-project.org/browse?package=iron-elements) and [Neon](https://elements.polymer-project.org/browse?package=neon-elements) elements +* [Material Design](http://www.google.com/design/spec/material-design/introduction.html) layout +* Routing with [Page.js](https://visionmedia.github.io/page.js/) +* Unit testing with [Web Component Tester](https://github.com/Polymer/web-component-tester) +* Optional offline setup through [Platinum](https://elements.polymer-project.org/browse?package=platinum-elements) Service Worker elements +* End-to-end Build Tooling (including [Vulcanize](https://github.com/Polymer/vulcanize)) +* [Recipes](/docs/README.md/) for ES2015 support, Polymer performance, using Chrome Dev Editor, Deploying to GitHub Pages, Deploying to Firebase, and Mobile Chrome Apps + +### Demo +See latest Polymer Starter Kit Demo (from master) at http://polymerelements.github.io/polymer-starter-kit + +### Tutorials + +Check out the Polymer Starter Kit tutorials on [polymer-project.org](https://polymer-project.org): + +* [Set up the PSK](https://www.polymer-project.org/1.0/docs/start/psk/set-up.html) +* [Create a page](https://www.polymer-project.org/1.0/docs/start/psk/create-a-page.html) +* [Deploy the PSK to the web](https://www.polymer-project.org/1.0/docs/start/psk/deploy.html) + +## Getting Started + +To take advantage of Polymer Starter Kit you need to: + +1. Get a copy of the code. +2. Install the dependencies if you don't already have them. +3. Modify the application to your liking. +4. Deploy your production code. + +### Get the code + +[Download](https://github.com/polymerelements/polymer-starter-kit/releases/latest) and extract Polymer Starter Kit to where you want to work. The project comes in two flavours - Light and Full. + +**Beginners**: Try Polymer Starter Kit Light. This doesn't require any extra dependencies nor knowledge of modern front-end tooling. This option is good for prototyping if you haven't build a Polymer app before. + +**Intermediate - Advanced**: Use the full version of Polymer Starter Kit. This comes with all the build tools you'll need for testing and productionising your app so it's nice and lean. You'll need to run a few extra commands to install the tools we recommend but it's worth it to make sure your final app is super optimised. + +:warning: **Important**: Polymer Starter Kit, and Polymer Starter Kit Light, both contain dotfiles (files starting with a `.`). If you're copying the contents of the Starter Kit to a new location make sure you bring along these dotfiles as well! On Mac, [enable showing hidden files](http://ianlunn.co.uk/articles/quickly-showhide-hidden-files-mac-os-x-mavericks/), then try extracting/copying Polymer Starter Kit again. This time the dotfiles needed should be visible so you can copy them over without issues. + +Rob Dodson has a fantastic [PolyCast video](https://www.youtube.com/watch?v=xz-yixRxZN8) available that walks through using Polymer Starter Kit. An [end-to-end with Polymer](https://www.youtube.com/watch?v=1f_Tj_JnStA) and Polymer Starter Kit talk is also available. + +### Install dependencies + +#### Quick-start (for experienced users) + +With Node.js installed, run the following one liner from the root of your Polymer Starter Kit download: + +```sh +npm install -g gulp bower && npm install && bower install +``` + +#### Prerequisites (for everyone) + +The full starter kit requires the following major dependencies: + +- Node.js, used to run JavaScript tools from the command line. +- npm, the node package manager, installed with Node.js and used to install Node.js packages. +- gulp, a Node.js-based build tool. +- bower, a Node.js-based package manager used to install front-end packages (like Polymer). + +**To install dependencies:** + +1) Check your Node.js version. + +```sh +node --version +``` + +The version should be at or above 0.12.x. + +2) If you don't have Node.js installed, or you have a lower version, go to [nodejs.org](https://nodejs.org) and click on the big green Install button. + +3) Install `gulp` and `bower` globally. + +```sh +npm install -g gulp bower +``` + +This lets you run `gulp` and `bower` from the command line. + +4) Install the starter kit's local `npm` and `bower` dependencies. + +```sh +cd polymer-starter-kit && npm install && bower install +``` + +This installs the element sets (Paper, Iron, Platinum) and tools the starter kit requires to build and serve apps. + +### Development workflow + +#### Serve / watch + +```sh +gulp serve +``` + +This outputs an IP address you can use to locally test and another that can be used on devices connected to your network. + +#### Run tests + +```sh +gulp test:local +``` + +This runs the unit tests defined in the `app/test` directory through [web-component-tester](https://github.com/Polymer/web-component-tester). + +To run tests Java 7 or higher is required. To update Java go to http://www.oracle.com/technetwork/java/javase/downloads/index.html and download ***JDK*** and install it. + +#### Build & Vulcanize + +```sh +gulp +``` + +Build and optimize the current project, ready for deployment. This includes linting as well as vulcanization, image, script, stylesheet and HTML optimization and minification. + +## Application Theming & Styling + +Polymer 1.0 introduces a shim for CSS custom properties. We take advantage of this in `app/styles/app-theme.html` to provide theming for your application. You can also find our presets for Material Design breakpoints in this file. + +[Read more](https://www.polymer-project.org/1.0/docs/devguide/styling.html) about CSS custom properties. + +### Styling +1. ***main.css*** - to define styles that can be applied outside of Polymer's custom CSS properties implementation. Some of the use-cases include defining styles that you want to be applied for a splash screen, styles for your application 'shell' before it gets upgraded using Polymer or critical style blocks that you want parsed before your elements are. +2. ***app-theme.html*** - to provide theming for your application. You can also find our presets for Material Design breakpoints in this file. +3. ***shared-styles.html*** - to share styles between elements and index.html. +4. ***element styles only*** - styles specific to element. These styles should be inside the `<style></style>` inside `template`. + + ```HTML + <dom-module id="my-list"> + <template> + <style> + :host { + display: block; + background-color: yellow; + } + </style> + <ul> + <template is="dom-repeat" items="{{items}}"> + <li><span class="paper-font-body1">{{item}}</span></li> + </template> + </ul> + </template> + </dom-module> + ``` + +These style files are located in the [styles folder](app/styles/). + +## Unit Testing + +Web apps built with Polymer Starter Kit come configured with support for [Web Component Tester](https://github.com/Polymer/web-component-tester) - Polymer's preferred tool for authoring and running unit tests. This makes testing your element based applications a pleasant experience. + +[Read more](https://github.com/Polymer/web-component-tester#html-suites) about using Web Component tester. + +## Dependency Management + +Polymer uses [Bower](http://bower.io) for package management. This makes it easy to keep your elements up to date and versioned. For tooling, we use npm to manage Node.js-based dependencies. + +Components installed by Bower live in the `app/bower_components` directory. This location is specified by the `.bowerrc` file. Many projects which follow Yeoman conventions place the `bower_components` directory outside of the `app` directory and then mount it using a server. This causes problems for tools like [Vulcanize](https://github.com/polymer/vulcanize) and [web-component-shards](https://github.com/PolymerLabs/web-component-shards) which rely on relative paths. We've chosen to simplify things and have `bower_components` live inside of `app` to resolve these issues. + +## Deploy + +### Github Pages + +1. Uncomment this line `// app.baseUrl = '/polymer-starter-kit/';` in app.js near the top +2. Change `app.baseUrl = '/polymer-starter-kit/';` to `app.baseUrl = '/your-pathname/';` (ex: if you repo is `github.com/username/bobs-awesome-site` you would change this to `bobs-awesome-site`) +3. Run `gulp build-deploy-gh-pages` from command line +4. To see changes wait 1-2 minutes then load Github pages for your app (ex: http://polymerelements.github.io/polymer-starter-kit) + +[See more details](/docs/deploy-to-github-pages.md/) + +### Firebase + +[See detail recipe](/docs/deploy-to-firebase-pretty-urls.md/) + +## Service Worker + +Polymer Starter Kit offers an optional offline experience thanks to Service Worker and the [Platinum Service Worker elements](https://github.com/PolymerElements/platinum-sw). New to Service Worker? Read the following [introduction](http://www.html5rocks.com/en/tutorials/service-worker/introduction/) to understand how it works. + +Our optional offline setup should work well for relatively simple applications. For more complex apps, we recommend learning how Service Worker works so that you can make the most of the Platinum Service Worker element abstractions. + +### Enable Service Worker support? + +To enable Service Worker support for Polymer Starter Kit project use these 3 steps: + +1. Uncomment Service Worker code in index.html + ```HTML + <!-- Uncomment next block to enable Service Worker support (1/2) --> + <!-- + <paper-toast id="caching-complete" + duration="6000" + text="Caching complete! This app will work offline."> + </paper-toast> + + <platinum-sw-register auto-register + clients-claim + skip-waiting + on-service-worker-installed="displayInstalledToast"> + <platinum-sw-cache default-cache-strategy="networkFirst" + cache-config-file="cache-config.json"> + </platinum-sw-cache> + </platinum-sw-register> + --> + ``` +2. Uncomment Service Worker code in elements.html + + ```HTML + <!-- Uncomment next block to enable Service Worker Support (2/2) --> + <!-- + <link rel="import" href="../bower_components/platinum-sw/platinum-sw-cache.html"> + <link rel="import" href="../bower_components/platinum-sw/platinum-sw-register.html"> + --> + ``` +3. Uncomment 'cache-config' in the `runSequence()` section of the 'default' gulp task, like below: +[(gulpfile.js)](https://github.com/PolymerElements/polymer-starter-kit/blob/master/gulpfile.js) + + ```JavaScript + // Build Production Files, the Default Task + gulp.task('default', ['clean'], function (cb) { + runSequence( + ['copy', 'styles'], + 'elements', + ['jshint', 'images', 'fonts', 'html'], + 'vulcanize', 'cache-config', + cb); + }); + ``` + +#### Filing bugs in the right place + +If you experience an issue with Service Worker support in your application, check the origin of the issue and use the appropriate issue tracker: + +* [sw-toolbox](https://github.com/GoogleChrome/sw-toolbox/issues) +* [platinum-sw](https://github.com/PolymerElements/platinum-sw/issues) +* [platinum-push-notifications-manager](https://github.com/PolymerElements/platinum-push-messaging) +* For all other issues, feel free to file them [here](https://github.com/polymerelements/polymer-starter-kit/issues). + +#### I get an error message about "Only secure origins are allowed" + +Service Workers are only available to "secure origins" (HTTPS sites, basically) in line with a policy to prefer secure origins for powerful new features. However http://localhost is also considered a secure origin, so if you can, developing on localhost is an easy way to avoid this error. For production, your site will need to support HTTPS. + +#### How do I debug Service Worker? + +If you need to debug the event listener wire-up use `chrome://serviceworker-internals`. + +#### What are those buttons on chrome://serviceworker-internals? + +This page shows your registered workers and provides some basic operations. + +* Unregister: Unregisters the worker. +* Start: Starts the worker. This would happen automatically when you navigate to a page in the worker's scope. +* Stop: Stops the worker. +* Sync: Dispatches a 'sync' event to the worker. If you don't handle this event, nothing will happen. +* Push: Dispatches a 'push' event to the worker. If you don't handle this event, nothing will happen. +* Inspect: Opens the worker in the Inspector. + +#### Development flow + +In order to guarantee that the latest version of your Service Worker script is being used, follow these instructions: + +* After you made changes to your service worker script, close all but one of the tabs pointing to your web application +* Hit shift-reload to bypass the service worker as to ensure that the remaining tab isn't under the control of a service worker +* Hit reload to let the newer version of the Service Worker control the page. + +If you find anything to still be stale, you can also try navigating to `chrome:serviceworker-internals` (in Chrome), finding the relevant Service Worker entry for your application and clicking 'Unregister' before refreshing your app. This will (of course) only clear it from the local development machine. If you have already deployed to production then further work will be necessary to remove it from your user's machines. + +#### Disable Service Worker support after you enabled it + +If for any reason you need to disable Service Worker support after previously enabling it, you can remove it from your Polymer Starter Kit project using these 4 steps: + +1. Remove references to the platinum-sw elements from your application [index](https://github.com/PolymerElements/polymer-starter-kit/blob/master/app/index.html). +2. Remove the two Platinum Service Worker elements (platinum-sw/..) in [app/elements/elements.html](https://github.com/PolymerElements/polymer-starter-kit/blob/master/app/elements/elements.html) +3. Remove 'precache' from the list in the 'default' gulp task ([gulpfile.js](https://github.com/PolymerElements/polymer-starter-kit/blob/master/gulpfile.js)) +4. Navigate to `chrome://serviceworker-internals` and unregister any Service Workers registered by Polymer Starter Kit for your app just in case there's a copy of it cached. + +## Yeoman support + +[generator-polymer](https://github.com/yeoman/generator-polymer/releases) now includes support for Polymer Starter Kit out of the box. + +## Frequently Asked Questions + +### Where do I customise my application theme? + +Theming can be achieved using [CSS Custom properties](https://www.polymer-project.org/1.0/docs/devguide/styling.html#xscope-styling-details) via [app/styles/app-theme.html](https://github.com/PolymerElements/polymer-starter-kit/blob/master/app/styles/app-theme.html). +You can also use `app/styles/main.css` for pure CSS stylesheets (e.g for global styles), however note that Custom properties will not work there under the shim. + +A [Polycast](https://www.youtube.com/watch?v=omASiF85JzI) is also available that walks through theming using Polymer 1.0. + +### Where do I configure routes in my application? + +This can be done via [`app/elements/routing.html`](https://github.com/PolymerElements/polymer-starter-kit/blob/master/app/elements/routing.html). We use Page.js for routing and new routes +can be defined in this import. We then toggle which `<iron-pages>` page to display based on the [selected](https://github.com/PolymerElements/polymer-starter-kit/blob/master/app/index.html#L105) route. + +### Why are we using Page.js rather than a declarative router like `<more-routing>`? + +`<more-routing>` (in our opinion) is good, but lacks imperative hooks for getting full control +over the routing in your application. This is one place where a pure JS router shines. We may +at some point switch back to a declarative router when our hook requirements are tackled. That +said, it should be trivial to switch to `<more-routing>` or another declarative router in your +own local setup. + +### Where can I find the application layouts from your Google I/O 2015 talk? + +App layouts live in a separate repository called [app-layout-templates](https://github.com/PolymerElements/app-layout-templates). +You can select a template and copy over the relevant parts you would like to reuse to Polymer Starter Kit. + +You will probably need to change paths to where your Iron and Paper dependencies can be found to get everything working. +This can be done by adding them to the [`elements.html`](https://github.com/PolymerElements/polymer-starter-kit/blob/master/app/elements/elements.html) import. + +### Something has failed during installation. How do I fix this? + +Our most commonly reported issue is around system permissions for installing Node.js dependencies. +We recommend following the [fixing npm permissions](https://github.com/sindresorhus/guides/blob/master/npm-global-without-sudo.md) +guide to address any messages around administrator permissions being required. If you use `sudo` +to work around these issues, this guide may also be useful for avoiding that. + +If you run into an exception that mentions five optional dependencies failing (or an `EEXIST` error), you +may have run into an npm [bug](https://github.com/npm/npm/issues/6309). We recommend updating to npm 2.11.0+ +to work around this. You can do this by opening a Command Prompt/terminal and running `npm install npm@2.11.0 -g`. If you are on Windows, +Node.js (and npm) may have been installed into `C:\Program Files\`. Updating npm by running `npm install npm@2.11.0 -g` will install npm +into `%AppData%\npm`, but your system will still use the npm version. You can avoid this by deleting your older npm from `C:\Program Files\nodejs` +as described [here](https://github.com/npm/npm/issues/6309#issuecomment-67549380). + +If the issue is to do with a failure somewhere else, you might find that due to a network issue +a dependency failed to correctly install. We recommend running `npm cache clean` and deleting the `node_modules` directory followed by +`npm install` to see if this corrects the problem. If not, please check the [issue tracker](https://github.com/PolymerElements/polymer-starter-kit/issues) in case +there is a workaround or fix already posted. + +### I'm having trouble getting Vulcanize to fully build my project on Windows. Help? + +Some Windows users have run into trouble with the `elements.html` file in their `dist` folder +not being correctly vulcanized. This can happen if your project is in a folder with a name containing a +space. You can work around this issue by ensuring your path doesn't contain one. + +There is also an [in-flight](https://github.com/PolymerElements/polymer-starter-kit/issues/62#issuecomment-108974016) issue +where some are finding they need to disable the `inlineCss` option in our configuration for Vulcanize +to correctly build. We are still investigating this, however for the time-being use the workaround if +you find your builds getting stuck here. + + +### How do I add new JavaScript files to Starter Kit so they're picked up by the build process? + +At the bottom of `app/index.html`, you will find a build block that can be used to include additional +scripts for your app. Build blocks are just normal script tags that are wrapped in a HTML +comment that indicates where to concatenate and minify their final contents to. + +Below, we've added in `script2.js` and `script3.js` to this block. The line +`<!-- build:js scripts/app.js -->` specifies that these scripts will be squashed into `scripts/app.js` +during a build. + +```html +<!-- build:js scripts/app.js --> +<script src="scripts/app.js"></script> +<script src="scripts/script2.js"></script> +<script src="scripts/script3.js"></script> +<!-- endbuild--> +``` + +If you are not using the build-blocks, but still wish for additional files (e.g scripts or stylesheets) to be included in the final `dist` directory, you will need to either copy these files as part of the gulpfile.js build process (see the `copy` task for how to automate this) or manually copy the files. + +### I'm finding the installation/tooling here overwhelming. What should I do? + +Don't worry! We've got your covered. Polymer Starter Kit tries to offer everything you need to build and optimize your apps for production, which is why we include the tooling we do. We realise however that our tooling setup may not be for everyone. + +If you find that you just want the simplest setup possible, we recommend using Polymer Starter Kit light, which is available from the [Releases](https://github.com/PolymerElements/polymer-starter-kit/releases) page. This takes next to no time to setup. + +## Licensing + +Like other Google projects, Polymer Starter Kit includes Google license headers at the top of several of our source files. Google's open-source licensing requires that this header be kept in place (sorry!), however we acknowledge that you may need to add your own licensing to files you modify. This can be done by appending your own extensions to these headers. + +## Contributing + +Polymer Starter Kit is a new project and is an ongoing effort by the Web Component community. We welcome your bug reports, PRs for improvements, docs and anything you think would improve the experience for other Polymer developers. diff --git a/app/cache-config.json b/app/cache-config.json @@ -0,0 +1,4 @@ +{ + "README": "This is the cache config for the dev server. The service worker cache is disabled, and it is recommended that you leave this as-is. In the dist environment, this file will be auto-generated based on the contents of your dist/ directory.", + "disabled": true +} diff --git a/app/elements/elements.html b/app/elements/elements.html @@ -0,0 +1,41 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<!-- Iron elements --> +<link rel="import" href="../bower_components/iron-flex-layout/classes/iron-flex-layout.html"> +<link rel="import" href="../bower_components/iron-icons/iron-icons.html"> +<link rel="import" href="../bower_components/iron-pages/iron-pages.html"> +<link rel="import" href="../bower_components/iron-selector/iron-selector.html"> + +<!-- Paper elements --> +<link rel="import" href="../bower_components/paper-drawer-panel/paper-drawer-panel.html"> +<link rel="import" href="../bower_components/paper-icon-button/paper-icon-button.html"> +<link rel="import" href="../bower_components/paper-item/paper-item.html"> +<link rel="import" href="../bower_components/paper-material/paper-material.html"> +<link rel="import" href="../bower_components/paper-menu/paper-menu.html"> +<link rel="import" href="../bower_components/paper-scroll-header-panel/paper-scroll-header-panel.html"> +<link rel="import" href="../bower_components/paper-styles/paper-styles-classes.html"> +<link rel="import" href="../bower_components/paper-toast/paper-toast.html"> +<link rel="import" href="../bower_components/paper-toolbar/paper-toolbar.html"> + +<!-- Uncomment next block to enable Service Worker Support (2/2) --> +<!-- +<link rel="import" href="../bower_components/platinum-sw/platinum-sw-cache.html"> +<link rel="import" href="../bower_components/platinum-sw/platinum-sw-register.html"> +--> + +<!-- Configure your routes here --> +<link rel="import" href="routing.html"> + +<!-- Add your elements here --> +<link rel="import" href="../styles/app-theme.html"> +<link rel="import" href="../styles/shared-styles.html"> +<link rel="import" href="my-greeting/my-greeting.html"> +<link rel="import" href="my-list/my-list.html"> diff --git a/app/elements/my-greeting/my-greeting.html b/app/elements/my-greeting/my-greeting.html @@ -0,0 +1,44 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<link rel="import" href="../../bower_components/polymer/polymer.html"> + +<dom-module id="my-greeting"> + <template> + <style include="shared-styles"></style> + <style> + :host { + display: block; + } + </style> + <h2 class="page-title">{{greeting}}</h2> + <span class="paper-font-body2">Update text to change the greeting.</span> + <!-- Listens for "input" event and sets greeting to <input>.value --> + <input class="paper-font-body2" value="{{greeting::input}}"> + </template> + + <script> + (function() { + 'use strict'; + + Polymer({ + is: 'my-greeting', + + properties: { + greeting: { + type: String, + value: 'Welcome!', + notify: true + } + } + }); + })(); + </script> + +</dom-module> +\ No newline at end of file diff --git a/app/elements/my-list/my-list.html b/app/elements/my-list/my-list.html @@ -0,0 +1,51 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<link rel="import" href="../../bower_components/polymer/polymer.html"> + +<dom-module id="my-list"> + <template> + <style> + :host { + display: block; + } + </style> + <ul> + <template is="dom-repeat" items="{{items}}"> + <li><span class="paper-font-body1">{{item}}</span></li> + </template> + </ul> + </template> + + <script> + (function() { + 'use strict'; + + Polymer({ + is: 'my-list', + properties: { + items: { + type: Array, + notify: true, + } + }, + ready: function() { + this.items = [ + 'Responsive Web App boilerplate', + 'Iron Elements and Paper Elements', + 'End-to-end Build Tooling (including Vulcanize)', + 'Unit testing with Web Component Tester', + 'Routing with Page.js', + 'Offline support with the Platinum Service Worker Elements' + ]; + } + }); + })(); + </script> +</dom-module> +\ No newline at end of file diff --git a/app/elements/routing.html b/app/elements/routing.html @@ -0,0 +1,74 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<script src="../bower_components/page/page.js"></script> +<script> + window.addEventListener('WebComponentsReady', function() { + + // We use Page.js for routing. This is a Micro + // client-side router inspired by the Express router + // More info: https://visionmedia.github.io/page.js/ + + // Removes end / from app.baseUrl which page.base requires for production + if (window.location.port === '') { // if production + page.base(app.baseUrl.replace(/\/$/, '')); + } + + // Middleware + function scrollToTop(ctx, next) { + app.scrollPageToTop(); + next(); + } + + function closeDrawer(ctx, next) { + app.closeDrawer(); + next(); + } + + // Routes + page('*', scrollToTop, closeDrawer, function(ctx, next) { + next(); + }); + + page('/', function() { + app.route = 'home'; + }); + + page(app.baseUrl, function() { + app.route = 'home'; + }); + + page('/users', function() { + app.route = 'users'; + }); + + page('/users/:name', function(data) { + app.route = 'user-info'; + app.params = data.params; + }); + + page('/contact', function() { + app.route = 'contact'; + }); + + // 404 + page('*', function() { + app.$.toast.text = 'Can\'t find: ' + window.location.href + '. Redirected you to Home Page'; + app.$.toast.show(); + page.redirect(app.baseUrl); + }); + + // add #! before urls + page({ + hashbang: true + }); + + }); +</script> diff --git a/app/favicon.ico b/app/favicon.ico Binary files differ. diff --git a/app/images/touch/apple-touch-icon.png b/app/images/touch/apple-touch-icon.png Binary files differ. diff --git a/app/images/touch/chrome-splashscreen-icon-384x384.png b/app/images/touch/chrome-splashscreen-icon-384x384.png Binary files differ. diff --git a/app/images/touch/chrome-touch-icon-192x192.png b/app/images/touch/chrome-touch-icon-192x192.png Binary files differ. diff --git a/app/images/touch/icon-128x128.png b/app/images/touch/icon-128x128.png Binary files differ. diff --git a/app/images/touch/ms-icon-144x144.png b/app/images/touch/ms-icon-144x144.png Binary files differ. diff --git a/app/images/touch/ms-touch-icon-144x144-precomposed.png b/app/images/touch/ms-touch-icon-144x144-precomposed.png Binary files differ. diff --git a/app/index.html b/app/index.html @@ -0,0 +1,84 @@ +<!doctype html> +<html lang="en"> + +<head> + <meta charset="utf-8"> + <meta name="description" content=""> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="generator" content="Share With Me!"> + <title>Share With Me!</title> + <!-- Place favicon.ico in the `app/` directory --> + + <!-- Chrome for Android theme color --> + <meta name="theme-color" content="#2E3AA1"> + + <!-- Web Application Manifest --> + <link rel="manifest" href="manifest.json"> + + <!-- Tile color for Win8 --> + <meta name="msapplication-TileColor" content="#3372DF"> + + <!-- Add to homescreen for Chrome on Android --> + <meta name="mobile-web-app-capable" content="yes"> + <meta name="application-name" content="PSK"> + <link rel="icon" sizes="192x192" href="images/touch/chrome-touch-icon-192x192.png"> + + <!-- Add to homescreen for Safari on iOS --> + <meta name="apple-mobile-web-app-capable" content="yes"> + <meta name="apple-mobile-web-app-status-bar-style" content="black"> + <meta name="apple-mobile-web-app-title" content="Share With Me!"> + <link rel="apple-touch-icon" href="images/touch/apple-touch-icon.png"> + + <!-- Tile icon for Win8 (144x144) --> + <meta name="msapplication-TileImage" content="images/touch/ms-touch-icon-144x144-precomposed.png"> + + <!-- build:css styles/main.css --> + <link rel="stylesheet" href="styles/main.css"> + <!-- endbuild--> + + <!-- build:js bower_components/webcomponentsjs/webcomponents-lite.min.js --> + <script src="bower_components/webcomponentsjs/webcomponents-lite.js"></script> + <!-- endbuild --> + + <!-- Because this project uses vulcanize this should be your only html import + in this file. All other imports should go in elements.html --> + <link rel="import" href="elements/elements.html"> + + <!-- For shared styles, shared-styles.html import in elements.html --> + <style is="custom-style" include="shared-styles"></style> + +</head> + +<body unresolved class="fullbleed layout vertical"> + <span id="browser-sync-binding"></span> + <template is="dom-bind" id="app"> + + + <paper-toast id="toast"> + <span class="toast-hide-button" role="button" tabindex="0" onclick="app.$.toast.hide()">Ok</span> + </paper-toast> + + <!-- Uncomment next block to enable Service Worker support (1/2) --> + + <paper-toast id="caching-complete" + duration="6000" + text="Caching complete! This app will work offline."> + </paper-toast> + + <platinum-sw-register auto-register + clients-claim + skip-waiting + base-uri="bower_components/platinum-sw/bootstrap" + on-service-worker-installed="displayInstalledToast"> + <platinum-sw-cache default-cache-strategy="fastest" + cache-config-file="cache-config.json"> + </platinum-sw-cache> + </platinum-sw-register> + </template> + + <!-- build:js scripts/app.js --> + <script src="scripts/app.js"></script> + <!-- endbuild--> +</body> + +</html> diff --git a/app/manifest.json b/app/manifest.json @@ -0,0 +1,28 @@ +{ + "name": "Polymer Starter Kit", + "short_name": "Polymer Starter Kit", + "icons": [{ + "src": "images/touch/icon-128x128.png", + "sizes": "128x128", + "type": "image/png" + }, { + "src": "images/touch/apple-touch-icon.png", + "sizes": "152x152", + "type": "image/png" + }, { + "src": "images/touch/ms-touch-icon-144x144-precomposed.png", + "sizes": "144x144", + "type": "image/png" + }, { + "src": "images/touch/chrome-touch-icon-192x192.png", + "sizes": "192x192", + "type": "image/png" + },{ + "src": "images/touch/chrome-splashscreen-icon-384x384.png", + "sizes": "384x384", + "type": "image/png" + }], + "background_color": "#3E4EB8", + "display": "standalone", + "theme_color": "#2E3AA1" +} diff --git a/app/robots.txt b/app/robots.txt @@ -0,0 +1,4 @@ +# www.robotstxt.org + +User-agent: * +Disallow: diff --git a/app/scripts/app.js b/app/scripts/app.js @@ -0,0 +1,81 @@ +/* +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +*/ + +(function(document) { + 'use strict'; + + // Grab a reference to our auto-binding template + // and give it some initial binding values + // Learn more about auto-binding templates at http://goo.gl/Dx1u2g + var app = document.querySelector('#app'); + + // Sets app default base URL + app.baseUrl = '/'; + if (window.location.port === '') { // if production + // Uncomment app.baseURL below and + // set app.baseURL to '/your-pathname/' if running from folder in production + // app.baseUrl = '/polymer-starter-kit/'; + } + + app.displayInstalledToast = function() { + // Check to make sure caching is actually enabled—it won't be in the dev environment. + if (!Polymer.dom(document).querySelector('platinum-sw-cache').disabled) { + Polymer.dom(document).querySelector('#caching-complete').show(); + } + }; + + // Listen for template bound event to know when bindings + // have resolved and content has been stamped to the page + app.addEventListener('dom-change', function() { + console.log('Our app is ready to rock!'); + }); + + // See https://github.com/Polymer/polymer/issues/1381 + window.addEventListener('WebComponentsReady', function() { + // imports are loaded and elements have been registered + }); + + // Main area's paper-scroll-header-panel custom condensing transformation of + // the appName in the middle-container and the bottom title in the bottom-container. + // The appName is moved to top and shrunk on condensing. The bottom sub title + // is shrunk to nothing on condensing. + window.addEventListener('paper-header-transform', function(e) { + var appName = Polymer.dom(document).querySelector('#mainToolbar .app-name'); + var middleContainer = Polymer.dom(document).querySelector('#mainToolbar .middle-container'); + var bottomContainer = Polymer.dom(document).querySelector('#mainToolbar .bottom-container'); + var detail = e.detail; + var heightDiff = detail.height - detail.condensedHeight; + var yRatio = Math.min(1, detail.y / heightDiff); + // appName max size when condensed. The smaller the number the smaller the condensed size. + var maxMiddleScale = 0.50; + var auxHeight = heightDiff - detail.y; + var auxScale = heightDiff / (1 - maxMiddleScale); + var scaleMiddle = Math.max(maxMiddleScale, auxHeight / auxScale + maxMiddleScale); + var scaleBottom = 1 - yRatio; + + // Move/translate middleContainer + Polymer.Base.transform('translate3d(0,' + yRatio * 100 + '%,0)', middleContainer); + + // Scale bottomContainer and bottom sub title to nothing and back + Polymer.Base.transform('scale(' + scaleBottom + ') translateZ(0)', bottomContainer); + + // Scale middleContainer appName + Polymer.Base.transform('scale(' + scaleMiddle + ') translateZ(0)', appName); + }); + + // Scroll page to top and expand header + app.scrollPageToTop = function() { + app.$.headerPanelMain.scrollToTop(true); + }; + + app.closeDrawer = function() { + app.$.paperDrawerPanel.closeDrawer(); + }; + +})(document); diff --git a/app/styles/app-theme.html b/app/styles/app-theme.html @@ -0,0 +1,214 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../bower_components/polymer/polymer.html"> + +<style is="custom-style"> + + /* + Polymer includes a shim for CSS Custom Properties that we can use for application theming. + Below, you'll find the default palette for the Polymer Starter Kit layout. Feel free to play + with changing the colors used or generate your own palette of colours at MaterialPalette.com. + + See https://www.polymer-project.org/1.0/docs/devguide/styling.html#xscope-styling-details + for further information on custom CSS properties. + */ + + /* Application theme */ + + :root { + --dark-primary-color: #303F9F; + --default-primary-color: #3F51B5; + --light-primary-color: #C5CAE9; + --text-primary-color: #ffffff; /*text/icons*/ + --accent-color: #FF4081; + --primary-background-color: #c5cae9; + --primary-text-color: #212121; + --secondary-text-color: #727272; + --disabled-text-color: #bdbdbd; + --divider-color: #B6B6B6; + + /* Components */ + + /* paper-drawer-panel */ + --drawer-menu-color: #ffffff; + --drawer-border-color: 1px solid #ccc; + --drawer-toolbar-border-color: 1px solid rgba(0, 0, 0, 0.22); + + /* paper-menu */ + --paper-menu-background-color: #fff; + --menu-link-color: #111111; + } + + /* General styles */ + + #drawerToolbar { + color: var(--secondary-text-color); + background-color: var(--drawer-menu-color); + border-bottom: var(--drawer-toolbar-border-color); + } + + paper-scroll-header-panel { + height: 100%; + } + + paper-material { + border-radius: 2px; + height: 100%; + padding: 16px 0 16px 0; + width: calc(98.66% - 16px); + margin: 16px auto; + background: white; + } + + paper-menu iron-icon { + margin-right: 33px; + opacity: 0.54; + } + + .paper-menu > .iron-selected { + color: var(--default-primary-color); + } + + paper-menu a { + @apply(--layout-horizontal); + @apply(--layout-center); + text-decoration: none; + color: var(--menu-link-color); + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; + font-size: 14px; + font-weight: 400; + line-height: 24px; + min-height: 48px; + padding: 0 16px; + } + + paper-toolbar.tall .app-name { + font-size: 40px; + font-weight: 300; + /* Required for main area's paper-scroll-header-panel custom condensing transformation */ + -webkit-transform-origin: left center; + transform-origin: left center; + } + + #mainToolbar .middle-container { + height: 100%; + margin-left: 48px; + } + + #mainToolbar:not(.tall) .middle { + font-size: 18px; + padding-bottom: 0; + } + + #mainToolbar .bottom { + margin-left: 48px; + /* Required for main area's paper-scroll-header-panel custom condensing transformation */ + -webkit-transform-origin: left center; + transform-origin: left center; + } + + /* Height of the scroll area */ + .content { + height: 900px; + } + + #toast .toast-hide-button { + color: #eeff41; + margin: 10px; + } + + /* Breakpoints */ + + /* Small */ + @media (max-width: 600px) { + + paper-material { + --menu-container-display: none; + width: calc(97.33% - 32px); + padding-left: 16px; + padding-right: 16px; + } + + paper-toolbar.tall .app-name { + font-size: 24px; + font-weight: 400; + } + + #drawer .paper-toolbar { + margin-left: 16px; + } + + } + + /* Tablet+ */ + @media (min-width: 601px) { + + paper-material { + width: calc(98% - 46px); + margin-bottom: 32px; + padding-left: 30px; + padding-right: 30px; + } + + #drawer.paper-drawer-panel > [drawer] { + border-right: 1px solid rgba(0, 0, 0, 0.14); + } + + iron-pages { + padding: 48px 62px; + } + + } + + /* Material Design Adaptive Breakpoints */ + /* + Below you'll find CSS media queries based on the breakpoint guidance + published by the Material Design team. You can choose to use, customise + or remove these breakpoints based on your needs. + + http://www.google.com/design/spec/layout/adaptive-ui.html#adaptive-ui-breakpoints + */ + + /* mobile-small */ + @media all and (min-width: 0) and (max-width: 360px) and (orientation: portrait) { } + /* mobile-large */ + @media all and (min-width: 361px) and (orientation: portrait) { } + /* mobile-small-landscape */ + @media all and (min-width: 0) and (max-width: 480px) and (orientation: landscape) { } + /* mobile-large-landscape */ + @media all and (min-width: 481px) and (orientation: landscape) { } + /* tablet-small-landscape */ + @media all and (min-width: 600px) and (max-width: 960px) and (orientation: landscape) { } + /* tablet-large-landscape */ + @media all and (min-width: 961px) and (orientation: landscape) { } + /* tablet-small */ + @media all and (min-width: 600px) and (orientation: portrait) { } + /* tablet-large */ + @media all and (min-width: 601px) and (max-width: 840px) and (orientation : portrait) { } + /* desktop-x-small-landscape */ + @media all and (min-width: 0) and (max-width: 480px) and (orientation: landscape) { } + /* desktop-x-small */ + @media all and (min-width: 0) and (max-width: 480px) and (max-aspect-ratio: 4/3) { } + /* desktop-small-landscape */ + @media all and (min-width: 481px) and (max-width: 840px) and (orientation: landscape) { } + /* desktop-small */ + @media all and (min-width: 481px) and (max-width: 840px) and (max-aspect-ratio: 4/3) { } + /* desktop-medium-landscape */ + @media all and (min-width: 841px) and (max-width: 1280px) and (orientation: landscape) { } + /* desktop-medium */ + @media all and (min-width: 841px) and (max-width: 1280px) and (max-aspect-ratio: 4/3) { } + /* desktop-large */ + @media all and (min-width: 1281px) and (max-width: 1600px) { } + /* desktop-xlarge */ + @media all and (min-width: 1601px) and (max-width: 1920px) { } +</style> diff --git a/app/styles/main.css b/app/styles/main.css @@ -0,0 +1,14 @@ +/* +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +*/ + +body { + background: #fafafa; + font-family: 'Roboto', 'Helvetica Neue', Helvetica, Arial, sans-serif; + color: #333; +} diff --git a/app/styles/shared-styles.html b/app/styles/shared-styles.html @@ -0,0 +1,23 @@ +<link rel="import" href="../bower_components/polymer/polymer.html"> +<link rel="import" href="../bower_components/paper-styles/typography.html"> + +<!-- shared styles for all elements and index.html --> +<dom-module id="shared-styles"> + <template> + <style> + .page-title { + @apply(--paper-font-display2); + } + + paper-menu a > *, paper-menu paper-item > *, paper-menu paper-icon-item > * { + pointer-events: none; + } + + @media (max-width: 600px) { + .page-title { + font-size: 24px!important; + } + } + </style> + </template> +</dom-module> diff --git a/app/sw-import.js b/app/sw-import.js @@ -0,0 +1,10 @@ +/* +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +*/ + +importScripts('bower_components/platinum-sw/service-worker.js'); diff --git a/app/test/index.html b/app/test/index.html @@ -0,0 +1,32 @@ +<!doctype html> +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<html> + + <head> + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> + <title>Elements Test Runner</title> + <meta charset="UTF-8"> + + <script src="../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script> + <script src="../bower_components/web-component-tester/browser.js"></script> + </head> + + <body> + + <script> + WCT.loadSuites(['my-greeting-basic.html', 'my-list-basic.html']); + </script> + + + </body> + +</html> diff --git a/app/test/my-greeting-basic.html b/app/test/my-greeting-basic.html @@ -0,0 +1,50 @@ +<!doctype html> +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<html> +<head> + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> + <title>my-greeting-basic</title> + + <script src="../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script> + <script src="../bower_components/web-component-tester/browser.js"></script> + + <!-- Import the element to test --> + <link rel="import" href="../elements/my-greeting/my-greeting.html"> + +</head> +<body> + + <test-fixture id="basic"> + <template> + <my-greeting></my-greeting> + </template> + </test-fixture> + + <script> + + suite('my-greeting tests', function() { + var greeting, header; + + setup(function() { + greeting = fixture('basic'); + }); + + test('Welcome!', function() { + header = greeting.querySelector('h2'); + assert.equal(header.textContent, 'Welcome!'); + }); + + }); + </script> + +</body> +</html> diff --git a/app/test/my-list-basic.html b/app/test/my-list-basic.html @@ -0,0 +1,65 @@ +<!doctype html> +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<html> +<head> + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> + <title>my-list-basic</title> + + <script src="../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script> + <script src="../bower_components/web-component-tester/browser.js"></script> + + <!-- Import the element to test --> + <link rel="import" href="../elements/my-list/my-list.html"> + +</head> +<body> + + <test-fixture id="basic"> + <template> + <my-list></my-list> + </template> + </test-fixture> + + <script> + suite('my-list tests', function() { + var list, listItems; + + setup(function() { + list = fixture('basic'); + }); + + test('Item lengths should be equalled', function(done) { + // Test a property + // TODO: Fix list.items.push('Foo') causing a WeakMap exception + // Invalid value used as weak map key + list.items = [ + 'Responsive Web App boilerplate', + 'Iron Elements and Paper Elements', + 'End-to-end Build Tooling (including Vulcanize)', + 'Unit testing with Web Component Tester', + 'Routing with Page.js', + 'Offline support with the Platinum Service Worker Elements' + ]; + + // Data bindings will stamp out new DOM asynchronously + // so wait to check for updates + flush(function() { + listItems = list.querySelectorAll('li'); + assert.equal(list.items.length, listItems.length); + done(); + }); + }) + }); + </script> + +</body> +</html> diff --git a/bower.json b/bower.json @@ -0,0 +1,20 @@ +{ + "name": "polymer-starter-kit", + "private": true, + "dependencies": { + "iron-elements": "PolymerElements/iron-elements#^1.0.0", + "neon-elements": "PolymerElements/neon-elements#^1.0.0", + "page": "visionmedia/page.js#~1.6.4", + "paper-elements": "PolymerElements/paper-elements#^1.0.1", + "platinum-elements": "PolymerElements/platinum-elements#^1.1.0", + "polymer": "Polymer/polymer#^1.2.0", + "paper-menu": "PolymerElements/paper-menu#4fecb43601" + }, + "devDependencies": { + "web-component-tester": "*" + }, + "ignore": [], + "resolutions": { + "paper-menu": "4fecb43601" + } +} diff --git a/docs/README.md b/docs/README.md @@ -0,0 +1,8 @@ +# Recipes + +* [Add ES2015 (formally ES6) support using Babel](add-es2015-support-babel.md) +* [Polymer Performance Recipe](polymer-perf.md) +* [Use PSK with Chrome Dev Editor](chrome-dev-editor.md) +* [Deploy to Github Pages](deploy-to-github-pages.md) +* [Deploy to Firebase using Pretty URLs](deploy-to-firebase-pretty-urls.md) +* [Use PSK for Mobile Chrome Apps](mobile-chrome-apps.md) diff --git a/docs/add-es2015-support-babel.md b/docs/add-es2015-support-babel.md @@ -0,0 +1,129 @@ +# Add ES2015 support through Babel + +Although support for ES2015 (formerly ES6) is improving in modern browsers, the majority do not yet support the full set of features. To benefit from the awesomeness of the new ES2015 syntax while keeping backwards compatibility with Polymer's supported browsers, you'll need to transpile your JS code from ES2015 to ES5 + +This recipe focuses on adding an ES2015 to ES5 transpile step to Polymer Starter Kit's build pipeline using [BabelJS](https://babeljs.io/). + + +## Create a transpile gulp task + +- Install the gulp Babel, Sourcemap, Crisper plugins and Babel ES2015 preset: `npm install --save-dev gulp-babel gulp-sourcemaps gulp-crisper babel-preset-es2015` +- Add the following gulp task in the `gulpfile.js` file: + +```patch ++ // Transpile all JS to ES5. ++ gulp.task('js', function () { ++ return gulp.src(['app/**/*.{js,html}', '!app/bower_components/**/*']) ++ .pipe($.sourcemaps.init()) ++ .pipe($.if('*.html', $.crisper({scriptInHead:false}))) // Extract JS from .html files ++ .pipe($.if('*.js', $.babel({ ++ presets: ['es2015'] ++ }))) ++ .pipe($.sourcemaps.write('.')) ++ .pipe(gulp.dest('.tmp/')) ++ .pipe(gulp.dest(dist())); ++ }); +``` + +This task will transpile all JS files and inline JS inside HTML files and also generate sourcemaps. The resulting files are generated in the `.tmp` and the `dist` folders + +[Crisper](https://github.com/PolymerLabs/crisper) extracts JavaScript that's inline to HTML files (such as imports). We need this as Babel does not support transpiling HTML files such as `<script>` tags directly + +Note: At the time of writing Crisper does not generate the sourcemaps. Your app will work but you won't get sourcemaps for files transformed by Crisper. Relevant issues: + + - [ragingwind/gulp-crisper#4](https://github.com/ragingwind/gulp-crisper/issues/4) + - [PolymerLabs/crisper#14](https://github.com/PolymerLabs/crisper/issues/14) + + +## Integrating the transpile task + +Make sure the `js` gulp task is triggered by the common build tasks: + + - In the gulp `serve` task, make sure `js` is triggered initially and on HTML and JS files changes: + +```patch +-gulp.task('serve', ['lint', 'styles', 'elements', 'images'], function () { ++gulp.task('serve', ['lint', 'styles', 'elements', 'images', 'js'], function () { + + ... + +- gulp.watch(['app/**/*.html'], reload); ++ gulp.watch(['app/**/*.html'], ['js', reload]); + gulp.watch(['app/styles/**/*.css'], ['styles', reload]); + gulp.watch(['app/elements/**/*.css'], ['elements', reload]); +- gulp.watch(['app/{scripts,elements}/**/{*.js,*.html}'], ['lint']); ++ gulp.watch(['app/{scripts,elements}/**/{*.js,*.html}'], ['lint', 'js']); + gulp.watch(['app/images/**/*'], reload); +}); +``` + + - In the `default` task make sure `js` is run in parallel to `elements`: + +```patch +gulp.task('default', ['clean'], function (cb) { + + ... + + runSequence( + ['copy', 'styles'], +- 'elements', ++ ['elements', 'js'], + ['lint', 'images', 'fonts', 'html'], + 'vulcanize', // 'cache-config', + cb); +}); +``` + + - In the `html` task replace `app` in the paths by `dist` since dist should already contain all JS and HTML files now transpiled. + + ```patch + // Scan your HTML for assets & optimize them + gulp.task('html', function () { + return optimizeHtmlTask( +- ['app/**/*.html', '!app/{elements,test}/**/*.html'], ++ [dist('/**/*.html'), '!' + dist('/{elements,test}/**/*.html')], + dist()); + }); + ``` + + + - In the `optimizeHtmlTask` function remove the `searchPath` attribute since all assets should be found under the `dist` folder and we want to make sure we are not picking up duplicates and un-transpiled JS files: + +```patch +var optimizeHtmlTask = function (src, dest) { +- var assets = $.useref.assets({searchPath: ['.tmp', 'app', 'dist']}); ++ var assets = $.useref.assets(); +``` + + +## Configure linters for ES2015 + +- Enable ES2015 support in JSCS. Add `"esnext": true` to the `.jscsrc` file: + +```patch +{ ++ "esnext": true, + "preset": "google", + "disallowSpacesInAnonymousFunctionExpression": null, + "excludeFiles": ["node_modules/**"] +} +``` + +- Enable ES2015 support in JSHint. Add `"esnext": true` to the `.jshintrc` file: + +```patch +{ ++ "esnext": true, + "node": true, + "browser": true, +``` + +## Optional - When using shadow-dom instead shady-dom +Place this configuration ([Read more](https://www.polymer-project.org/1.0/docs/devguide/settings.html)) in a separate file like `scripts/polymer-settings` + +```html +<script> + window.Polymer = window.Polymer || {}; + window.Polymer.dom = 'shadow'; +</script> +``` diff --git a/docs/chrome-dev-editor.md b/docs/chrome-dev-editor.md @@ -0,0 +1,52 @@ +# Use Polymer Starter Kit on Chrome Dev Editor + +If you are using a Chromebook, one of the few IDE you can use is [Chrome Dev Editor](https://github.com/GoogleChrome/chromedeveditor). + +To use the Polymer Starter Kit you have to download the [latest release](https://github.com/PolymerElements/polymer-starter-kit/releases) in the `light` flavor (the additional tools can't be used from CDE). + +After downloading the `polymer-starter-kit-light-*.zip` file unpack it in a new folder (for Example `psk-light`) you should have a directory structure like + +![psk-light-folder-p1](https://cloud.githubusercontent.com/assets/1431346/9451900/a73ffcf2-4ab1-11e5-8742-e0b5523ba9d5.png) + + +Before opening the folder inside CDE, we need to move the file `bower.json` to `app/bower.json`, this way running `Bower Update` from CDE's menu, will place the updated packages in `app/bower_components` + +![bower json-post](https://cloud.githubusercontent.com/assets/1431346/9452119/c5826a46-4ab2-11e5-96c5-00cf404d9c50.png) + + +We can now `Open Folder...` inside CDE and start renaming the file `app/manifest.json` to `app/web-app-manifest.json`, followed by updating the link to it in the file `app/index.html` + +![manifest json](https://cloud.githubusercontent.com/assets/1431346/9452182/27e41478-4ab3-11e5-8e40-d7c0f1249feb.png) + + +*This change is needed because `manifest.json` is interpreted by CDE as a [Chrome Apps Manifest](https://developer.chrome.com/extensions/manifest) and the [web app manifest](https://w3c.github.io/manifest/) is slightly different* + +Open `app/elements/routing.html` and add the following code after the last route: + +```javascript +page('*', function () { + app.route = 'home'; +}); +``` + +After the change, the code will look like the following: + +```javascript +... +page('/contact', function () { + app.route = 'contact'; +}); + +page('*', function () { + app.route = 'home'; +}); + +// add #! before urls +page({ + hashbang: true +}); +... +``` + + +Select `app/index.html` and hit run (or press CTRL+R) to see the application running in the browser. diff --git a/docs/deploy-to-firebase-pretty-urls.md b/docs/deploy-to-firebase-pretty-urls.md @@ -0,0 +1,67 @@ +# Deploy to Firebase using Pretty URLs + +Firebase is a very simple and secure way to deploy a Polymer Starter Kit site. You can sign up for a free account and deploy your application in less than 5 minutes. + +The instructions below are based on the [Firebase hosting quick start +guide](https://www.firebase.com/docs/hosting/quickstart.html). + +1. [Sign up for a Firebase account](https://www.firebase.com/signup/) + +1. Install the Firebase command line tools + + npm install -g firebase-tools + + The `-g` flag instructs `npm` to install the package globally so that you + can use the `firebase` command from any directory. You may need + to install the package with `sudo` privileges. + +1. `cd` into your project directory + +1. Inititalize the Firebase application + + firebase init + + Firebase asks you which app you would like to use for hosting. If you just + signed up, you should see one app with a randomly-generated name. You can + use that one. Otherwise go to + [https://www.firebase.com/account](https://www.firebase.com/account) to + create a new app. + +1. Firebase asks you the name of your app's public directory. Enter `dist`. + This works because when you run `gulp` to build your application, PSK + builds everything and places it all in `dist`. So `dist` contains + everything your application needs to run. + +1. Edit firebase.json add rewrites section + + { + "firebase": "polymer-starter-kit", + "public": "dist", + "ignore": [ + "firebase.json", + "**/.*", + "**/node_modules/**" + ], + "rewrites": [ { + "source": "**", + "destination": "/index.html" + } ] + } + +1. Add `<base href="/">` to `head` in index.html + +1. Remove `hashbang: true` in routing.html near bottom. The call to `page` should look like this now: + + page(); + +1. Build + + gulp + +1. Deploy + + firebase deploy + + The URL to your live site is listed in the output. + +You can see a demo of Polymer Starter Kit hosted on Firebase using pretty URLs at https://polymer-starter-kit.firebaseapp.com. diff --git a/docs/deploy-to-github-pages.md b/docs/deploy-to-github-pages.md @@ -0,0 +1,23 @@ +# Deploy to Github Pages + +You can deploy to github pages with a couple minor changes to Polymer Starter Kit: + +1. Uncomment this line `// app.baseUrl = '/polymer-starter-kit/';` in app.js near the top + + ```JavaScript + // Sets app default base URL + app.baseUrl = '/'; + if (window.location.port === '') { // if production + // Uncomment app.baseURL below and + // set app.baseURL to '/your-pathname/' if running from folder in production + // app.baseUrl = '/polymer-starter-kit/'; + } + ``` +2. Change `app.baseUrl = '/polymer-starter-kit/';` to `app.baseUrl = '/your-pathname/';` (ex: if you repo is `github.com/username/bobs-awesome-site` you would change this to `bobs-awesome-site`) +3. Run `gulp build-deploy-gh-pages` from command line +4. To see changes wait 1-2 minutes then load Github pages for your app (ex: http://polymerelements.github.io/polymer-starter-kit) + +### Notes + +* When deploying to Github Pages we recommend using hashbangs which is Polymer Starter Kit default. +* This method should work for most hosting providers when using a subfolder. diff --git a/docs/mobile-chrome-apps.md b/docs/mobile-chrome-apps.md @@ -0,0 +1,131 @@ +# Use Polymer Starter Kit for [Mobile Chrome Apps](https://github.com/MobileChromeApps/mobile-chrome-apps) + +## Getting started + +Polymer Starter Kit could be fully adapted to Mobile Chrome Apps through mobile-friendly features. Mobile Chrome Apps, is based on Apache Cordova, and requires mobile application SDKs such as Android and iOS. so please make sure that installation development tool by following [installation guide](https://github.com/MobileChromeApps/mobile-chrome-apps/blob/master/docs/Installation.md) of Mobile Chrome Apps. And then, You do some further steps to resolve some of restrictions and configurations to use Polymer Starter Kit on Cordova. Looking for a [guide video](https://www.youtube.com/watch?v=-ifgyobPLVg) below to better understand. + +[![](https://camo.githubusercontent.com/7c498c4d60113dd1ea072576df897283100428b6/687474703a2f2f696d672e796f75747562652e636f6d2f76692f2d696667796f62504c56672f302e6a7067)](https://www.youtube.com/watch?v=-ifgyobPLVg) + +## Download Polymer Starter Kit into your workspace + +To download and preparation, follow this [guide of Polymer Starter Kit](https://github.com/PolymerElements/polymer-starter-kit#getting-started). Make sure that install all of dependencies of npm and Bower. + +## Create a Cordova project + +Create a Cordova project in path `polymer-starter-kit` by following command. `platform` is the path for Cordova project files, `com.your.app` is the project name/id and next following string is the description for your app. + +```sh +cca create platform com.your.app "Your Polymer Starter Kit App" +``` + +If you have no problems while creating a project you will seeing the message of installing successful coming from Cordova and have the tree of the project below. + +```sh +└── polymer-starter-kit + └── app + │   ├── elements + │   ├── images + │   ├── index.html + │   ├── manifest.json + │   ├── scripts + │   ├── styles + │   └── test + ├── bower.json + ├── bower_components + ├── docs + ├── gulpfile.js + ├── node_modules + ├── package.json + ├── platform + │   ├── config.xml + │   ├── hooks + │   ├── platforms + │   ├── plugins + │   └── www +``` + +For further informations of Cordova, please visit [corodova document](https://github.com/MobileChromeApps/mobile-chrome-apps/tree/master/docs) + +## Configuration + +You need to have some changes of configuration to fit for Mobile Chrome Apps as it was mentioned above. + +### Configure path for app built by gulp + +- Change the path `dist` in `gulpfile.js` from `dist` to `platform/www/app`, then the app built with Polymer Starter Kit will be placed under `platform/www` will be used by Cordova. + ```js + var DIST = 'platform/www/app'; + ``` + +- Change the path in `platform/www/background.js` into new path + ```js + chrome.app.runtime.onLaunched.addListener(function() { + chrome.app.window.create('app/index.html', { + width: 244, + height: 380, + }); + }); + ``` + +- Add path `/app` to `app.baseURL` in `app/scripts/app.js'. `platform/www` is root path of app that will prevent errors coming from page routing. + ```js + app.baseUrl = '/app'; + ``` + +### Update gulp tasks + +- Using `polybuild(vulcanize + crisper)` task is mandatory because of Chrome Apps doesn't allow inline script blocks according to [CSP](https://developer.chrome.com/apps/contentSecurityPolicy). You should replace current `vulcanize` task with new task below. To do this install `polybuild` first with `npm install --save-dev polybuild` command + ```js + // load polybuild + var polybuild = require('polybuild'); + + // Vulcanize granular configuration + gulp.task('vulcanize', function() { + return gulp.src('app/elements/elements.html') + .pipe(polybuild({maximumCrush: true})) + .pipe($.rename(function(file) { + if (file.extname === '.html') { + file.basename = file.basename.replace('.build', ''); + } + })) + .pipe(gulp.dest(dist('elements'))) + .pipe($.size({title: 'vulcanize'})); + }); + ``` + +### More updates + +- Remove useless files generated from Cordova. + ```sh + rm platform/www/index.* + ``` +- To complete first route for `home` you need to put try/catch block into the first route code on starting app, in `app/elements/routing.html`, because Chrome Apps doesn't allow using `history` APIs which related to error message `history.pushState/replaceState is not available in packaged apps`. + ```js + try { + page({ + hashbang: true + }); + } catch (e) { + app.route = 'home'; + } + ``` + +- Using `@import` instead of `link` to download external Google robot fonts which is related to `Refused to load the stylesheet` errors. Update code in `bower_components/font-roboto/roboto.html` to using `@import` code below + ``` + @import url(https://fonts.googleapis.com/css?family=Roboto:400,300,300italic,400italic,500,500italic,700,700italic); + @import url(https://fonts.googleapis.com/css?family=Roboto+Mono:400,700); + ``` + +## Build and run app + +After done of above steps. run this command on root path that let you see Chrome Apps built with Polymer Starter Kit. + +```sh +gulp && cd platform && cca run chrome +``` + +or to run on Android emulator or devices + +```sh +gulp && cd platform && cca run android +``` diff --git a/docs/polymer-perf.md b/docs/polymer-perf.md @@ -0,0 +1,100 @@ +### Polymer Performance Recipe + +In the following write up we are going to take a look at how to optimize the loading of Web Component enabled websites. The goal here is not to give you a copy and paste approach, but rather to give you the starting components and thought process with how to optimize your web app given your domain constraints. + +Current native support for Web Components is limited but growing, with only Chrome and Opera having a “fully" implemented spec. Due to the limited support, using Polymer or any web components in production across more than just chrome requires you to load a polyfill. As with any polyfill there is a performance tradeoff, in the run time performance, spec compliance, as well as the network cost overhead. Lets dive into a few approaches that you can use to conditionally load the polyfill only when it is required. + +The first step in conditionally loading the Web Component polyfill is detecting whether or not the environment that we are in supports the features that are required. + +Over in GitHub land @geenlen has cooked up a nifty technique bit of code to do this work for us: + +```js +var webComponentsSupported = ('registerElement' in document + && 'import' in document.createElement('link') + && 'content' in document.createElement('template')); +``` + +Once we know if things are supported or not we can then dynamically load our polyfill and then load up our custom elements so that our app will be able to properly upgrade our custom elements. + +```js +if (webComponentsSupported) { + loadElements(); +} else { + loadWebComponentPolyfill(loadElements) +} +``` + +This bit of code can be placed directly in [`app.js`](https://github.com/PolymerElements/polymer-starter-kit/blob/master/app/scripts/app.js), right under the beginning of the IIFE. + +Now that we have our initial sniff and load call, let’s take a look at the code for `loadWebComponentPolyfill`, and how exactly it works. + +```js +function loadWebComponentPolyfill(cb) { + var polyfill = document.createElement('script'); + polyfill.onload = cb || null; + polyfill.src = 'webcomponents-lite.min.js'; + document.head.appendChild(polyfill); +} +``` + +So what is going on here, how does it work? The first thing that this method does is dynamically create a script tag, then conditionally assign a callback when the resource loads, the code then sets the src of the script tag, and then injects the script tag into the head of our document. Once the tag is placed inside of our document, the network request will start and the resource is fully downloaded the callback will be invoked. + +Awesome! So now let’s move onto the logic around `loadElements`. + +You might be wondering why `loadElements` is even needed? Why can we not just `<link rel="import" href="path_to_elements.html">` directly in our html. The reason why `loadElements` is needed is because we are loading the webComponents polyfill async to the initial page load, therefore we can not assume that our import statements will always work across browsers and browser versions, rather we need to explicitly call into loadElements only after we are sure the current environment supports webComponents (even if we have to polyfill it first). + +```js +function loadElements() { + var bundle = document.createElement('link'); + bundle.rel = 'import'; + bundle.href = 'elements/path_to_bundle.html'; + + document.head.appendChild(bundle); +} +``` + +`loadElements` follows a very similar pattern as `loadWebComponentPolyfill`, only this time we are dynamically injecting a link tag into our head that will load our element bundle. Now that we have both of these methods defined, we are left with a very basic example of loading our polyfill and element async to the `window.onload` event. + +This approach opens up the possibility for you to only have users download the elements that they need for specific pages in your app. Consider for instance an application with an admin panel and a general app view. Given the fact that most users in our made up app do not go to the admin panel too often, there is no need for them to always incur the cost of downloading the admin suite of elements. Instead we will only have users download the “bundle" that they need depending on what page they enter on. + +For example with page.js your router could be structured as follows to optimize page load time, given a few assumptions about how users will be interacting with your app. + +```js +page.on('admin', ensureWebComponentSupport, function() { + loadElementBundle('admin'); + renderAdminPane(); +}); +``` + +#### Further Thoughts + +With Polymer, it is easy to fall into the trap of getting a flash of unstyled content, or a blank page while the polyfill and elements are downloading. The best way to avoid these pitfalls is to use a "loading" screen approach. The simplest of the loading approach to create a "splash" screen to display while your elements bundle is downloading. + +You can easily modify `loadElements` to enable this type of behavior. + +```js +function loadElements() { + document.body.innerHTML = '<div><!-- loading screen markup → --></div>'; + bundle.rel = 'import'; + bundle.href = 'elements/path_to_bundle.html'; + bundle.onload = function() { + document.body.innerHTML = '<real-markup></real-markup>'; + }; + + document.head.appendChild(bundle); +} +``` + +You can take this concept of a loading screen one step further by instead of showing a loading screen show a screen that looks like a lite version of your app. By this I mean simple shapes and blocks that match the color and blocks of your app once your elements are fully upgraded, so that your user has a faster perceived loading time. + +Hopefully these approaches give you some ideas on how to make your app lightning fast. + +We hope to explore further ideas including [application shells](https://github.com/ebidel/polymer-experiments/blob/master/polymersummit/fouc/appshell.html) and being smart about your first meaningful paint in the near future. + +-------- + +Further reading + +* [Fast Polymer app loading](https://gist.github.com/ebidel/1ba71473d687d0567bd3) from Eric Bidelman +* [Polymer Perf Patterns](https://www.youtube.com/watch?v=Yr84DpNaMfk) from Eric Bidelman +* [Polymer for the Performance-obsessed](https://aerotwist.com/blog/polymer-for-the-performance-obsessed/) from Paul Lewis diff --git a/gulpfile.js b/gulpfile.js @@ -0,0 +1,330 @@ +/* +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +*/ + +'use strict'; + +// Include Gulp & tools we'll use +var gulp = require('gulp'); +var $ = require('gulp-load-plugins')(); +var del = require('del'); +var runSequence = require('run-sequence'); +var browserSync = require('browser-sync'); +var reload = browserSync.reload; +var merge = require('merge-stream'); +var path = require('path'); +var fs = require('fs'); +var glob = require('glob-all'); +var historyApiFallback = require('connect-history-api-fallback'); +var packageJson = require('./package.json'); +var crypto = require('crypto'); +var ensureFiles = require('./tasks/ensure-files.js'); + +// var ghPages = require('gulp-gh-pages'); + +var AUTOPREFIXER_BROWSERS = [ + 'ie >= 10', + 'ie_mob >= 10', + 'ff >= 30', + 'chrome >= 34', + 'safari >= 7', + 'opera >= 23', + 'ios >= 7', + 'android >= 4.4', + 'bb >= 10' +]; + +var DIST = 'dist'; + +var dist = function(subpath) { + return !subpath ? DIST : path.join(DIST, subpath); +}; + +var styleTask = function(stylesPath, srcs) { + return gulp.src(srcs.map(function(src) { + return path.join('app', stylesPath, src); + })) + .pipe($.changed(stylesPath, {extension: '.css'})) + .pipe($.autoprefixer(AUTOPREFIXER_BROWSERS)) + .pipe(gulp.dest('.tmp/' + stylesPath)) + .pipe($.minifyCss()) + .pipe(gulp.dest(dist(stylesPath))) + .pipe($.size({title: stylesPath})); +}; + +var imageOptimizeTask = function(src, dest) { + return gulp.src(src) + .pipe($.imagemin({ + progressive: true, + interlaced: true + })) + .pipe(gulp.dest(dest)) + .pipe($.size({title: 'images'})); +}; + +var optimizeHtmlTask = function(src, dest) { + var assets = $.useref.assets({ + searchPath: ['.tmp', 'app'] + }); + + return gulp.src(src) + .pipe(assets) + // Concatenate and minify JavaScript + .pipe($.if('*.js', $.uglify({ + preserveComments: 'some' + }))) + // Concatenate and minify styles + // In case you are still using useref build blocks + .pipe($.if('*.css', $.minifyCss())) + .pipe(assets.restore()) + .pipe($.useref()) + // Minify any HTML + .pipe($.if('*.html', $.minifyHtml({ + quotes: true, + empty: true, + spare: true + }))) + // Output files + .pipe(gulp.dest(dest)) + .pipe($.size({ + title: 'html' + })); +}; + +// Compile and automatically prefix stylesheets +gulp.task('styles', function() { + return styleTask('styles', ['**/*.css']); +}); + +gulp.task('elements', function() { + return styleTask('elements', ['**/*.css']); +}); + +// Ensure that we are not missing required files for the project +// "dot" files are specifically tricky due to them being hidden on +// some systems. +gulp.task('ensureFiles', function(cb) { + var requiredFiles = ['.jscsrc', '.jshintrc', '.bowerrc']; + + ensureFiles(requiredFiles.map(function(p) { + return path.join(__dirname, p); + }), cb); +}); + +// Lint JavaScript +gulp.task('lint', ['ensureFiles'], function() { + return gulp.src([ + 'app/scripts/**/*.js', + 'app/elements/**/*.js', + 'app/elements/**/*.html', + 'gulpfile.js' + ]) + .pipe(reload({ + stream: true, + once: true + })) + + // JSCS has not yet a extract option + .pipe($.if('*.html', $.htmlExtract())) + .pipe($.jshint()) + .pipe($.jscs()) + .pipe($.jscsStylish.combineWithHintResults()) + .pipe($.jshint.reporter('jshint-stylish')) + .pipe($.if(!browserSync.active, $.jshint.reporter('fail'))); +}); + +// Optimize images +gulp.task('images', function() { + return imageOptimizeTask('app/images/**/*', dist('images')); +}); + +// Copy all files at the root level (app) +gulp.task('copy', function() { + var app = gulp.src([ + 'app/*', + '!app/test', + '!app/elements', + '!app/bower_components', + '!app/cache-config.json' + ], { + dot: true + }).pipe(gulp.dest(dist())); + + // Copy over only the bower_components we need + // These are things which cannot be vulcanized + var bower = gulp.src([ + 'app/bower_components/{webcomponentsjs,platinum-sw,sw-toolbox,promise-polyfill}/**/*' + ]).pipe(gulp.dest(dist('bower_components'))); + + return merge(app, bower) + .pipe($.size({ + title: 'copy' + })); +}); + +// Copy web fonts to dist +gulp.task('fonts', function() { + return gulp.src(['app/fonts/**']) + .pipe(gulp.dest(dist('fonts'))) + .pipe($.size({ + title: 'fonts' + })); +}); + +// Scan your HTML for assets & optimize them +gulp.task('html', function() { + return optimizeHtmlTask( + ['app/**/*.html', '!app/{elements,test,bower_components}/**/*.html'], + dist()); +}); + +// Vulcanize granular configuration +gulp.task('vulcanize', function() { + return gulp.src('app/elements/elements.html') + .pipe($.vulcanize({ + stripComments: true, + inlineCss: true, + inlineScripts: true + })) + .pipe(gulp.dest(dist('elements'))) + .pipe($.size({title: 'vulcanize'})); +}); + +// Generate config data for the <sw-precache-cache> element. +// This include a list of files that should be precached, as well as a (hopefully unique) cache +// id that ensure that multiple PSK projects don't share the same Cache Storage. +// This task does not run by default, but if you are interested in using service worker caching +// in your project, please enable it within the 'default' task. +// See https://github.com/PolymerElements/polymer-starter-kit#enable-service-worker-support +// for more context. +gulp.task('cache-config', function(callback) { + var dir = dist(); + var config = { + cacheId: packageJson.name || path.basename(__dirname), + disabled: false + }; + + glob([ + 'index.html', + './', + 'bower_components/webcomponentsjs/webcomponents-lite.min.js', + '{elements,scripts,styles}/**/*.*'], + {cwd: dir}, function(error, files) { + if (error) { + callback(error); + } else { + config.precache = files; + + var md5 = crypto.createHash('md5'); + md5.update(JSON.stringify(config.precache)); + config.precacheFingerprint = md5.digest('hex'); + + var configPath = path.join(dir, 'cache-config.json'); + fs.writeFile(configPath, JSON.stringify(config), callback); + } + }); +}); + +// Clean output directory +gulp.task('clean', function() { + return del(['.tmp', dist()]); +}); + +// Watch files for changes & reload +gulp.task('serve', ['lint', 'styles', 'elements', 'images'], function() { + browserSync({ + port: 5000, + notify: false, + logPrefix: 'PSK', + snippetOptions: { + rule: { + match: '<span id="browser-sync-binding"></span>', + fn: function(snippet) { + return snippet; + } + } + }, + // Run as an https by uncommenting 'https: true' + // Note: this uses an unsigned certificate which on first access + // will present a certificate warning in the browser. + // https: true, + server: { + baseDir: ['.tmp', 'app'], + middleware: [historyApiFallback()] + } + }); + + gulp.watch(['app/**/*.html'], reload); + gulp.watch(['app/styles/**/*.css'], ['styles', reload]); + gulp.watch(['app/elements/**/*.css'], ['elements', reload]); + gulp.watch(['app/{scripts,elements}/**/{*.js,*.html}'], ['lint']); + gulp.watch(['app/images/**/*'], reload); +}); + +// Build and serve the output from the dist build +gulp.task('serve:dist', ['default'], function() { + browserSync({ + port: 5001, + notify: false, + logPrefix: 'PSK', + snippetOptions: { + rule: { + match: '<span id="browser-sync-binding"></span>', + fn: function(snippet) { + return snippet; + } + } + }, + // Run as an https by uncommenting 'https: true' + // Note: this uses an unsigned certificate which on first access + // will present a certificate warning in the browser. + // https: true, + server: dist(), + middleware: [historyApiFallback()] + }); +}); + +// Build production files, the default task +gulp.task('default', ['clean'], function(cb) { + // Uncomment 'cache-config' if you are going to use service workers. + runSequence( + ['copy', 'styles'], + 'elements', + ['lint', 'images', 'fonts', 'html'], + 'vulcanize', // 'cache-config', + cb); +}); + +// Build then deploy to GitHub pages gh-pages branch +gulp.task('build-deploy-gh-pages', function(cb) { + runSequence( + 'default', + 'deploy-gh-pages', + cb); +}); + +// Deploy to GitHub pages gh-pages branch +gulp.task('deploy-gh-pages', function() { + return gulp.src(dist('**/*')) + // Check if running task from Travis CI, if so run using GH_TOKEN + // otherwise run using ghPages defaults. + .pipe($.if(process.env.TRAVIS === 'true', $.ghPages({ + remoteUrl: 'https://$GH_TOKEN@github.com/polymerelements/polymer-starter-kit.git', + silent: true, + branch: 'gh-pages' + }), $.ghPages())); +}); + +// Load tasks for web-component-tester +// Adds tasks for `gulp test:local` and `gulp test:remote` +require('web-component-tester').gulp.init(gulp); + +// Load custom tasks from the `tasks` directory +try { + require('require-dir')('tasks'); +} catch (err) {} diff --git a/package.json b/package.json @@ -0,0 +1,43 @@ +{ + "private": true, + "devDependencies": { + "browser-sync": "^2.7.7", + "connect-history-api-fallback": "^1.1.0", + "del": "^2.0.2", + "glob-all": "^3.0.1", + "gulp": "^3.8.5", + "gulp-autoprefixer": "^3.1.0", + "gulp-cache": "^0.4.0", + "gulp-changed": "^1.0.0", + "gulp-gh-pages": "^0.5.4", + "gulp-html-extract": "^0.0.3", + "gulp-if": "^2.0.0", + "gulp-imagemin": "^2.2.1", + "gulp-jscs": "^3.0.0", + "gulp-jscs-stylish": "^1.1.2", + "gulp-jshint": "^1.6.3", + "gulp-load-plugins": "^1.1.0", + "gulp-minify-css": "^1.2.1", + "gulp-minify-html": "^1.0.2", + "gulp-rename": "^1.2.0", + "gulp-replace": "^0.5.4", + "gulp-size": "^2.0.0", + "gulp-uglify": "^1.2.0", + "gulp-useref": "^2.1.0", + "gulp-vulcanize": "^6.0.0", + "jshint-stylish": "^2.0.0", + "merge-stream": "^1.0.0", + "require-dir": "^0.3.0", + "run-sequence": "^1.0.2", + "vulcanize": ">= 1.4.2", + "web-component-tester": "^4.0.0" + }, + "scripts": { + "test": "gulp test:local", + "start": "gulp serve", + "lint": "gulp lint" + }, + "engines": { + "node": ">=0.10.0" + } +} diff --git a/tasks/ensure-files.js b/tasks/ensure-files.js @@ -0,0 +1,34 @@ +var fs = require('fs'); + +/** + * @param {Array<string>} files + * @param {Function} cb + */ + +function ensureFiles(files, cb) { + var missingFiles = files.reduce(function(prev, filePath) { + var fileFound = false; + + try { + fileFound = fs.statSync(filePath).isFile(); + } catch (e) { } + + if (!fileFound) { + prev.push(filePath + ' Not Found'); + } + + return prev; + }, []); + + if (missingFiles.length) { + var err = new Error('Missing Required Files\n' + missingFiles.join('\n')); + } + + if (cb) { + cb(err); + } else if (err) { + throw err; + } +} + +module.exports = ensureFiles; diff --git a/travis-runner.sh b/travis-runner.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -o pipefail + +if [ "$TRAVIS_BRANCH" = "master" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ] +then + git config --global user.email "samccone@gmail.com" && \ + git config --global user.name "auto deployer" && \ + echo "Deploying!" && \ + sed -i.tmp "s/\/\/ app.baseUrl = '\/polymer-starter-kit/app.baseUrl = '\/polymer-starter-kit/" app/scripts/app.js && \ + rm app/scripts/app.js.tmp && \ + bower i && \ + gulp build-deploy-gh-pages && \ + sed -i.tmp "s/app.baseUrl = '\/polymer-starter-kit/\/\/ app.baseUrl = '\/polymer-starter-kit/" app/scripts/app.js && \ + rm app/scripts/app.js.tmp +else + npm run lint + npm test +fi diff --git a/wct.conf.js b/wct.conf.js @@ -0,0 +1,18 @@ +var path = require('path'); + +var ret = { + 'suites': ['app/test'], + 'webserver': { + 'pathMappings': [] + } +}; + +var mapping = {}; +var rootPath = (__dirname).split(path.sep).slice(-1)[0]; + +mapping['/components/' + rootPath + +'/app/bower_components'] = 'bower_components'; + +ret.webserver.pathMappings.push(mapping); + +module.exports = ret;