diff --git a/.bowerrc b/.bowerrc new file mode 100644 index 00000000..1f984984 --- /dev/null +++ b/.bowerrc @@ -0,0 +1,5 @@ +{ + "directory": "vendor", + "json": "bower.json" +} + diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..dcf48bb8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.sw* +*~ +build/ +bin/ +node_modules/ +vendor/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..e69de29b diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..9c33c2f6 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +language: node_js +node_js: + - "0.10" + +before_script: + - export DISPLAY=:99.0 + - sh -e /etc/init.d/xvfb start + - npm install --quiet -g grunt-cli karma bower + - bower install + +script: grunt + diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..2f93d86e --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,125 @@ +# 0.3.1 (2013-09-13) + +## Features + +* Page titles are now set via state objects ([33de8097](git@github.com:joshdmiller/ng-boilerplate/commit/33de8097)) +* Append pkg.version to JS and CSS ([90e1b71f](git@github.com:joshdmiller/ng-boilerplate/commit/90e1b71f)) +* Vendor CSS is copied and concatenated with the app's CSS ([dda8792c](git@github.com:joshdmiller/ng-boilerplate/commit/dda8792c)) +* Vendor assets are copied to the build too ([29502bff](git@github.com:joshdmiller/ng-boilerplate/commit/29502bff)) +* Treat JS in src/assets as assets (i.e. don't do anything with it) ([99b50751](git@github.com:joshdmiller/ng-boilerplate/commit/99b50751)) +* Added PhantomJS support ([89acf5f6](git@github.com:joshdmiller/ng-boilerplate/commit/89acf5f6)) +* Files for use only in testing are now configurable ([a04e663b](git@github.com:joshdmiller/ng-boilerplate/commit/a04e663b)) + +## Bug fixes + +* CopyPasteException in index.html comments ([3a0596a7](git@github.com:joshdmiller/ng-boilerplate/commit/3a0596a7)) +* Fixed typos in the README ([5ae95393](git@github.com:joshdmiller/ng-boilerplate/commit/5ae95393)), ([8c362208](git@github.com:joshdmiller/ng-boilerplate/commit/8c362208)), and ([6b617282](git@github.com:joshdmiller/ng-boilerplate/commit/6b617282)) +* Vendor files were added to build twice ([09277b74](git@github.com:joshdmiller/ng-boilerplate/commit/09277b74)) +* IE7 Font Awesome stylesheet pointed nowhere ([515673b1](git@github.com:joshdmiller/ng-boilerplate/commit/515673b1)) + +# 0.3.0 (2013-06-25) + +## Features +### build + +* split build into build+compile ([97fb290d](https://github.com/joshdmiller/ng-boilerplate/commits/97fb290d)) +* Moved config to separate file ([ff5d8b58](https://github.com/joshdmiller/ng-boilerplate/commits/ff5d8b58)) +* Added grunt-bump to ease releasing ([27312de1](https://github.com/joshdmiller/ng-boilerplate/commits/27312de1)) +* Added changelog generation ([328d25d2](https://github.com/joshdmiller/ng-boilerplate/commits/328d25d2)) +* karma config managed automatically ([3384b6fd](https://github.com/joshdmiller/ng-boilerplate/commits/3384b6fd)) +* CoffeeScript support ([0f308f2f](https://github.com/joshdmiller/ng-boilerplate/commits/0f308f2f)) + +### * + +* switched to ui-router for state mgmt ([7bec0378](https://github.com/joshdmiller/ng-boilerplate/commits/7bec0378)) + +## Bug fixes +### build + +* Karma no longer hangs the watch (([f66cfcc6])(https://github.com/joshdmiller/ng-boilerplate/commits/f66cfcc6)) + + + +# 0.2.0 (2013-05-10) + +## Features +### build + +* live reload added through grunt-watch ([653df741](https://github.com/joshdmiller/ng-boilerplate/commits/653df741)) + +* Add grunt ng-min for annotation ([9c529ccb](https://github.com/joshdmiller/ng-boilerplate/commits/9c529ccb)) + +### * + +* far better Bower integration ([864c2656](https://github.com/joshdmiller/ng-boilerplate/commits/864c2656)) + +* included AngularUI `utils` to use uiRoute ([df08e4be](https://github.com/joshdmiller/ng-boilerplate/commits/df08e4be)) + + + + + + +# 0.1.0 (2013-03-11) + +## Features +### * + +* Initial application structure ([7c149227](https://github.com/joshdmiller/ng-boilerplate/commits/7c149227)) + +* improved navigation styling and added home page tpl ([e1a655e0](https://github.com/joshdmiller/ng-boilerplate/commits/e1a655e0)) + +### app + +* added current route indication to menu with appropriate unit test ([14d35da8](https://github.com/joshdmiller/ng-boilerplate/commits/14d35da8)) + +### index + +* improved navbar style and added additional links ([a7c4504c](https://github.com/joshdmiller/ng-boilerplate/commits/a7c4504c)) + +### about + +* Added an about page with some descriptive content ([290704ab](https://github.com/joshdmiller/ng-boilerplate/commits/290704ab)) + +* Added placeholders demo to about page ([89a06e9f](https://github.com/joshdmiller/ng-boilerplate/commits/89a06e9f)) + +### titleService + +* dynamic title support) ([3db6ec2b](https://github.com/joshdmiller/ng-boilerplate/commits/3db6ec2b)) + +* suffix is now customizable ([9f8b4c73](https://github.com/joshdmiller/ng-boilerplate/commits/9f8b4c73)) + +### activeIfCurrentDirective + +* created directory to test for current route ([0ac1f4b4](https://github.com/joshdmiller/ng-boilerplate/commits/0ac1f4b4)) + +### home + +* replaced placeholder text with mrktg copy ([dcaf7237](https://github.com/joshdmiller/ng-boilerplate/commits/dcaf7237)) + +* added google +1 button ([98d3312b](https://github.com/joshdmiller/ng-boilerplate/commits/98d3312b)) + + + +## Bug fixes +### build + +* Removed unnecessary step from delta:unittest ([5ffbfd78](https://github.com/joshdmiller/ng-boilerplate/commits/5ffbfd78)) + +* delta tasks that concat must also uglify ([926983f8](https://github.com/joshdmiller/ng-boilerplate/commits/926983f8)) + +### test-config + +* Change browser-name case, add browser list ([682b1ea4](https://github.com/joshdmiller/ng-boilerplate/commits/682b1ea4)) + +### home + +* corrected typo in tweet button URL ([b9920eea](https://github.com/joshdmiller/ng-boilerplate/commits/b9920eea)) + +### testacular + +* fixed typo in browser docstring ([11a60fa7](https://github.com/joshdmiller/ng-boilerplate/commits/11a60fa7)) + + + + diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 00000000..51a73705 --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,678 @@ +module.exports = function ( grunt ) { + + /** + * Load required Grunt tasks. These are installed based on the versions listed + * in `package.json` when you do `npm install` in this directory. + */ + grunt.loadNpmTasks('grunt-contrib-clean'); + grunt.loadNpmTasks('grunt-contrib-copy'); + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-contrib-concat'); + grunt.loadNpmTasks('grunt-contrib-watch'); + grunt.loadNpmTasks('grunt-contrib-uglify'); + grunt.loadNpmTasks('grunt-contrib-coffee'); + grunt.loadNpmTasks('grunt-conventional-changelog'); + grunt.loadNpmTasks('grunt-bump'); + grunt.loadNpmTasks('grunt-coffeelint'); + grunt.loadNpmTasks('grunt-recess'); + grunt.loadNpmTasks('grunt-karma'); + grunt.loadNpmTasks('grunt-ngmin'); + grunt.loadNpmTasks('grunt-html2js'); + grunt.loadNpmTasks('grunt-gjslint'); + + /** + * Load in our build configuration file. + */ + var userConfig = require( './build.config.js' ); + + /** + * This is the configuration object Grunt uses to give each plugin its + * instructions. + */ + var taskConfig = { + /** + * We read in our `package.json` file so we can access the package name and + * version. It's already there, so we don't repeat ourselves here. + */ + pkg: grunt.file.readJSON("package.json"), + + /** + * The banner is the comment that is placed at the top of our compiled + * source files. It is first processed as a Grunt template, where the `<%=` + * pairs are evaluated based on this very configuration object. + */ + meta: { + banner: + '/**\n' + + ' * <%= pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' + + ' * <%= pkg.homepage %>\n' + + ' *\n' + + ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' + + ' * Licensed <%= pkg.licenses.type %> <<%= pkg.licenses.url %>>\n' + + ' */\n' + }, + + gjslint: { + options: { + flags: [ + '--disable 220', //ignore error code 220 from gjslint + '--max_line_length 120' + ], + reporter: { + name: 'console' + } + }, + all: { + src: '<%= app_files.js %>' + } + }, + + /** + * Creates a changelog on a new version. + */ + changelog: { + options: { + dest: 'CHANGELOG.md', + template: 'changelog.tpl' + } + }, + + /** + * Increments the version number, etc. + */ + bump: { + options: { + files: [ + "package.json", + "bower.json" + ], + commit: false, + commitMessage: 'chore(release): v%VERSION%', + commitFiles: [ + "package.json", + "client/bower.json" + ], + createTag: false, + tagName: 'v%VERSION%', + tagMessage: 'Version %VERSION%', + push: false, + pushTo: 'origin' + } + }, + + /** + * The directories to delete when `grunt clean` is executed. + */ + clean: [ + '<%= build_dir %>', + '<%= compile_dir %>' + ], + + /** + * The `copy` task just copies files from A to B. We use it here to copy + * our project assets (images, fonts, etc.) and javascripts into + * `build_dir`, and then to copy the assets to `compile_dir`. + */ + copy: { + build_app_assets: { + files: [ + { + src: [ '**' ], + dest: '<%= build_dir %>/assets/', + cwd: 'src/assets', + expand: true + } + ] + }, + build_vendor_assets: { + files: [ + { + src: [ '<%= vendor_files.assets %>' ], + dest: '<%= build_dir %>/assets/', + cwd: '.', + expand: true, + flatten: true + } + ] + }, + build_vendor_fonts: { + files: [ + { + src: [ '<%= vendor_files.fonts %>' ], + dest: '<%= build_dir %>/fonts/', + cwd: '.', + expand: true, + flatten: true + } + ] + }, + build_appjs: { + files: [ + { + src: [ '<%= app_files.js %>' ], + dest: '<%= build_dir %>/', + cwd: '.', + expand: true + } + ] + }, + build_vendorjs: { + files: [ + { + src: [ '<%= vendor_files.js %>' ], + dest: '<%= build_dir %>/', + cwd: '.', + expand: true + } + ] + }, + compile_assets: { + files: [ + { + src: [ '**' ], + dest: '<%= compile_dir %>/assets', + cwd: '<%= build_dir %>/assets', + expand: true + } + ] + }, + compile_fonts: { + files: [ + { + src: [ '**' ], + dest: '<%= compile_dir %>/fonts', + cwd: '<%= build_dir %>/fonts', + expand: true + } + ] + } + }, + + /** + * `grunt concat` concatenates multiple source files into a single file. + */ + concat: { + /** + * The `build_css` target concatenates compiled CSS and vendor CSS + * together. + */ + build_css: { + src: [ + '<%= vendor_files.css %>', + '<%= recess.build.dest %>' + ], + dest: '<%= recess.build.dest %>' + }, + /** + * The `compile_js` target is the concatenation of our application source + * code and all specified vendor source code into a single file. + */ + compile_js: { + options: { + banner: '<%= meta.banner %>' + }, + src: [ + '<%= vendor_files.js %>', + 'module.prefix', + '<%= build_dir %>/src/**/*.js', + '<%= html2js.app.dest %>', + '<%= html2js.common.dest %>', + 'module.suffix' + ], + dest: '<%= compile_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.js' + } + }, + + /** + * `grunt coffee` compiles the CoffeeScript sources. To work well with the + * rest of the build, we have a separate compilation task for sources and + * specs so they can go to different places. For example, we need the + * sources to live with the rest of the copied JavaScript so we can include + * it in the final build, but we don't want to include our specs there. + */ + coffee: { + source: { + options: { + bare: true + }, + expand: true, + cwd: '.', + src: [ '<%= app_files.coffee %>' ], + dest: '<%= build_dir %>', + ext: '.js' + } + }, + + /** + * `ng-min` annotates the sources before minifying. That is, it allows us + * to code without the array syntax. + */ + ngmin: { + compile: { + files: [ + { + src: [ '<%= app_files.js %>' ], + cwd: '<%= build_dir %>', + dest: '<%= build_dir %>', + expand: true + } + ] + } + }, + + /** + * Minify the sources! + */ + uglify: { + compile: { + options: { + banner: '<%= meta.banner %>' + }, + files: { + '<%= concat.compile_js.dest %>': '<%= concat.compile_js.dest %>' + } + } + }, + + /** + * `recess` handles our LESS compilation and uglification automatically. + * Only our `main.less` file is included in compilation; all other files + * must be imported from this file. + */ + recess: { + build: { + src: [ '<%= app_files.less %>' ], + dest: '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css', + options: { + compile: true, + compress: false, + noUnderscores: false, + noIDs: false, + zeroUnits: false + } + }, + compile: { + src: [ '<%= recess.build.dest %>' ], + dest: '<%= recess.build.dest %>', + options: { + compile: true, + compress: true, + noUnderscores: false, + noIDs: false, + zeroUnits: false + } + } + }, + + /** + * `jshint` defines the rules of our linter as well as which files we + * should check. This file, all javascript sources, and all our unit tests + * are linted based on the policies listed in `options`. But we can also + * specify exclusionary patterns by prefixing them with an exclamation + * point (!); this is useful when code comes from a third party but is + * nonetheless inside `src/`. + */ + jshint: { + src: [ + '<%= app_files.js %>' + ], + test: [ + '<%= app_files.jsunit %>' + ], + gruntfile: [ + 'Gruntfile.js' + ], + options: { + curly: true, + immed: true, + newcap: true, + noarg: true, + sub: true, + boss: true, + eqnull: true + }, + globals: {} + }, + + /** + * `coffeelint` does the same as `jshint`, but for CoffeeScript. + * CoffeeScript is not the default in ngBoilerplate, so we're just using + * the defaults here. + */ + coffeelint: { + src: { + files: { + src: [ '<%= app_files.coffee %>' ] + } + }, + test: { + files: { + src: [ '<%= app_files.coffeeunit %>' ] + } + } + }, + + /** + * HTML2JS is a Grunt plugin that takes all of your template files and + * places them into JavaScript files as strings that are added to + * AngularJS's template cache. This means that the templates too become + * part of the initial payload as one JavaScript file. Neat! + */ + html2js: { + /** + * These are the templates from `src/app`. + */ + app: { + options: { + base: 'src/app' + }, + src: [ '<%= app_files.atpl %>' ], + dest: '<%= build_dir %>/templates-app.js' + }, + + /** + * These are the templates from `src/common`. + */ + common: { + options: { + base: 'src/common' + }, + src: [ '<%= app_files.ctpl %>' ], + dest: '<%= build_dir %>/templates-common.js' + } + }, + + /** + * The Karma configurations. + */ + karma: { + options: { + configFile: '<%= build_dir %>/karma-unit.js' + }, + unit: { + runnerPort: 9101, + background: true + }, + continuous: { + singleRun: true + } + }, + + /** + * The `index` task compiles the `index.html` file as a Grunt template. CSS + * and JS files co-exist here but they get split apart later. + */ + index: { + + /** + * During development, we don't want to have wait for compilation, + * concatenation, minification, etc. So to avoid these steps, we simply + * add all script files directly to the `` of `index.html`. The + * `src` property contains the list of included files. + */ + build: { + dir: '<%= build_dir %>', + src: [ + '<%= vendor_files.js %>', + '<%= build_dir %>/src/**/*.js', + '<%= html2js.common.dest %>', + '<%= html2js.app.dest %>', + '<%= recess.build.dest %>' + ] + }, + + /** + * When it is time to have a completely compiled application, we can + * alter the above to include only a single JavaScript and a single CSS + * file. Now we're back! + */ + compile: { + dir: '<%= compile_dir %>', + src: [ + '<%= concat.compile_js.dest %>', + '<%= vendor_files.css %>', + '<%= recess.compile.dest %>' + ] + } + }, + + /** + * This task compiles the karma template so that changes to its file array + * don't have to be managed manually. + */ + karmaconfig: { + unit: { + dir: '<%= build_dir %>', + src: [ + '<%= vendor_files.js %>', + '<%= html2js.app.dest %>', + '<%= html2js.common.dest %>', + '<%= test_files.js %>' + ] + } + }, + + /** + * And for rapid development, we have a watch set up that checks to see if + * any of the files listed below change, and then to execute the listed + * tasks when they do. This just saves us from having to type "grunt" into + * the command-line every time we want to see what we're working on; we can + * instead just leave "grunt watch" running in a background terminal. Set it + * and forget it, as Ron Popeil used to tell us. + * + * But we don't need the same thing to happen for all the files. + */ + delta: { + /** + * By default, we want the Live Reload to work for all tasks; this is + * overridden in some tasks (like this file) where browser resources are + * unaffected. It runs by default on port 35729, which your browser + * plugin should auto-detect. + */ + options: { + livereload: true + }, + + /** + * When the Gruntfile changes, we just want to lint it. In fact, when + * your Gruntfile changes, it will automatically be reloaded! + */ + gruntfile: { + files: 'Gruntfile.js', + tasks: [ 'jshint:gruntfile' ], + options: { + livereload: false + } + }, + + /** + * When our JavaScript source files change, we want to run lint them and + * run our unit tests. + */ + jssrc: { + files: [ + '<%= app_files.js %>' + ], + tasks: [ 'jshint:src', 'karma:unit:run', 'copy:build_appjs' ] + }, + + /** + * When our CoffeeScript source files change, we want to run lint them and + * run our unit tests. + */ + coffeesrc: { + files: [ + '<%= app_files.coffee %>' + ], + tasks: [ 'coffeelint:src', 'coffee:source', 'karma:unit:run', 'copy:build_appjs' ] + }, + + /** + * When assets are changed, copy them. Note that this will *not* copy new + * files, so this is probably not very useful. + */ + assets: { + files: [ + 'src/assets/**/*' + ], + tasks: [ 'copy:build_assets' ] + }, + + /** + * When index.html changes, we need to compile it. + */ + html: { + files: [ '<%= app_files.html %>' ], + tasks: [ 'index:build' ] + }, + + /** + * When our templates change, we only rewrite the template cache. + */ + tpls: { + files: [ + '<%= app_files.atpl %>', + '<%= app_files.ctpl %>' + ], + tasks: [ 'html2js' ] + }, + + /** + * When the CSS files change, we need to compile and minify them. + */ + less: { + files: [ 'src/**/*.less' ], + tasks: [ 'recess:build' ] + }, + + /** + * When a JavaScript unit test file changes, we only want to lint it and + * run the unit tests. We don't want to do any live reloading. + */ + jsunit: { + files: [ + '<%= app_files.jsunit %>' + ], + tasks: [ 'jshint:test', 'karma:unit:run' ], + options: { + livereload: false + } + }, + + /** + * When a CoffeeScript unit test file changes, we only want to lint it and + * run the unit tests. We don't want to do any live reloading. + */ + coffeeunit: { + files: [ + '<%= app_files.coffeeunit %>' + ], + tasks: [ 'coffeelint:test', 'karma:unit:run' ], + options: { + livereload: false + } + } + } + }; + + grunt.initConfig( grunt.util._.extend( taskConfig, userConfig ) ); + + /** + * In order to make it safe to just compile or copy *only* what was changed, + * we need to ensure we are starting from a clean, fresh build. So we rename + * the `watch` task to `delta` (that's why the configuration var above is + * `delta`) and then add a new task called `watch` that does a clean build + * before watching for changes. + */ + grunt.renameTask( 'watch', 'delta' ); + grunt.registerTask( 'watch', [ 'build', 'karma:unit', 'delta' ] ); + + /** + * The default task is to build and compile. + */ + grunt.registerTask( 'default', [ 'build', 'compile' ] ); + + /** + * The `build` task gets your app ready to run for development and testing. + */ + grunt.registerTask( 'build', [ + 'clean', 'html2js', 'gjslint', 'jshint', 'coffeelint', 'coffee', 'recess:build', + 'concat:build_css', 'copy:build_app_assets', 'copy:build_vendor_assets', 'copy:build_vendor_fonts', + 'copy:build_appjs', 'copy:build_vendorjs', 'index:build', 'karmaconfig', + 'karma:continuous' + ]); + + /** + * The `compile` task gets your app ready for deployment by concatenating and + * minifying your code. + */ + grunt.registerTask( 'compile', [ + 'recess:compile', 'copy:compile_assets', 'copy:compile_fonts', 'ngmin', 'concat:compile_js', 'uglify', 'index:compile' + ]); + + /** + * A utility function to get all app JavaScript sources. + */ + function filterForJS ( files ) { + return files.filter( function ( file ) { + return file.match( /\.js$/ ); + }); + } + + /** + * A utility function to get all app CSS sources. + */ + function filterForCSS ( files ) { + return files.filter( function ( file ) { + return file.match( /\.css$/ ); + }); + } + + /** + * The index.html template includes the stylesheet and javascript sources + * based on dynamic names calculated in this Gruntfile. This task assembles + * the list into variables for the template to use and then runs the + * compilation. + */ + grunt.registerMultiTask( 'index', 'Process index.html template', function () { + var dirRE = new RegExp( '^('+grunt.config('build_dir')+'|'+grunt.config('compile_dir')+')\/', 'g' ); + var jsFiles = filterForJS( this.filesSrc ).map( function ( file ) { + return file.replace( dirRE, '' ); + }); + var cssFiles = filterForCSS( this.filesSrc ).map( function ( file ) { + return file.replace( dirRE, '' ); + }); + + grunt.file.copy('src/index.html', this.data.dir + '/index.html', { + process: function ( contents, path ) { + return grunt.template.process( contents, { + data: { + scripts: jsFiles, + styles: cssFiles, + version: grunt.config( 'pkg.version' ) + } + }); + } + }); + }); + + /** + * In order to avoid having to specify manually the files needed for karma to + * run, we use grunt to manage the list for us. The `karma/*` files are + * compiled as grunt templates for use by Karma. Yay! + */ + grunt.registerMultiTask( 'karmaconfig', 'Process karma config templates', function () { + var jsFiles = filterForJS( this.filesSrc ); + + grunt.file.copy( 'karma/karma-unit.tpl.js', grunt.config( 'build_dir' ) + '/karma-unit.js', { + process: function ( contents, path ) { + return grunt.template.process( contents, { + data: { + scripts: jsFiles + } + }); + } + }); + }); + +}; diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..8f9a7f4a --- /dev/null +++ b/LICENSE @@ -0,0 +1,4 @@ +Copyright (c) 2013 LMN Solutions, LLC, All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 00000000..aa63fd43 --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +## Quick Start + +Install Node.js and then: + +```sh +$ git clone git://github.com/ROGUE-JCTD/MapLoom +$ cd MapLoom +$ sudo npm -g install grunt-cli karma bower +$ npm install +$ bower install +$ grunt watch +``` + +Finally, open `file:///path/to/MapLoom/build/index.html` in your browser. diff --git a/bower.json b/bower.json new file mode 100644 index 00000000..b741657e --- /dev/null +++ b/bower.json @@ -0,0 +1,21 @@ +{ + "name": "MapLoom", + "version": "0.0.1", + "devDependencies": { + "bootstrap": "3.0.0", + "angular": "1.2.0-rc.2", + "angular-mocks": "1.2.0-rc.2", + "angular-bootstrap": "0.6.0", + "angular-ui-router": "0.2.0", + "jquery": "~2.0.3" + }, + "dependencies": { + "bootstrap": "3.0.0", + "angular": "1.2.0-rc.2", + "angular-mocks": "1.2.0-rc.2", + "angular-bootstrap": "0.6.0", + "angular-ui-router": "0.2.0", + "jquery": "~2.0.3", + "openlayers": "./openlayers" + } +} diff --git a/build.config.js b/build.config.js new file mode 100644 index 00000000..caab57de --- /dev/null +++ b/build.config.js @@ -0,0 +1,83 @@ +/** + * This file/module contains all configuration for the build process. + */ +module.exports = { + /** + * The `build_dir` folder is where our projects are compiled during + * development and the `compile_dir` folder is where our app resides once it's + * completely built. + */ + build_dir: 'build', + compile_dir: 'bin', + + /** + * This is a collection of file patterns that refer to our app code (the + * stuff in `src/`). These file paths are used in the configuration of + * build tasks. `js` is all project javascript, less tests. `ctpl` contains + * our reusable components' (`src/common`) template HTML files, while + * `atpl` contains the same, but for our app's code. `html` is just our + * main HTML file, `less` is our main stylesheet, and `unit` contains our + * app's unit tests. + */ + app_files: { + js: [ 'src/**/*.js', '!src/**/*.spec.js', '!src/assets/**/*.js' ], + jsunit: [ 'src/**/*.spec.js' ], + + coffee: [ 'src/**/*.coffee', '!src/**/*.spec.coffee' ], + coffeeunit: [ 'src/**/*.spec.coffee' ], + + atpl: [ 'src/app/**/*.tpl.html' ], + ctpl: [ 'src/common/**/*.tpl.html' ], + + html: [ 'src/index.html' ], + less: 'src/less/main.less' + }, + + /** + * This is a collection of files used during testing only. + */ + test_files: { + js: [ + 'vendor/angular-mocks/angular-mocks.js' + ] + }, + + /** + * This is the same as `app_files`, except it contains patterns that + * reference vendor code (`vendor/`) that we need to place into the build + * process somewhere. While the `app_files` property ensures all + * standardized files are collected for compilation, it is the user's job + * to ensure non-standardized (i.e. vendor-related) files are handled + * appropriately in `vendor_files.js`. + * + * The `vendor_files.js` property holds files to be automatically + * concatenated and minified with our project source files. + * + * The `vendor_files.css` property holds any CSS files to be automatically + * included in our app. + * + * The `vendor_files.assets` property holds any assets to be copied along + * with our app's assets. This structure is flattened, so it is not + * recommended that you use wildcards. + */ + vendor_files: { + js: [ + 'vendor/jquery/jquery.min.js', + 'vendor/angular/angular.js', + 'vendor/angular-bootstrap/ui-bootstrap-tpls.min.js', + 'vendor/placeholders/angular-placeholders-0.0.1-SNAPSHOT.min.js', + 'vendor/angular-ui-router/release/angular-ui-router.js', + 'vendor/angular-ui-utils/modules/route/route.js', + 'vendor/bootstrap/dist/js/bootstrap.js', + 'vendor/openlayers/ol.js' + ], + css: [ + 'vendor/openlayers/ol.css' + ], + assets: [ + ], + fonts: [ + 'vendor/bootstrap/fonts/*' + ] + }, +}; diff --git a/changelog.tpl b/changelog.tpl new file mode 100644 index 00000000..c0274e4a --- /dev/null +++ b/changelog.tpl @@ -0,0 +1,23 @@ + +# <%= version%> (<%= today%>) + +<% if (_(changelog.feat).size() > 0) { %> ## Features +<% _(changelog.feat).forEach(function(changes, scope) { %> +- **<%= scope%>:** + <% changes.forEach(function(change) { %> - <%= change.msg%> (<%= helpers.commitLink(change.sha1) %>) + <% }); %> +<% }); %> <% } %> + +<% if (_(changelog.fix).size() > 0) { %> ## Fixes +<% _(changelog.fix).forEach(function(changes, scope) { %> +- **<%= scope%>:** + <% changes.forEach(function(change) { %> - <%= change.msg%> (<%= helpers.commitLink(change.sha1) %>) + <% }); %> +<% }); %> <% } %> + +<% if (_(changelog.breaking).size() > 0) { %> ## Breaking Changes +<% _(changelog.breaking).forEach(function(changes, scope) { %> +- **<%= scope%>:** + <% changes.forEach(function(change) { %> <%= change.msg%> + <% }); %> +<% }); %> <% } %> diff --git a/gjslint.py b/gjslint.py new file mode 100755 index 00000000..cbabf3c4 --- /dev/null +++ b/gjslint.py @@ -0,0 +1,9 @@ +#!/usr/bin/python +# EASY-INSTALL-ENTRY-SCRIPT: 'closure-linter==2.3.11','console_scripts','gjslint' +__requires__ = 'closure-linter==2.3.11' +import sys +from pkg_resources import load_entry_point + +sys.exit( + load_entry_point('closure-linter==2.3.11', 'console_scripts', 'gjslint')() +) diff --git a/karma/karma-unit.tpl.js b/karma/karma-unit.tpl.js new file mode 100644 index 00000000..e1e423d7 --- /dev/null +++ b/karma/karma-unit.tpl.js @@ -0,0 +1,62 @@ +module.exports = function ( karma ) { + karma.configure({ + /** + * From where to look for files, starting with the location of this file. + */ + basePath: '../', + + /** + * This is the list of file patterns to load into the browser during testing. + */ + files: [ + <% scripts.forEach( function ( file ) { %>'<%= file %>', + <% }); %> + 'src/**/*.js', + 'src/**/*.coffee', + ], + exclude: [ + 'src/assets/**/*.js' + ], + frameworks: [ 'jasmine' ], + plugins: [ 'karma-jasmine', 'karma-firefox-launcher', 'karma-chrome-launcher', 'karma-phantomjs-launcher', 'karma-coffee-preprocessor' ], + preprocessors: { + '**/*.coffee': 'coffee', + }, + + /** + * How to report, by default. + */ + reporters: 'dots', + + /** + * On which port should the browser connect, on which port is the test runner + * operating, and what is the URL path for the browser to use. + */ + port: 9018, + runnerPort: 9100, + urlRoot: '/', + + /** + * Disable file watching by default. + */ + autoWatch: false, + + /** + * The list of browsers to launch to test on. This includes only "Firefox" by + * default, but other browser names include: + * Chrome, ChromeCanary, Firefox, Opera, Safari, PhantomJS + * + * Note that you can also use the executable name of the browser, like "chromium" + * or "firefox", but that these vary based on your operating system. + * + * You may also leave this blank and manually navigate your browser to + * http://localhost:9018/ when you're running tests. The window/tab can be left + * open and the tests will automatically occur there during the build. This has + * the aesthetic advantage of not launching a browser every time you save. + */ + browsers: [ + 'Chrome' + ] + }); +}; + diff --git a/module.prefix b/module.prefix new file mode 100644 index 00000000..c52d9b72 --- /dev/null +++ b/module.prefix @@ -0,0 +1 @@ +(function ( window, angular, undefined ) { diff --git a/module.suffix b/module.suffix new file mode 100644 index 00000000..f6354bac --- /dev/null +++ b/module.suffix @@ -0,0 +1 @@ +})( window, window.angular ); diff --git a/openlayers/ol.css b/openlayers/ol.css new file mode 100644 index 00000000..45c2cb8e --- /dev/null +++ b/openlayers/ol.css @@ -0,0 +1 @@ +.ol-attribution{position:absolute;text-align:right;color:#eee;bottom:0;right:0;background:rgba(0,60,136,0.3);font-family:'Lucida Grande',Verdana,Geneva,Lucida,Arial,Helvetica,sans-serif;padding:6px}.ol-attribution a{color:white;text-decoration:none}.ol-attribution ul{margin:0;padding:0;font-size:10px;line-height:12px}.ol-attribution li{display:inline;list-style:none;line-height:inherit}.ol-attribution li:not(:last-child):after{content:"\002003"}.ol-dragbox{position:absolute;border:2px solid red}.ol-full-screen{background:rgba(255,255,255,0.4);border-radius:4px;padding:2px;position:absolute;right:8px;top:8px}@media print{.ol-full-screen{display:none}}.ol-full-screen a{background:rgba(0,60,136,0.5);color:white;display:block;font-family:'Lucida Grande',Verdana,Geneva,Lucida,Arial,Helvetica,sans-serif;font-size:18px;font-weight:bold;height:22px;line-height:19px;margin:1px;padding:0;text-align:center;text-decoration:none;width:22px}a.ol-full-screen-false:after{content:"\002194"}a.ol-full-screen-true:after{content:"\0000d7"}.ol-full-screen div{border-radius:2px}.ol-full-screen div a{border-radius:2px}.ol-full-screen a:hover{background:rgba(0,60,136,0.7)}.ol-logo{bottom:0;left:0;padding:2px;position:absolute}.ol-logo ul{margin:0}.ol-logo ul li{display:inline;list-style:none}.ol-mouse-position{top:8px;right:8px;position:absolute}.ol-scale-line{background:rgba(0,60,136,0.3);border-radius:4px;bottom:8px;left:8px;padding:2px;position:absolute}.ol-scale-line-inner{border:1px solid #eee;border-top:none;color:#eee;font-size:10px;font-family:'Lucida Grande',Verdana,Geneva,Lucida,Arial,Helvetica,sans-serif;text-align:center;margin:1px;padding:0 2px}.ol-unsupported{display:none}.ol-viewport .ol-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}.ol-zoom{position:absolute;top:8px;left:8px;background:rgba(255,255,255,0.4);border-radius:4px;padding:2px}@media print{.ol-zoom{display:none}}.ol-zoom a{display:block;margin:1px;padding:0;color:white;font-size:18px;font-family:'Lucida Grande',Verdana,Geneva,Lucida,Arial,Helvetica,sans-serif;font-weight:bold;text-decoration:none;text-align:center;height:22px;width:22px;line-height:19px;background:rgba(0,60,136,0.5)}.ol-touch .ol-zoom a{font-size:20px;height:30px;width:30px;line-height:26px}.ol-zoom a:hover{background:rgba(0,60,136,0.7)}.ol-zoom-in{border-radius:2px 2px 0 0}.ol-zoom-in:before{content:"+"}.ol-zoom-out{border-radius:0 0 2px 2px}.ol-zoom-out:before{content:"\002212"}.ol-zoomslider{position:absolute;top:67px;left:8px;background:rgba(255,255,255,0.4);border-radius:4px;width:28px;height:200px;outline:none;overflow:hidden;padding:0;margin:0}.ol-zoomslider-thumb{position:absolute;display:block;padding:0;margin:2px;background:rgba(0,60,136,0.5);border-radius:2px;outline:none;overflow:hidden;height:20px;width:24px}.ol-zoom-extent{position:absolute;background:rgba(255,255,255,0.4);border-radius:4px;left:8px;padding:2px;top:65px}@media print{.ol-zoom-extent{display:none}}.ol-zoom-extent a{display:block;margin:1px;padding:0;color:white;font-size:16px;font-family:'Lucida Grande',Verdana,Geneva,Lucida,Arial,Helvetica,sans-serif;font-weight:bold;text-decoration:none;text-align:center;height:22px;width:22px;background-color:rgba(0,60,136,0.5);border-radius:2px}.ol-touch .ol-zoom-extent a{font-size:20px;height:30px;width:30px;line-height:26px}.ol-zoom-extent a:hover{background-color:rgba(0,60,136,0.7)}.ol-zoom-extent a:after{content:"E"} \ No newline at end of file diff --git a/openlayers/ol.js b/openlayers/ol.js new file mode 100644 index 00000000..92d31fa1 --- /dev/null +++ b/openlayers/ol.js @@ -0,0 +1,508 @@ +(function(){function k(a){return function(){return this[a]}}function ba(a){return function(){return a}}var m,ca=ca||{},p=this;function da(){}function fa(a){a.va=function(){return a.Vd?a.Vd:a.Vd=new a}} +function ga(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null"; +else if("function"==b&&"undefined"==typeof a.call)return"object";return b}function s(a){return void 0!==a}function ia(a){return"array"==ga(a)}function ja(a){var b=ga(a);return"array"==b||"object"==b&&"number"==typeof a.length}function u(a){return"string"==typeof a}function ka(a){return"number"==typeof a}function la(a){return"function"==ga(a)}function ma(a){var b=typeof a;return"object"==b&&null!=a||"function"==b}function x(a){return a[na]||(a[na]=++oa)} +var na="closure_uid_"+(1E9*Math.random()>>>0),oa=0;function pa(a,b,c){return a.call.apply(a.bind,arguments)}function qa(a,b,c){if(!a)throw Error();if(2/g,Ba=/\"/g,xa=/[&<>\"]/; +function Ca(a){a=s(void 0)?a.toFixed(void 0):String(a);var b=a.indexOf(".");-1==b&&(b=a.length);b=Math.max(0,2-b);return Array(b+1).join("0")+a};var Da=Array.prototype,Fa=Da.indexOf?function(a,b,c){return Da.indexOf.call(a,b,c)}:function(a,b,c){c=null==c?0:0>c?Math.max(0,a.length+c):c;if(u(a))return u(b)&&1==b.length?a.indexOf(b,c):-1;for(;cc?null:u(a)?a.charAt(c):a[c]}function Na(a,b,c){for(var d=a.length,e=u(a)?a.split(""):a,f=0;f=arguments.length?Da.slice.call(a,b):Da.slice.call(a,b,c)}function Ua(a,b){Da.sort.call(a,b||Va)}function Va(a,b){return a>b?1:a>=1;return b.join("")}Xa.prototype.toString=function(){return Za(this.z,this.x,this.y)};function ab(a,b,c,d){this.a=a;this.d=b;this.c=c;this.b=d}function bb(a,b,c,d,e){return s(e)?(e.a=a,e.d=b,e.c=c,e.b=d,e):new ab(a,b,c,d)}ab.prototype.contains=function(a){return this.a<=a.x&&a.x<=this.d&&this.c<=a.y&&a.y<=this.b};function cb(a){this.b=a.html;this.a=s(a.tileRanges)?a.tileRanges:null};function db(){0!=eb&&(this.Ug=Error().stack,fb[x(this)]=this)}var eb=0,fb={};db.prototype.$b=!1;db.prototype.pc=function(){if(!this.$b&&(this.$b=!0,this.v(),0!=eb)){var a=x(this);delete fb[a]}};function gb(a,b){var c=ra(hb,b);a.V||(a.V=[]);a.V.push(y(c,void 0))}db.prototype.v=function(){if(this.V)for(;this.V.length;)this.V.shift()()};function hb(a){a&&"function"==typeof a.pc&&a.pc()};function ib(a,b){this.type=a;this.c=this.target=b}m=ib.prototype;m.pc=function(){};m.jb=!1;m.Te=!1;m.ie=!0;m.rb=function(){this.jb=!0};m.U=function(){this.Te=!0;this.ie=!1};function jb(a){a.rb()}function kb(a){a.U()};var lb,mb,nb,ob,pb,qb,rb;function sb(){return p.navigator?p.navigator.userAgent:null}function tb(){return p.navigator}ob=nb=mb=lb=!1;var ub;if(ub=sb()){var vb=tb();lb=0==ub.lastIndexOf("Opera",0);mb=!lb&&(-1!=ub.indexOf("MSIE")||-1!=ub.indexOf("Trident"));nb=!lb&&-1!=ub.indexOf("WebKit");ob=!lb&&!nb&&!mb&&"Gecko"==vb.product}var wb=lb,G=mb,xb=ob,yb=nb,zb,Ab=tb();zb=Ab&&Ab.platform||"";pb=-1!=zb.indexOf("Mac");qb=-1!=zb.indexOf("Win");rb=-1!=zb.indexOf("Linux"); +var Cb=!!tb()&&-1!=(tb().appVersion||"").indexOf("X11");function Db(){var a=p.document;return a?a.documentMode:void 0}var Eb;a:{var Gb="",Hb;if(wb&&p.opera)var Ib=p.opera.version,Gb="function"==typeof Ib?Ib():Ib;else if(xb?Hb=/rv\:([^\);]+)(\)|;)/:G?Hb=/\b(?:MSIE|rv)\s+([^\);]+)(\)|;)/:yb&&(Hb=/WebKit\/(\S+)/),Hb)var Jb=Hb.exec(sb()),Gb=Jb?Jb[1]:"";if(G){var Kb=Db();if(Kb>parseFloat(Gb)){Eb=String(Kb);break a}}Eb=Gb}var Lb={}; +function Mb(a){var b;if(!(b=Lb[a])){b=0;for(var c=ua(String(Eb)).split("."),d=ua(String(a)).split("."),e=Math.max(c.length,d.length),f=0;0==b&&f(0==r[1].length?0:parseInt(r[1],10))?1:0)||((0==q[2].length)< +(0==r[2].length)?-1:(0==q[2].length)>(0==r[2].length)?1:0)||(q[2]r[2]?1:0)}while(0==b)}b=Lb[a]=0<=b}return b}var Nb=p.document,Ob=Nb&&G?Db()||("CSS1Compat"==Nb.compatMode?parseInt(Eb,10):5):void 0;var Pb=!G||G&&9<=Ob,Qb=!G||G&&9<=Ob,Rb=G&&!Mb("9");!yb||Mb("528");xb&&Mb("1.9b")||G&&Mb("8")||wb&&Mb("9.5")||yb&&Mb("528");xb&&!Mb("8")||G&&Mb("9");function Sb(a){Sb[" "](a);return a}Sb[" "]=da;function Tb(a,b){a&&Ub(this,a,b)}E(Tb,ib);var Vb=[1,4,2];m=Tb.prototype;m.target=null;m.Se=null;m.Ld=0;m.Md=0;m.clientX=0;m.clientY=0;m.gd=0;m.hd=0;m.Re=0;m.Va=0;m.ed=0;m.Qb=!1;m.wa=!1;m.Wa=!1;m.fd=!1;m.Gb=!1;m.fa=null; +function Ub(a,b,c){var d=a.type=b.type;ib.call(a,d);a.target=b.target||b.srcElement;a.c=c;if(c=b.relatedTarget){if(xb){var e;a:{try{Sb(c.nodeName);e=!0;break a}catch(f){}e=!1}e||(c=null)}}else"mouseover"==d?c=b.fromElement:"mouseout"==d&&(c=b.toElement);a.Se=c;a.Ld=yb||void 0!==b.offsetX?b.offsetX:b.layerX;a.Md=yb||void 0!==b.offsetY?b.offsetY:b.layerY;a.clientX=void 0!==b.clientX?b.clientX:b.pageX;a.clientY=void 0!==b.clientY?b.clientY:b.pageY;a.gd=b.screenX||0;a.hd=b.screenY||0;a.Re=b.button;a.Va= +b.keyCode||0;a.ed=b.charCode||("keypress"==d?b.keyCode:0);a.Qb=b.ctrlKey;a.wa=b.altKey;a.Wa=b.shiftKey;a.fd=b.metaKey;a.Gb=pb?b.metaKey:b.ctrlKey;a.a=b.state;a.fa=b;b.defaultPrevented&&a.U();delete a.jb}function Wb(a){return(Pb?0==a.fa.button:"click"==a.type?!0:!!(a.fa.button&Vb[0]))&&!(yb&&pb&&a.Qb)}m.rb=function(){Tb.F.rb.call(this);this.fa.stopPropagation?this.fa.stopPropagation():this.fa.cancelBubble=!0}; +m.U=function(){Tb.F.U.call(this);var a=this.fa;if(a.preventDefault)a.preventDefault();else if(a.returnValue=!1,Rb)try{if(a.ctrlKey||112<=a.keyCode&&123>=a.keyCode)a.keyCode=-1}catch(b){}};m.Ge=k("fa");var Xb="closure_listenable_"+(1E6*Math.random()|0);function cc(a){return!(!a||!a[Xb])}var dc=0;function ec(a,b,c,d,e,f){this.Oa=a;this.a=b;this.src=c;this.type=d;this.capture=!!e;this.tb=f;this.key=++dc;this.Za=this.Ab=!1}function fc(a){a.Za=!0;a.Oa=null;a.a=null;a.src=null;a.tb=null};function gc(a,b){for(var c in a)b.call(void 0,a[c],c,a)}function hc(a,b){var c={},d;for(d in a)b.call(void 0,a[d],d,a)&&(c[d]=a[d]);return c}function ic(a){var b=0,c;for(c in a)b++;return b}function jc(a){for(var b in a)return b}function kc(a){var b=[],c=0,d;for(d in a)b[c++]=a[d];return b}function lc(a){var b=[],c=0,d;for(d in a)b[c++]=d;return b}function mc(a){var b=qc,c;for(c in b)if(a.call(void 0,b[c],c,b))return c}function rc(a){for(var b in a)return!1;return!0} +function sc(a){var b={},c;for(c in a)b[c]=a[c];return b}var tc="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" ");function I(a,b){for(var c,d,e=1;ee.keyCode||void 0!=e.returnValue)return!0;a:{var h=!1;if(0==e.keyCode)try{e.keyCode=-1;break a}catch(l){h=!0}if(h||void 0==e.returnValue)e.returnValue=!0}}h=new Tb;Ub(h,e,this);e=!0;try{if(c){for(var n=[],q=h.c;q;q=q.parentNode)n.push(q);f=d[!0];for(var r=n.length- +1;!h.jb&&0<=r;r--)h.c=n[r],e&=Ic(f,n[r],h);if(g)for(f=d[!1],r=0;!h.jb&&r>>0);function yc(a){return la(a)?a:a[Kc]||(a[Kc]=function(b){return a.handleEvent(b)})};function Lc(a){this.src=a;this.a={};this.b=0}Lc.prototype.add=function(a,b,c,d,e){var f=this.a[a];f||(f=this.a[a]=[],this.b++);var g=Mc(f,b,d,e);-1c*b?c+b:c}function ad(a){return a*Math.PI/180};function fd(a){M.call(this);a=s(a)?a:{};this.a=null;J(this,Uc("tracking"),this.i,!1,this);this.b(s(a.tracking)?a.tracking:!1)}E(fd,M);fd.prototype.v=function(){this.b(!1);fd.F.v.call(this)};var gd="DeviceOrientationEvent"in p;fd.SUPPORTED=gd; +fd.prototype.k=function(a){a=a.fa;if(null!=a.alpha){var b=ad(a.alpha);this.l("alpha",b);"boolean"==typeof a.absolute&&a.absolute?this.l("heading",b):null!=a.webkitCompassHeading&&(null!=a.webkitCompassAccuracy&&-1!=a.webkitCompassAccuracy)&&this.l("heading",ad(a.webkitCompassHeading))}null!=a.beta&&this.l("beta",ad(a.beta));null!=a.gamma&&this.l("gamma",ad(a.gamma))};fd.prototype.d=function(){return this.get("alpha")};fd.prototype.getAlpha=fd.prototype.d;fd.prototype.e=function(){return this.get("beta")}; +fd.prototype.getBeta=fd.prototype.e;fd.prototype.f=function(){return this.get("gamma")};fd.prototype.getGamma=fd.prototype.f;fd.prototype.g=function(){return this.get("heading")};fd.prototype.getHeading=fd.prototype.g;fd.prototype.c=function(){return this.get("tracking")};fd.prototype.getTracking=fd.prototype.c;fd.prototype.i=function(){if(gd){var a=this.c();a&&null===this.a?this.a=J(p,"deviceorientation",this.k,!1,this):a||null===this.a||(Fc(this.a),this.a=null)}}; +fd.prototype.b=function(a){this.l("tracking",a)};fd.prototype.setTracking=fd.prototype.b;function hd(a,b){a[0]+=b[0];a[1]+=b[1]}function id(a,b){var c=$c(a+180,360)-180,d=Math.abs(Math.round(3600*c));return Math.floor(d/3600)+"\u00b0 "+Math.floor(d/60%60)+"\u2032 "+Math.floor(d%60)+"\u2033 "+b.charAt(0>c?1:0)}function jd(a,b){var c=Math.cos(b),d=Math.sin(b),e=a[1]*c+a[0]*d;a[0]=a[0]*c-a[1]*d;a[1]=e}function kd(a,b){var c=a[0]-b[0],d=a[1]-b[1];return c*c+d*d}function ld(a,b){if(s(a)){var c=b||0;return a[0].toFixed(c)+", "+a[1].toFixed(c)}return""} +function md(a,b){var c=b.charAt(0);return"n"===c||"s"===c?[a[1],a[0]]:a};function nd(a){var b=od(),c=a.length,d;for(d=0;de[2]&&(e[2]=f[0]);f[1]e[3]&&(e[3]=f[1])}return b}function pd(a,b,c){var d=Math.min.apply(null,a);a=Math.max.apply(null,a);var e=Math.min.apply(null,b);b=Math.max.apply(null,b);return qd(d,a,e,b,c)}function rd(a,b){return a[0]<=b[0]&&b[0]<=a[2]&&a[1]<=b[1]&&b[1]<=a[3]}function sd(a,b){return a[0]<=b[0]&&b[2]<=a[2]&&a[1]<=b[1]&&b[3]<=a[3]} +function od(){return[Infinity,Infinity,-Infinity,-Infinity]}function qd(a,b,c,d,e){return s(e)?(e[0]=a,e[2]=b,e[1]=c,e[3]=d,e):[a,c,b,d]}function td(a,b){return a[0]==b[0]&&a[2]==b[2]&&a[1]==b[1]&&a[3]==b[3]}function ud(a,b){b[0]a[2]&&(a[2]=b[2]);b[1]a[3]&&(a[3]=b[3])}function vd(a){return[a[0],a[1]]}function wd(a){return[(a[0]+a[2])/2,(a[1]+a[3])/2]} +function xd(a,b,c,d){var e=b*d[0]/2;d=b*d[1]/2;b=Math.cos(c);c=Math.sin(c);e=[-e,-e,e,e];d=[-d,d,-d,d];var f,g,h;for(f=0;4>f;++f)g=e[f],h=d[f],e[f]=a[0]+g*b-h*c,d[f]=a[1]+g*c+h*b;return pd(e,d,void 0)}function yd(a){return[a[0],a[3]]}function zd(a,b){return a[0]<=b[2]&&a[2]>=b[0]&&a[1]<=b[3]&&a[3]>=b[1]}function Ad(a,b){return zd(a,b)&&(a[0]==b[2]||a[2]==b[0]||a[1]==b[3]||a[3]==b[1])} +function Bd(a,b,c){a=[a[0],a[1],a[0],a[3],a[2],a[1],a[2],a[3]];b(a,a,2);return pd([a[0],a[2],a[4],a[6]],[a[1],a[3],a[5],a[7]],c)};function Cd(a){a=a?a:{};this.coordinates=[];this.b=[];this.c=[];this.za=a.dimension||2;this.a=a.offset||null}Cd.prototype.add=function(a){for(var b=this.coordinates.length,c=this.a,d=this.za,e=a.length,f,g,h=0;h>1;){var l=2*b+1,n=2*b+2,l=nb;){var g=c-1>>1;if(a[g]>f)d[c]=d[g],a[c]=a[g],c=g;else break}d[c]=e;a[c]=f}function Ke(a){var b=a.f,c=a.a,d=a.b,e=0,f=c.length,g,h,l;for(h=0;h>1)-1;0<=b;b--)He(a,b)};function Le(a,b){Fe.call(this,function(b){return a.apply(null,b)},function(a){return a[0].b()});this.V=b;this.d=0}E(Le,Fe);Le.prototype.g=function(){--this.d;this.V()};function S(a){M.call(this);a=sc(a);a.brightness=s(a.brightness)?a.brightness:0;a.contrast=s(a.contrast)?a.contrast:1;a.hue=s(a.hue)?a.hue:0;a.opacity=s(a.opacity)?a.opacity:1;a.saturation=s(a.saturation)?a.saturation:1;a.visible=s(a.visible)?a.visible:!0;a.maxResolution=s(a.maxResolution)?a.maxResolution:Infinity;a.minResolution=s(a.minResolution)?a.minResolution:0;this.Zb(a);J(this,[Uc("brightness"),Uc("contrast"),Uc("hue"),Uc("opacity"),Uc("saturation"),Uc("maxResolution"),Uc("minResolution")], +this.Cc,!1,this);J(this,Uc("visible"),this.Td,!1,this)}E(S,M);function Me(a){K(a,"change")}S.prototype.e=function(){return this.get("brightness")};S.prototype.getBrightness=S.prototype.e;S.prototype.f=function(){return this.get("contrast")};S.prototype.getContrast=S.prototype.f;S.prototype.g=function(){return this.get("hue")};S.prototype.getHue=S.prototype.g; +function Ne(a){var b=a.e(),c=a.f(),d=a.g(),e=a.r(),f=a.Ma(),g=a.p(),h=a.b(),l=a.i();a=a.k();return{brightness:s(b)?Zc(b,-1,1):0,contrast:s(c)?Math.max(c,0):1,hue:s(d)?d:0,opacity:s(e)?Zc(e,0,1):1,Mc:f,saturation:s(g)?Math.max(g,0):1,visible:s(h)?!!h:!0,maxResolution:s(l)?l:Infinity,minResolution:s(a)?Math.max(a,0):0}}S.prototype.i=function(){return this.get("maxResolution")};S.prototype.getMaxResolution=S.prototype.i;S.prototype.k=function(){return this.get("minResolution")}; +S.prototype.getMinResolution=S.prototype.k;S.prototype.r=function(){return this.get("opacity")};S.prototype.getOpacity=S.prototype.r;S.prototype.p=function(){return this.get("saturation")};S.prototype.getSaturation=S.prototype.p;S.prototype.b=function(){return this.get("visible")};S.prototype.getVisible=S.prototype.b;S.prototype.Cc=function(){this.b()&&this.Ma()&&Me(this)};S.prototype.Td=function(){this.Ma()&&Me(this)};S.prototype.R=function(a){this.l("brightness",a)};S.prototype.setBrightness=S.prototype.R; +S.prototype.W=function(a){this.l("contrast",a)};S.prototype.setContrast=S.prototype.W;S.prototype.la=function(a){this.l("hue",a)};S.prototype.setHue=S.prototype.la;S.prototype.ia=function(a){this.l("maxResolution",a)};S.prototype.setMaxResolution=S.prototype.ia;S.prototype.sa=function(a){this.l("minResolution",a)};S.prototype.setMinResolution=S.prototype.sa;S.prototype.K=function(a){this.l("opacity",a)};S.prototype.setOpacity=S.prototype.K;S.prototype.Ra=function(a){this.l("saturation",a)}; +S.prototype.setSaturation=S.prototype.Ra;S.prototype.lb=function(a){this.l("visible",a)};S.prototype.setVisible=S.prototype.lb;function Oe(a){return function(){return a}}var Pe=Oe(!1),Qe=Oe(!0),Re=Oe(null);function Se(a){return function(){throw a;}}function Te(a){var b;b=b||0;return function(){return a.apply(this,Array.prototype.slice.call(arguments,0,b))}}function Ue(a){var b=arguments,c=b.length;return function(){for(var a,e=0;ea?bf(2*a):1-bf(2*(a-0.5))};function ef(a){var b=a.resolution,c=s(a.start)?a.start:sa(),d=s(a.duration)?a.duration:1E3,e=s(a.easing)?a.easing:df;return function(a,g){if(g.timeb;)d-=3;if(0<=d){var b=a.a[c+2]-a.a[d+2],e=a.a[c]-a.a[d],c=a.a[c+1]-a.a[d+1];a.c=Math.atan2(c,e);a.b=Math.sqrt(e*e+c*c)/b;return a.b>a.d}return!1}function yf(a,b){var c=a.e,d=a.b,e=a.d,f=Math.log(a.d/a.b)/a.e;return tf({source:b,duration:f,easing:function(a){return d*(Math.exp(c*a*f)-1)/(e-d)}})};function zf(a){if("function"==typeof a.La)return a.La();if(u(a))return a.split("");if(ja(a)){for(var b=[],c=a.length,d=0;d2*this.u&&Df(this),!0):!1};function Df(a){if(a.u!=a.a.length){for(var b=0,c=0;bc?a[1]="?":c==b.length-1&&(a[1]=void 0)}return a.join("")} +function Jf(a,b,c){if(ia(b))for(var d=0;db)throw Error("Bad port number "+b);a.Lc=b}else a.Lc=null}function Pf(a,b,c){Nf(a);b instanceof Qf?(a.a=b,Wf(a.a,a.pb)):(c||(b=Rf(b,Xf)),a.a=new Qf(b,0,a.pb))}function Yf(a,b,c){Nf(a);ia(c)||(c=[String(c)]);Zf(a.a,b,c)}function Nf(a){if(a.xf)throw Error("Tried to modify a read-only Uri");} +function Rf(a,b){return u(a)?encodeURI(a).replace(b,$f):null}function $f(a){a=a.charCodeAt(0);return"%"+(a>>4&15).toString(16)+(a&15).toString(16)}var Sf=/[#\/\?@]/g,Uf=/[\#\?:]/g,Tf=/[\#\?]/g,Xf=/[\#\?@]/g,Vf=/#/g;function Qf(a,b,c){this.a=a||null;this.b=!!c} +function ag(a){if(!a.$&&(a.$=new Bf,a.u=0,a.a))for(var b=a.a.split("\x26"),c=0;c=a||96<=a&&106>=a||65<=a&&90>=a||yb&&0==a)return!0;switch(a){case 32:case 63:case 107:case 109:case 110:case 111:case 186:case 59:case 189:case 187:case 61:case 188:case 190:case 191:case 192:case 222:case 219:case 220:case 221:return!0;default:return!1}}function rh(a){switch(a){case 61:return 187;case 59:return 186;case 224:return 91;case 0:return 224;default:return a}};function sh(a,b){Nc.call(this);a&&th(this,a,b)}E(sh,Nc);m=sh.prototype;m.Rb=null;m.Fc=null;m.jd=null;m.Gc=null;m.pa=-1;m.fb=-1;m.Tc=!1; +var uh={3:13,12:144,63232:38,63233:40,63234:37,63235:39,63236:112,63237:113,63238:114,63239:115,63240:116,63241:117,63242:118,63243:119,63244:120,63245:121,63246:122,63247:123,63248:44,63272:46,63273:36,63275:35,63276:33,63277:34,63289:144,63302:45},vh={Up:38,Down:40,Left:37,Right:39,Enter:13,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,"U+007F":46,Home:36,End:35,PageUp:33,PageDown:34,Insert:45},wh=G||yb&&Mb("525"),xh=pb&&xb; +sh.prototype.a=function(a){yb&&(17==this.pa&&!a.Qb||18==this.pa&&!a.wa||pb&&91==this.pa&&!a.fd)&&(this.fb=this.pa=-1);-1==this.pa&&(a.Qb&&17!=a.Va?this.pa=17:a.wa&&18!=a.Va?this.pa=18:a.fd&&91!=a.Va&&(this.pa=91));wh&&!ph(a.Va,this.pa,a.Wa,a.Qb,a.wa)?this.handleEvent(a):(this.fb=xb?rh(a.Va):a.Va,xh&&(this.Tc=a.wa))};sh.prototype.b=function(a){this.fb=this.pa=-1;this.Tc=a.wa}; +sh.prototype.handleEvent=function(a){var b=a.fa,c,d,e=b.altKey;G&&"keypress"==a.type?(c=this.fb,d=13!=c&&27!=c?b.keyCode:0):yb&&"keypress"==a.type?(c=this.fb,d=0<=b.charCode&&63232>b.charCode&&qh(c)?b.charCode:0):wb?(c=this.fb,d=qh(c)?b.keyCode:0):(c=b.keyCode||this.fb,d=b.charCode||0,xh&&(e=this.Tc),pb&&(63==d&&224==c)&&(c=191));var f=c,g=b.keyIdentifier;c?63232<=c&&c in uh?f=uh[c]:25==c&&a.Wa&&(f=9):g&&g in vh&&(f=vh[g]);a=f==this.pa;this.pa=f;b=new yh(f,d,a,b);b.wa=e;K(this,b)}; +function th(a,b,c){a.Gc&&zh(a);a.Rb=b;a.Fc=J(a.Rb,"keypress",a,c);a.jd=J(a.Rb,"keydown",a.a,c,a);a.Gc=J(a.Rb,"keyup",a.b,c,a)}function zh(a){a.Fc&&(Fc(a.Fc),Fc(a.jd),Fc(a.Gc),a.Fc=null,a.jd=null,a.Gc=null);a.Rb=null;a.pa=-1;a.fb=-1}sh.prototype.v=function(){sh.F.v.call(this);zh(this)};function yh(a,b,c,d){d&&Ub(this,d,void 0);this.type="key";this.Va=a;this.ed=b;this.b=c}E(yh,Tb);function Ah(a,b,c,d){this.top=a;this.right=b;this.bottom=c;this.left=d}m=Ah.prototype;m.ea=function(){return new Ah(this.top,this.right,this.bottom,this.left)};m.contains=function(a){return this&&a?a instanceof Ah?a.left>=this.left&&a.right<=this.right&&a.top>=this.top&&a.bottom<=this.bottom:a.x>=this.left&&a.x<=this.right&&a.y>=this.top&&a.y<=this.bottom:!1}; +m.ceil=function(){this.top=Math.ceil(this.top);this.right=Math.ceil(this.right);this.bottom=Math.ceil(this.bottom);this.left=Math.ceil(this.left);return this};m.floor=function(){this.top=Math.floor(this.top);this.right=Math.floor(this.right);this.bottom=Math.floor(this.bottom);this.left=Math.floor(this.left);return this};m.round=function(){this.top=Math.round(this.top);this.right=Math.round(this.right);this.bottom=Math.round(this.bottom);this.left=Math.round(this.left);return this}; +m.scale=function(a,b){var c=ka(b)?b:a;this.left*=a;this.right*=a;this.top*=c;this.bottom*=c;return this};function Bh(a,b,c,d){this.left=a;this.top=b;this.width=c;this.height=d}m=Bh.prototype;m.ea=function(){return new Bh(this.left,this.top,this.width,this.height)};m.contains=function(a){return a instanceof Bh?this.left<=a.left&&this.left+this.width>=a.left+a.width&&this.top<=a.top&&this.top+this.height>=a.top+a.height:a.x>=this.left&&a.x<=this.left+this.width&&a.y>=this.top&&a.y<=this.top+this.height}; +m.ceil=function(){this.left=Math.ceil(this.left);this.top=Math.ceil(this.top);this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};m.floor=function(){this.left=Math.floor(this.left);this.top=Math.floor(this.top);this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};m.round=function(){this.left=Math.round(this.left);this.top=Math.round(this.top);this.width=Math.round(this.width);this.height=Math.round(this.height);return this}; +m.scale=function(a,b){var c=ka(b)?b:a;this.left*=a;this.width*=a;this.top*=c;this.height*=c;return this};function Ch(a,b){var c=sg(a);return c.defaultView&&c.defaultView.getComputedStyle&&(c=c.defaultView.getComputedStyle(a,null))?c[b]||c.getPropertyValue(b)||"":""}function Dh(a,b){return Ch(a,b)||(a.currentStyle?a.currentStyle[b]:null)||a.style&&a.style[b]}function Eh(a,b,c){var d,e=xb&&(pb||Cb)&&Mb("1.9");b instanceof og?(d=b.x,b=b.y):(d=b,b=c);a.style.left=Fh(d,e);a.style.top=Fh(b,e)} +function Gh(a){var b;try{b=a.getBoundingClientRect()}catch(c){return{left:0,top:0,right:0,bottom:0}}G&&(a=a.ownerDocument,b.left-=a.documentElement.clientLeft+a.body.clientLeft,b.top-=a.documentElement.clientTop+a.body.clientTop);return b} +function Hh(a){if(G&&!(G&&8<=Ob))return a.offsetParent;var b=sg(a),c=Dh(a,"position"),d="fixed"==c||"absolute"==c;for(a=a.parentNode;a&&a!=b;a=a.parentNode)if(c=Dh(a,"position"),d=d&&"static"==c&&a!=b.documentElement&&a!=b.body,!d&&(a.scrollWidth>a.clientWidth||a.scrollHeight>a.clientHeight||"fixed"==c||"absolute"==c||"relative"==c))return a;return null} +function Ih(a){var b,c=sg(a),d=Dh(a,"position"),e=xb&&c.getBoxObjectFor&&!a.getBoundingClientRect&&"absolute"==d&&(b=c.getBoxObjectFor(a))&&(0>b.screenX||0>b.screenY),f=new og(0,0),g;b=c?sg(c):document;g=!G||G&&9<=Ob||Gg(qg(b))?b.documentElement:b.body;if(a==g)return f;if(a.getBoundingClientRect)b=Gh(a),a=Ig(qg(c)),f.x=b.left+a.x,f.y=b.top+a.y;else if(c.getBoxObjectFor&&!e)b=c.getBoxObjectFor(a),a=c.getBoxObjectFor(g),f.x=b.screenX-a.screenX,f.y=b.screenY-a.screenY;else{b=a;do{f.x+=b.offsetLeft;f.y+= +b.offsetTop;b!=a&&(f.x+=b.clientLeft||0,f.y+=b.clientTop||0);if(yb&&"fixed"==Dh(b,"position")){f.x+=c.body.scrollLeft;f.y+=c.body.scrollTop;break}b=b.offsetParent}while(b&&b!=a);if(wb||yb&&"absolute"==d)f.y-=c.body.offsetTop;for(b=a;(b=Hh(b))&&b!=c.body&&b!=g;)f.x-=b.scrollLeft,wb&&"TR"==b.tagName||(f.y-=b.scrollTop)}return f}function Jh(a,b){var c=Kh(a),d=Kh(b);return new og(c.x-d.x,c.y-d.y)} +function Kh(a){if(1==a.nodeType){var b;if(a.getBoundingClientRect)b=Gh(a),b=new og(b.left,b.top);else{b=Ig(qg(a));var c=Ih(a);b=new og(c.x-b.x,c.y-b.y)}if(xb&&!Mb(12)){var d;G?d="-ms-transform":yb?d="-webkit-transform":wb?d="-o-transform":xb&&(d="-moz-transform");var e;d&&(e=Dh(a,d));e||(e=Dh(a,"transform"));a=e?(a=e.match(Lh))?new og(parseFloat(a[1]),parseFloat(a[2])):new og(0,0):new og(0,0);a=new og(b.x+a.x,b.y+a.y)}else a=b;return a}d=la(a.Ge);e=a;a.targetTouches?e=a.targetTouches[0]:d&&a.fa.targetTouches&& +(e=a.fa.targetTouches[0]);return new og(e.clientX,e.clientY)}function Fh(a,b){"number"==typeof a&&(a=(b?Math.round(a):a)+"px");return a}function Mh(a){var b=Nh;if("none"!=Dh(a,"display"))return b(a);var c=a.style,d=c.display,e=c.visibility,f=c.position;c.visibility="hidden";c.position="absolute";c.display="inline";a=b(a);c.display=d;c.position=f;c.visibility=e;return a} +function Nh(a){var b=a.offsetWidth,c=a.offsetHeight,d=yb&&!b&&!c;return s(b)&&!d||!a.getBoundingClientRect?new pg(b,c):(a=Gh(a),new pg(a.right-a.left,a.bottom-a.top))}function Oh(a,b){var c=a.style;"opacity"in c?c.opacity=b:"MozOpacity"in c?c.MozOpacity=b:"filter"in c&&(c.filter=""===b?"":"alpha(opacity\x3d"+100*b+")")}function Ph(a,b){a.style.display=b?"":"none"}function Qh(a){return"rtl"==Dh(a,"direction")} +function Rh(a,b){var c=Gg(qg(sg(a)));if(!G||c&&Mb("8")){var d=a.style;xb?d.MozBoxSizing="border-box":yb?d.WebkitBoxSizing="border-box":d.boxSizing="border-box";d.width=Math.max(b.width,0)+"px";d.height=Math.max(b.height,0)+"px"}else if(d=a.style,c){var c=Sh(a,"padding"),e=Th(a);d.pixelWidth=b.width-e.left-c.left-c.right-e.right;d.pixelHeight=b.height-e.top-c.top-c.bottom-e.bottom}else d.pixelWidth=b.width,d.pixelHeight=b.height} +function Uh(a,b,c,d){if(/^\d+px?$/.test(b))return parseInt(b,10);var e=a.style[c],f=a.runtimeStyle[c];a.runtimeStyle[c]=a.currentStyle[c];a.style[c]=b;b=a.style[d];a.style[c]=e;a.runtimeStyle[c]=f;return b}function Vh(a,b){var c=a.currentStyle?a.currentStyle[b]:null;return c?Uh(a,c,"left","pixelLeft"):0} +function Sh(a,b){if(G){var c=Vh(a,b+"Left"),d=Vh(a,b+"Right"),e=Vh(a,b+"Top"),f=Vh(a,b+"Bottom");return new Ah(e,d,f,c)}c=Ch(a,b+"Left");d=Ch(a,b+"Right");e=Ch(a,b+"Top");f=Ch(a,b+"Bottom");return new Ah(parseFloat(e),parseFloat(d),parseFloat(f),parseFloat(c))}var Wh={thin:2,medium:4,thick:6};function Xh(a,b){if("none"==(a.currentStyle?a.currentStyle[b+"Style"]:null))return 0;var c=a.currentStyle?a.currentStyle[b+"Width"]:null;return c in Wh?Wh[c]:Uh(a,c,"left","pixelLeft")} +function Th(a){if(G){var b=Xh(a,"borderLeft"),c=Xh(a,"borderRight"),d=Xh(a,"borderTop");a=Xh(a,"borderBottom");return new Ah(d,c,a,b)}b=Ch(a,"borderLeftWidth");c=Ch(a,"borderRightWidth");d=Ch(a,"borderTopWidth");a=Ch(a,"borderBottomWidth");return new Ah(parseFloat(d),parseFloat(c),parseFloat(a),parseFloat(b))}var Lh=/matrix\([0-9\.\-]+, [0-9\.\-]+, [0-9\.\-]+, [0-9\.\-]+, ([0-9\.\-]+)p?x?, ([0-9\.\-]+)p?x?\)/;function Yh(a,b){Nc.call(this);this.a=a;var c=ma(this.a)&&1==this.a.nodeType?this.a:this.a?this.a.body:null;this.e=!!c&&Qh(c);this.b=J(this.a,xb?"DOMMouseScroll":"mousewheel",this,b)}E(Yh,Nc); +Yh.prototype.handleEvent=function(a){var b=0,c=0,d=0;a=a.fa;if("mousewheel"==a.type){c=1;if(G||yb&&(qb||Mb("532.0")))c=40;d=Zh(-a.wheelDelta,c);s(a.wheelDeltaX)?(b=Zh(-a.wheelDeltaX,c),c=Zh(-a.wheelDeltaY,c)):c=d}else d=a.detail,100d&&(d=-3),s(a.axis)&&a.axis===a.HORIZONTAL_AXIS?b=d:c=d;ka(this.c)&&(b=Zc(b,-this.c,this.c));ka(this.d)&&(c=Zc(c,-this.d,this.d));this.e&&(b=-b);b=new $h(d,a,b,c);K(this,b)};function Zh(a,b){return yb&&(pb||rb)&&0!=a%b?a:a/b} +Yh.prototype.v=function(){Yh.F.v.call(this);Fc(this.b);this.b=null};function $h(a,b,c,d){b&&Ub(this,b,void 0);this.type="mousewheel";this.b=a;this.na=c;this.ma=d}E($h,Tb);var ai=p.document&&"ontouchstart"in p.document.documentElement||!!p.navigator.msPointerEnabled;function bi(a,b,c){ib.call(this,a);this.map=b;this.b=s(c)?c:null}E(bi,ib);function ci(a,b,c,d){bi.call(this,a,b,d);this.a=c;this.g=this.f=null}E(ci,bi);ci.prototype.d=function(){null===this.f&&(this.f=di(this.map,this.e()));return this.f};ci.prototype.e=function(){if(null===this.g){var a=Jh(this.a,this.map.b);this.g=[a.x,a.y]}return this.g};ci.prototype.U=function(){ci.F.U.call(this);this.a.U()};ci.prototype.rb=function(){ci.F.rb.call(this);this.a.rb()}; +function ei(a){Nc.call(this);this.a=a;this.c=!1;this.b=this.g=this.d=this.e=this.f=null;a=this.a.b;this.e=[J(a,["click","dblclick"],this.Bd,!1,this),J(a,"mousedown",this.cf,!1,this),J(a,"mousemove",this.pd,!1,this),J(a,"mouseout",this.pd,!1,this),J(a,"contextmenu",this.pd,!1,this)];this.g=[J(a,["touchstart","MSPointerDown"],this.rf,!1,this),J(p.document,["touchmove","MSPointerMove"],this.qf,!1,this),J(p.document,["touchend","MSPointerUp"],this.pf,!1,this)]}E(ei,Nc);m=ei.prototype; +m.Bd=function(a){if(!this.c){var b=a.type;K(this,0===this.f||"dblclick"==b?new ci(fi,this.a,a):new ci(gi,this.a,a))}};m.ef=function(a){this.b&&(this.b=null,Ga(this.d,Fc),this.d=null,this.c&&K(this,new ci(hi,this.a,a)))};m.cf=function(a){K(this,new ci(ii,this.a,a));this.b||(this.b=a,this.c=!1,this.d=[J(p.document,"mousemove",this.df,!1,this),J(p.document,"mouseup",this.ef,!1,this)],a.U())}; +m.df=function(a){var b;this.c||(this.c=!0,b=new ci(ji,this.a,this.b),K(this,b));b=new ci(ki,this.a,a);K(this,b)};m.pd=function(a){K(this,new ci(a.type,this.a,a))};m.rf=function(a){a.U();this.b=a;this.c=!1;K(this,new ci(li,this.a,a))};m.qf=function(a){this.b&&(this.c=!0,K(this,new ci(mi,this.a,a)))};m.pf=function(a){K(this,new ci(ni,this.a,a));this.c||(a=sa(),this.f=!this.f||250c)for(c=1;cf?1:0.5,d=Math.floor(Math.log(b/d)/Math.log(a)+f),e=Math.max(d+e,0),s(c)&&(e=Math.min(e,c)),b/Math.pow(a,e)}};function si(){return function(a,b){if(s(a))return 0.1>=Math.abs(a+b)?0:a+b}};function ti(a){var b=si();this.resolution=a;this.rotation=b};function T(a){Ze.call(this);a=a||{};var b={};b.center=s(a.center)?a.center:null;b.projection=je(a.projection);var c,d,e;if(s(a.resolutions))c=a.resolutions,d=c[0],e=c[c.length-1],c=qi(c);else{d=a.maxResolution;s(d)||(d=a.projection,e=je(d).ba(),d=(null===e?360*Kd.degrees/Kd[d.Kb]:Math.max(e[2]-e[0],e[3]-e[1]))/256);c=a.maxZoom;s(c)||(c=28);var f=a.zoomFactor;s(f)||(f=2);e=d/Math.pow(f,c);c=ri(f,d,c)}this.b=d;this.f=e;this.g=new ti(c);s(a.resolution)?b.resolution=a.resolution:s(a.zoom)&&(b.resolution= +this.Ha(this.b,a.zoom));b.rotation=s(a.rotation)?a.rotation:0;this.Zb(b)}E(T,Ze);function ui(a,b,c){var d,e=a.a();s(e)&&(d=[e[0]-c[0],e[1]-c[1]],jd(d,b-a.c()),hd(d,c));return d}function vi(a,b,c){var d,e=a.a();a=a.D();s(e)&&s(a)&&(d=[c[0]-b*(c[0]-e[0])/a,c[1]-b*(c[1]-e[1])/a]);return d}T.prototype.Ha=function(a,b,c){return this.g.resolution(a,b||0,c||0)};T.prototype.lc=function(a,b){return this.g.rotation(a,b||0)};T.prototype.a=function(){return this.get("center")};T.prototype.getCenter=T.prototype.a; +T.prototype.i=function(a){var b=this.a(),c=this.D();return[b[0]-c*a[0]/2,b[1]-c*a[1]/2,b[0]+c*a[0]/2,b[1]+c*a[1]/2]};T.prototype.ga=function(){return this.get("projection")};T.prototype.getProjection=T.prototype.ga;T.prototype.D=function(){return this.get("resolution")};T.prototype.getResolution=T.prototype.D;function wi(a){var b=a.b,c=Math.log(b/a.f)/Math.log(2);return function(a){return b/Math.pow(2,a*c)}}T.prototype.c=function(){return this.get("rotation")};T.prototype.getRotation=T.prototype.c; +function xi(a){var b=a.b,c=Math.log(b/a.f)/Math.log(2);return function(a){return Math.log(b/a)/Math.log(2)/c}}m=T.prototype;m.O=function(){return this};function yi(a){var b=a.a(),c=a.ga(),d=a.D();a=a.c();return{center:b.slice(),projection:s(c)?c:null,resolution:d,rotation:s(a)?a:0}}m.Qe=function(){var a,b=this.D();if(s(b)){var c,d=0;do{c=this.Ha(this.b,d);if(c==b){a=d;break}++d}while(c>this.f)}return a}; +m.$c=function(a,b){this.Da(wd(a));var c=Math.max((a[2]-a[0])/b[0],(a[3]-a[1])/b[1]),c=this.Ha(c,0,0);this.kb(c)};m.Wb=function(){return null!=this.a()&&s(this.D())};m.Da=function(a){this.l("center",a)};T.prototype.setCenter=T.prototype.Da;T.prototype.k=function(a){this.l("projection",a)};T.prototype.setProjection=T.prototype.k;T.prototype.kb=function(a){this.l("resolution",a)};T.prototype.setResolution=T.prototype.kb;T.prototype.d=function(a){this.l("rotation",a)};T.prototype.setRotation=T.prototype.d; +T.prototype.p=function(a){a=this.Ha(this.b,a,0);this.kb(a)};function zi(a){M.call(this);this.element=s(a.element)?a.element:null;this.p=a.target;this.a=null;this.e=[]}E(zi,M);zi.prototype.v=function(){Eg(this.element);zi.F.v.call(this)};zi.prototype.W=k("a");zi.prototype.d=da;zi.prototype.setMap=function(a){null===this.a||Eg(this.element);0!=this.e.length&&(Ga(this.e,Fc),this.e.length=0);this.a=a;null!==this.a&&((s(this.p)?this.p:a.K).appendChild(this.element),this.d!==da&&this.e.push(J(a,"postrender",this.d,!1,this)))};function Ai(a){a=s(a)?a:{};this.g=zg("UL");var b=wg("DIV",{"class":(s(a.className)?a.className:"ol-attribution")+" ol-unselectable"},this.g);zi.call(this,{element:b,target:a.target});this.f=!0;this.c={};this.b={}}E(Ai,zi); +Ai.prototype.d=function(a){a=a.b;if(null===a)this.f&&(Ph(this.element,!1),this.f=!1);else{var b,c,d,e,f,g,h,l,n,q=a.Hc,r=sc(a.attributions),w={};b=0;for(c=q.length;b=B.a&&g.a[v][t].c<=B.b&&g.a[v][t].b>= +B.c){t=!0;break a}t=!1}t?(h in w&&delete w[h],r[h]=g):w[h]=g}b=[r,w];a=b[0];b=b[1];for(var z in this.c)z in a?(this.b[z]||(Ph(this.c[z],!0),this.b[z]=!0),delete a[z]):z in b?(this.b[z]&&(Ph(this.c[z],!1),delete this.b[z]),delete b[z]):(Eg(this.c[z]),delete this.c[z],delete this.b[z]);for(z in a)c=zg("LI"),c.innerHTML=a[z].b,this.g.appendChild(c),this.c[z]=c,this.b[z]=!0;for(z in b)c=zg("LI"),c.innerHTML=b[z].b,Ph(c,!1),this.g.appendChild(c),this.c[z]=c;z=!rc(this.b);this.f!=z&&(Ph(this.element,z), +this.f=z)}};function Bi(a){a=s(a)?a:{};this.c=zg("UL");var b=wg("DIV",{"class":(s(a.className)?a.className:"ol-logo")+" ol-unselectable"},this.c);zi.call(this,{element:b,target:a.target});this.b=!0;this.f={}}E(Bi,zi); +Bi.prototype.d=function(a){a=a.b;if(null===a)this.b&&(Ph(this.element,!1),this.b=!1);else{var b;a=a.Wd;var c=this.f;for(b in c)b in a||(Eg(c[b]),delete c[b]);var d,e;for(b in a)b in c||(d=new Image,d.src=b,e=zg("LI"),e.appendChild(d),this.c.appendChild(e),c[b]=e);b=!rc(a);this.b!=b&&(Ph(this.element,b),this.b=b)}};function Ci(a){a=s(a)?a:{};var b=s(a.className)?a.className:"ol-zoom",c=s(a.delta)?a.delta:1,d=wg("A",{href:"#zoomIn","class":b+"-in"});J(d,["touchend","click"],ra(Ci.prototype.b,c),!1,this);var e=wg("A",{href:"#zoomOut","class":b+"-out"});J(e,["touchend","click"],ra(Ci.prototype.b,-c),!1,this);b=wg("DIV",b+" ol-unselectable",d,e);zi.call(this,{element:b,target:a.target})}E(Ci,zi); +Ci.prototype.b=function(a,b){b.U();var c=this.a,d=c.a().O(),e=d.D();s(e)&&(c.Ga(vf({resolution:e,duration:250,easing:af})),c=d.Ha(e,a),d.kb(c))};function Di(a){a=s(a)?a:{};var b=new N;(s(a.attribution)?a.attribution:1)&&b.push(new Ai(s(a.attributionOptions)?a.attributionOptions:void 0));(s(a.logo)?a.logo:1)&&b.push(new Bi(s(a.logoOptions)?a.logoOptions:void 0));(s(a.zoom)?a.zoom:1)&&b.push(new Ci(s(a.zoomOptions)?a.zoomOptions:void 0));return b};function Ei(){}function Fi(a,b,c,d,e){if(null!=c){var f=b.c(),g=b.a();s(f)&&(s(g)&&s(e))&&(a.Ga(uf({rotation:f,duration:e,easing:af})),s(d)&&a.Ga(tf({source:g,duration:e,easing:af})));if(null!=d){var h=ui(b,c,d);Gi(a,function(){b.Da(h);b.d(c)})}else b.d(c)}}function Hi(a,b,c,d,e){var f=b.D();c=b.Ha(f,c,0);Ii(a,b,c,d,e)} +function Ii(a,b,c,d,e){if(null!=c){var f=b.D(),g=b.a();s(f)&&(s(g)&&s(e))&&(a.Ga(vf({resolution:f,duration:e,easing:af})),s(d)&&a.Ga(tf({source:g,duration:e,easing:af})));if(null!=d){var h=vi(b,c,d);Gi(a,function(){b.Da(h);b.kb(c)})}else b.kb(c)}};function Ji(a){a=s(a)?a:{};this.a=s(a.delta)?a.delta:1}E(Ji,Ei);Ji.prototype.xb=function(a){var b=!1,c=a.a;if(a.type==fi&&(ai||Wb(a.a))){var b=a.map,d=a.d(),c=c.Wa?-this.a:this.a,e=b.a().O();Hi(b,e,c,d,250);a.U();b=!0}return!b};function Ki(a){a=a.a;return a.wa&&!a.Gb&&a.Wa}function Li(a){return"click"==a.a.type}function Mi(a){a=a.a;return!a.wa&&!a.Gb&&!a.Wa}function Ni(a){a=a.a;return!a.wa&&!a.Gb&&a.Wa}function Oi(a){a=a.a.target.tagName;return"INPUT"!==a&&"SELECT"!==a&&"TEXTAREA"!==a};function Pi(){this.c=!1;this.q=this.i=this.e=this.d=0;this.fc=this.g=null}E(Pi,Ei);m=Pi.prototype;m.Bc=da;m.Tb=da;m.Ub=Pe;m.Sd=da; +m.xb=function(a){var b=a.map;if(!b.Wb())return!0;var c=!1,b=b.a(),d=a.a;a.type==ii&&this.Sd(a);if(this.c)a.type==ki?(this.na=d.clientX-this.d,this.ma=d.clientY-this.e,this.Bc(a)):a.type==hi&&(this.na=d.clientX-this.d,this.ma=d.clientY-this.e,this.Tb(a),$e(b,-1),this.c=!1);else if(a.type==ji){var e=yi(b.O());this.d=d.clientX;this.e=d.clientY;this.ma=this.na=0;this.g=e.center;this.fc=a.d();this.Ub(a)&&($e(b,1),this.c=!0,a.U(),c=!0)}return!c};function Qi(a){Pi.call(this);a=s(a)?a:{};this.f=s(a.condition)?a.condition:Mi;this.a=a.kinetic;this.b=null}E(Qi,Pi);Qi.prototype.Bc=function(a){this.a&&this.a.a.push(a.a.clientX,a.a.clientY,sa());a=a.map;var b=a.a(),c=yi(b),d=[-c.resolution*this.na,c.resolution*this.ma];jd(d,c.rotation);hd(d,this.g);Ri(a);b.Da(d)}; +Qi.prototype.Tb=function(a){a=a.map;var b=a.a().O();if(this.a&&xf(this.a)){var c=yi(b),d=(this.a.d-this.a.b)/this.a.e,e=this.a.c;this.b=yf(this.a,c.center);a.Ga(this.b);c=Si(a,c.center);d=di(a,[c[0]-d*Math.cos(e),c[1]-d*Math.sin(e)]);b.Da(d)}Ri(a)};Qi.prototype.Ub=function(a){var b=a.a;if(Wb(b)&&this.f(a)){if(this.a){var c=this.a;c.a.length=0;c.c=0;c.b=0;this.a.a.push(b.clientX,b.clientY,sa())}Ri(a.map);return!0}return!1}; +Qi.prototype.Sd=function(a){var b=a.map,c=b.a();null!==this.b&&Oa(b.g,this.b)&&(Ri(b),c.Da(a.b.A.center),this.b=null)};function Ti(a){a=s(a)?a:{};Pi.call(this);this.b=s(a.condition)?a.condition:Ki;this.a=void 0}E(Ti,Pi);Ti.prototype.Bc=function(a){var b=a.map,c=b.c();a=a.e();c=Math.atan2(c[1]/2-a[1],a[0]-c[0]/2);if(s(this.a)){a=c-this.a;var d=b.a().O(),e=yi(d);Ri(b);Fi(b,d,e.rotation-a)}this.a=c};Ti.prototype.Tb=function(a){a=a.map;var b=a.a().O(),c=yi(b).rotation,c=b.lc(c,0);Fi(a,b,c,void 0,250)};Ti.prototype.Ub=function(a){return Wb(a.a)&&this.b(a)?(Ri(a.map),this.a=void 0,!0):!1};function Ui(a){var b=wg("DIV","ol-dragbox");this.b=null;this.c=a.fc;zi.call(this,{element:b})}E(Ui,zi);Ui.prototype.setMap=function(a){Ui.F.setMap.call(this,a);null!==a&&(this.b=Si(a,this.c),Eh(this.element,this.b[0],this.b[1]),Rh(this.element,new pg(0,0)),this.e.push(J(a,ki,this.f,!1,this)))};Ui.prototype.f=function(a){var b=this.a;a=a.d();b=Si(b,a);Eh(this.element,Math.min(b[0],this.b[0]),Math.min(b[1],this.b[1]));Rh(this.element,new pg(Math.abs(b[0]-this.b[0]),Math.abs(b[1]-this.b[1])))};function Vi(a){Pi.call(this);a=s(a)?a:{};this.b=s(a.condition)?a.condition:Ni;this.a=null}E(Vi,Pi);Vi.prototype.Tb=function(a){this.a.setMap(null);this.a=null;if(64<=this.na*this.na+this.ma*this.ma){var b=a.map,c=nd([this.fc,a.d()]);Gi(b,function(){var a=b.a(),e=b.c();a.$c(c,e);a.d(0)})}};Vi.prototype.Ub=function(a){return Wb(a.a)&&this.b(a)?(this.a=new Ui({fc:this.fc}),this.a.setMap(a.map),!0):!1};function Wi(a){a=s(a)?a:{};this.a=s(a.condition)?a.condition:Ve(Mi,Oi);this.b=s(a.delta)?a.delta:128}E(Wi,Ei);Wi.prototype.xb=function(a){var b=!1;if("key"==a.type){var c=a.a.Va;if(this.a(a)&&(40==c||37==c||39==c||38==c)){var b=a.map,d=b.a(),e=yi(d),f=e.resolution*this.b,g=0,h=0;40==c?h=-f:37==c?g=-f:39==c?g=f:h=f;c=[g,h];jd(c,e.rotation);e=d.a();s(e)&&(s(100)&&b.Ga(tf({source:e,duration:100,easing:cf})),d.Da([e[0]+c[0],e[1]+c[1]]));a.U();b=!0}}return!b};function Xi(a){a=s(a)?a:{};this.b=s(a.condition)?a.condition:Oi;this.a=s(a.delta)?a.delta:1}E(Xi,Ei);Xi.prototype.xb=function(a){var b=!1;if("key"==a.type){var c=a.a.ed;if(this.b(a)&&(43==c||45==c)){b=a.map;c=43==c?this.a:-this.a;Ri(b);var d=b.a().O();Hi(b,d,c,void 0,100);a.U();b=!0}}return!b};function Yi(){this.a=0;this.c=null;this.d=this.b=void 0}E(Yi,Ei);Yi.prototype.xb=function(a){var b=!1;if("mousewheel"==a.type){var b=a.map,c=a.a;this.c=a.d();this.a+=c.ma/3;s(this.b)||(this.b=sa());c=Math.max(80-(sa()-this.b),0);p.clearTimeout(this.d);this.d=p.setTimeout(y(this.e,this,b),c);a.U();b=!0}return!b};Yi.prototype.e=function(a){var b=Zc(this.a,-1,1),c=a.a().O();Ri(a);Hi(a,c,-b,this.c,250);this.a=0;this.c=null;this.d=this.b=void 0};function Zi(){this.c=!1;this.i={};this.targetTouches=[]}E(Zi,Ei);function $i(a){for(var b=a.length,c=0,d=0,e=0;ethis.q&&(this.a=!0));this.d=c;a=a.map;c=Kh(a.b);d=$i(this.targetTouches);d[0]-=c.x;d[1]-=c.y;this.b=di(a,d);this.a&&(c=a.a().O(),d=yi(c),Ri(a),Fi(a,c,d.rotation+b,this.b))}; +bj.prototype.e=function(a){if(2>this.targetTouches.length){a=a.map;var b=a.a().O(),c=yi(b);if(this.a){var c=c.rotation,d=this.b,c=b.lc(c,0);Fi(a,b,c,d,250)}return!1}return!0};bj.prototype.g=function(a){return 2<=this.targetTouches.length?(a=a.map,this.b=null,this.d=void 0,this.a=!1,this.V=0,Ri(a),!0):!1};function cj(){Zi.call(this);this.b=null;this.a=void 0;this.d=1}E(cj,Zi);cj.prototype.f=function(a){var b=1,c=this.targetTouches[0],d=this.targetTouches[1],e=c.clientX-d.clientX,c=c.clientY-d.clientY,e=Math.sqrt(e*e+c*c);s(this.a)&&(b=this.a/e);this.a=e;1!=b&&(this.d=b);a=a.map;var e=a.a().O(),c=yi(e),d=Kh(a.b),f=$i(this.targetTouches);f[0]-=d.x;f[1]-=d.y;this.b=di(a,f);Ri(a);Ii(a,e,c.resolution*b,this.b)}; +cj.prototype.e=function(a){if(2>this.targetTouches.length){a=a.map;var b=a.a().O(),c=yi(b).resolution,d=this.b,c=b.Ha(c,0,this.d-1);Ii(a,b,c,d,400);return!1}return!0};cj.prototype.g=function(a){return 2<=this.targetTouches.length?(a=a.map,this.b=null,this.a=void 0,this.d=1,Ri(a),!0):!1};function dj(a){a=s(a)?a:{};var b=new N,c=new wf(-0.005,0.05,100);(s(a.altShiftDragRotate)?a.altShiftDragRotate:1)&&b.push(new Ti);(s(a.doubleClickZoom)?a.doubleClickZoom:1)&&b.push(new Ji({delta:a.zoomDelta}));(s(a.touchPan)?a.touchPan:1)&&b.push(new aj({kinetic:c}));(s(a.touchRotate)?a.touchRotate:1)&&b.push(new bj);(s(a.touchZoom)?a.touchZoom:1)&&b.push(new cj);(s(a.dragPan)?a.dragPan:1)&&b.push(new Qi({kinetic:c}));if(s(a.keyboard)?a.keyboard:1)b.push(new Wi),b.push(new Xi({delta:a.zoomDelta})); +(s(a.mouseWheelZoom)?a.mouseWheelZoom:1)&&b.push(new Yi);(s(a.shiftDragZoom)?a.shiftDragZoom:1)&&b.push(new Vi);return b};function ej(a){var b=s(a)?a:{};a=sc(b);delete a.layers;b=b.layers;S.call(this,a);this.a=null;J(this,Uc("layers"),this.$e,!1,this);s(b)?ia(b)&&(b=new N(Ra(b))):b=new N;this.c(b)}E(ej,S);m=ej.prototype;m.Cc=function(){this.b()&&Me(this)};m.Td=function(){Me(this)}; +m.$e=function(){null!==this.a&&(Ga(kc(this.a),Fc),this.a=null);var a=this.gb();if(null!=a){this.a={add:J(a,"add",this.Ze,!1,this),remove:J(a,"remove",this.af,!1,this)};var a=a.a,b,c,d;b=0;for(c=a.length;b=this.minZoom;){if(b.call(c,a,sj(this,e,a,d)))return!0;--a}return!1};m.Le=k("minZoom"); +m.Fb=function(a){return null===this.d?this.f[a]:this.d};m.D=function(a){return this.a[a]};m.Pb=k("a");m.yc=function(a,b,c){return a.za.d&&(a.d=d.d),d.ca.b&&(a.b=d.b)):a[b][c]=d:(a[b]={},a[b][c]=d)}function dk(a,b,c){return function(d,e,f){d=b.Db(d,e,f,c);return a(d)?d:null}}function ek(a,b,c){return[b*(Math.round(a[0]/b)+c[0]%2/2),b*(Math.round(a[1]/b)+c[1]%2/2)]} +function fk(a,b,c,d,e,f,g,h,l){var n=x(b).toString();n in a.Lb||(a.Lb[n]={});var q=a.Lb[n];a=a.Uf;var r=c.minZoom,w,t,A,B,v,z;for(z=f;z>=r;--z)for(t=sj(c,e,z),A=c.D(z),B=t.a;B<=t.d;++B)for(v=t.c;v<=t.b;++v)f-z<=g?(w=b.Db(z,B,v,d),0==w.a&&(q[w.H.toString()]=!0,w.b()in a.c||Ie(a,[w,n,Tj(c,w.H),A])),s(h)&&h.call(l,w)):b.ne(z,B,v)};function gk(a,b){db.call(this);this.f=b;this.d={}}E(gk,db); +function hk(a){var b=a.A,c=a.Dd;ye(c);Ce(c,a.size[0]/2,a.size[1]/2);De(c,1/b.resolution,-1/b.resolution);Ee(c,-b.rotation);Ce(c,-b.center[0],-b.center[1]);a=a.ee;var b=c[0],d=c[1],e=c[2],f=c[3],g=c[4],h=c[5],l=c[6],n=c[7],q=c[8],r=c[9],w=c[10],t=c[11],A=c[12],B=c[13],v=c[14],c=c[15],z=b*h-d*g,H=b*l-e*g,D=b*n-f*g,R=d*l-e*h,U=d*n-f*h,P=e*n-f*l,F=q*B-r*A,L=q*v-w*A,aa=q*c-t*A,va=r*v-w*B,ea=r*c-t*B,ha=w*c-t*v,Z=z*ha-H*ea+D*va+R*aa-U*L+P*F;0!=Z&&(Z=1/Z,a[0]=(h*ha-l*ea+n*va)*Z,a[1]=(-d*ha+e*ea-f*va)*Z,a[2]= +(B*P-v*U+c*R)*Z,a[3]=(-r*P+w*U-t*R)*Z,a[4]=(-g*ha+l*aa-n*L)*Z,a[5]=(b*ha-e*aa+f*L)*Z,a[6]=(-A*P+v*D-c*H)*Z,a[7]=(q*P-w*D+t*H)*Z,a[8]=(g*ea-h*aa+n*F)*Z,a[9]=(-b*ea+d*aa-f*F)*Z,a[10]=(A*U-B*D+c*z)*Z,a[11]=(-q*U+r*D-t*z)*Z,a[12]=(-g*va+h*L-l*F)*Z,a[13]=(b*va-d*L+e*F)*Z,a[14]=(-A*R+B*H-v*z)*Z,a[15]=(q*R-r*H+w*z)*Z)}m=gk.prototype;m.mc=function(a){return new Xj(this,a)};m.v=function(){gc(this.d,function(a){hb(a)});gk.F.v.call(this)};m.wc=Re; +m.Ta=function(a,b,c,d){function e(a,d){g[Fa(b,d)]=a;--f;f||c(g)}for(var f=b.length,g=Array(f),h,l=0;ld;else if("\x3c"===b)d=a=d;else if("\x3c\x3d"===b)d=a<=d;else throw Error("Unsupported comparison operator: "+this.b);return d};function yk(a){this.b=a} +E(yk,tk);yk.prototype.a=function(a){if(null==a)throw Error("Attempt to evaluate identifier with no scope");return a[this.b]};function V(a){this.$a=a}E(V,tk);V.prototype.a=k("$a");var zk={fg:"\x26\x26",Rg:"||"};function Ak(a,b,c){this.b=a;this.Na=b;this.Qa=c}E(Ak,tk);var Bk=function(){var a={},b;for(b in zk)a[zk[b]]=!0;return function(b){return!!a[b]}}(); +Ak.prototype.a=function(a,b,c){var d;d=this.Qa.a(a,b,c);a=this.Na.a(a,b,c);if("\x26\x26"===this.b)d=a&&d;else if("||"===this.b)d=a||d;else throw Error("Unsupported logical operator: "+this.b);return d};var Ck={eg:"+",Xg:"-",Mg:"*",ng:"/",Ig:"%"};function Dk(a,b,c){this.b=a;this.Na=b;this.Qa=c}E(Dk,tk);var Ek=function(){var a={},b;for(b in Ck)a[Ck[b]]=!0;return function(b){return!!a[b]}}(); +Dk.prototype.a=function(a,b,c){var d;d=this.Qa.a(a,b,c);a=this.Na.a(a,b,c);b=this.b;if("+"===b)d=a+d;else if("-"===b)d=Number(a)-Number(d);else if("*"===b)d=Number(a)*Number(d);else if("/"===b)d=Number(a)/Number(d);else if("%"===b)d=Number(a)%Number(d);else throw Error("Unsupported math operator: "+this.b);return d};function Fk(a,b){this.b=a;this.c=b}E(Fk,tk);Fk.prototype.a=function(a,b,c){a=this.b.a(a,b,c);if(!ma(a))throw Error("Expected member expression to evaluate to an object but got "+a);return this.c.a(a)}; +function Gk(a){this.b=a}E(Gk,tk);Gk.prototype.a=function(a,b,c){return!this.b.a(a,b,c)};function Hk(a){this.b=a;this.c=a.length;this.d=this.a=0}function Ik(a,b){if(!a.match(b))throw new Jk({type:"Unknown",value:a.b[a.a],index:a.a});a.a=a.d}function Kk(a,b){a.a+=b}function Lk(a){return 48<=a&&57>=a}function Mk(a){return 36===a||95===a||65<=a&&90>=a||97<=a&&122>=a}function Nk(a){return a.b.charCodeAt(a.a+0)}Hk.prototype.match=function(a){var b=Ok(this);return"Punctuator"===b.type&&b.value===a}; +function Pk(a){var b;for(b=NaN;a.a=a.c)a={type:"\x3cend\x3e",value:null,index:a.a};else if(40===b||41===b)a=Qk(a,b);else if(39===b||34===b){var c=a.a;Kk(a,1);for(var d="",e;a.a=c)Kk(a,1);else break;a=a.b.slice(b,a.a);a={type:1===a.length?"Identifier":"break"===a||"case"===a||"catch"===a||"continue"===a||"debugger"===a||"default"===a||"delete"===a||"do"===a||"else"===a||"finally"===a||"for"===a||"function"===a||"if"===a||"in"===a||"instanceof"===a||"new"===a||"return"===a||"switch"===a||"this"===a||"throw"===a||"try"===a||"typeof"===a||"var"=== +a||"void"===a||"while"===a||"with"===a?"Keyword":"null"===a?"Null":"true"===a||"false"===a?"Boolean":"Identifier",value:a,index:b}}else a=46===b?Lk(a.b.charCodeAt(a.a+1))?Rk(a,b):Qk(a,b):Lk(b)?Rk(a,b):Qk(a,b);return a}function Ok(a){var b=a.a,c=Pk(a);a.d=a.a;a.a=b;return c} +function Rk(a,b){var c="",d=a.a;if(46!==b){if(48===b){var e=a.b.charCodeAt(a.a+1);if(88===e||120===e){Kk(a,2);c=Nk(a);d="";for(e=a.a-2;a.a=c||65<=c&&70>=c);)d+=String.fromCharCode(c),Kk(a,1),c=Nk(a);if(0===d.length||Mk(c))throw new Jk({type:"Unknown",value:String.fromCharCode(c),index:a.a});return{type:"Numeric",value:parseInt("0x"+d,16),index:e}}if(48<=e&&55>=e){Kk(a,1);d="0"+String.fromCharCode(e);e=a.a-1;for(Kk(a,1);a.a=c))break;d+=String.fromCharCode(c); +Kk(a,1)}c=Nk(a);if(Mk(c)||Lk(c))throw new Jk({type:"Unknown",value:String.fromCharCode(c),index:a.a});return{type:"Numeric",value:parseInt(d,8),index:e}}if(Lk(e))throw new Jk({type:"Unknown",value:String.fromCharCode(e),index:a.a});}for(;Lk(b);)c+=String.fromCharCode(b),Kk(a,1),b=Nk(a)}if(46===b)for(c+=String.fromCharCode(b),Kk(a,1),b=Nk(a);Lk(b);)c+=String.fromCharCode(b),Kk(a,1),b=Nk(a);if(69===b||101===b){c+="E";Kk(a,1);b=Nk(a);if(43===b||45===b)c+=String.fromCharCode(b),Kk(a,1),b=Nk(a);if(!Lk(b))throw new Jk({type:"Unknown", +value:String.fromCharCode(b),index:a.a});for(;Lk(b);)c+=String.fromCharCode(b),Kk(a,1),b=Nk(a)}if(Mk(b))throw new Jk({type:"Unknown",value:String.fromCharCode(b),index:a.a});return{type:"Numeric",value:parseFloat(c),index:d}} +function Qk(a,b){var c=a.a;if(46===b||40===b||41===b||44===b||43===b||45===b||42===b||47===b||37===b||126===b)return Kk(a,1),{type:"Punctuator",value:String.fromCharCode(b),index:c};var d=a.b.charCodeAt(a.a+1);if(61===d){if(33===b||61===b)return Kk(a,2),61===Nk(a)?(Kk(a,1),{type:"Punctuator",value:String.fromCharCode(b)+"\x3d\x3d",index:c}):{type:"Punctuator",value:String.fromCharCode(b)+"\x3d",index:c};if(62===b||60===b)return Kk(a,2),{type:"Punctuator",value:String.fromCharCode(b)+"\x3d",index:c}}if(b=== +d&&(124===b||38===b))return Kk(a,2),d=String.fromCharCode(b),{type:"Punctuator",value:d+d,index:c};if(62===b||60===b||33===b||38===b||124===b)return Kk(a,1),{type:"Punctuator",value:String.fromCharCode(b),index:c};throw new Jk({type:"Unknown",value:String.fromCharCode(b),index:a.a});}function Jk(a,b){ta.call(this,s(b)?b:"Unexpected token "+a.value+" at index "+a.index);this.a=a}E(Jk,ta);Jk.prototype.name="UnexpectedToken";function Sk(){}function Tk(a){var b=0;if("Punctuator"!==a.type)return b;switch(a.value){case "||":b=1;break;case "\x26\x26":b=2;break;case "\x3d\x3d":case "!\x3d":case "\x3d\x3d\x3d":case "!\x3d\x3d":b=3;break;case "\x3e":case "\x3c":case "\x3e\x3d":case "\x3c\x3d":b=4;break;case "+":case "-":b=5;break;case "*":case "/":case "%":b=6}return b} +function Uk(a,b,c){if(xk(a))a=new wk(a,b,c);else if(Bk(a))a=new Ak(a,b,c);else if(Ek(a))a=new Dk(a,b,c);else throw Error("Unsupported binary operator: "+a);return a}function Vk(a){return new V(a)}function Wk(a){var b=new Hk(a);a=Xk(new Sk,b);b=Ok(b);if("\x3cend\x3e"!==b.type)throw new Jk(b);return a} +function Xk(a,b){var c=Yk(a,b),d=Ok(b),e=Tk(d);if(0===e)return c;b.a=b.d;for(var f=Yk(a,b),g=[c,d,f],e=Tk(Ok(b));0b.extent[2]?l.extent[2]:b.extent[2])-(l.extent[0]b.extent[3]?l.extent[3]:b.extent[3])-(l.extent[1]e||Math.abs(l-n)g[h].extent[0]?h=q:r.extent[2]g[l].extent[1]?l=q:r.extent[3]Math.abs(g[n].extent[3]-g[l].extent[1])?c>h?(q=g.splice(c,1)[0],r=g.splice(h,1)[0]):(r=g.splice(h,1)[0],q=g.splice(c,1)[0]):n>l?(q=g.splice(n,1)[0],r=g.splice(l,1)[0]):(r=g.splice(l,1)[0],q=g.splice(n,1)[0]);for(g=[{extent:q.extent.slice(),n:[q]},{extent:r.extent.slice(),n:[r]}];0v.extent[2]?n.extent[2]:v.extent[2],n.extent[1]v.extent[3]?n.extent[3]:v.extent[3]],z=Math.abs(Dl(z[1]-z[0],z[3]-z[2],n.n.length+2)-r),v=[l.extent[0]v.extent[2]?l.extent[2]: +v.extent[2],l.extent[1]v.extent[3]?l.extent[3]:v.extent[3]],v=Math.abs(Dl(v[1]-v[0],v[3]-v[2],l.n.length+2)-w),H=Math.abs(v-z);if(!A||!t||Hf.length&&(d.n.push(e[0]),f.push(d),b=e[1])}}else ud(d.extent,b.extent),b={extent:d.extent.slice()}}while(0< +f.length)}}Bl.prototype.remove=function(a,b){arguments[0]={extent:a};switch(arguments.length){case 1:arguments[1]=!1;case 2:arguments[2]=this.b;default:arguments.length=3}if(!1===arguments[1]){var c=0,d=[];do c=d.length,d=d.concat(this.d.apply(this,arguments));while(c!=d.length);return d}return this.d.apply(this,arguments)}; +Bl.prototype.d=function(a,b,c){var d=[],e=[],f=[];if(!a||!zd(a.extent,c.extent))return f;a=a.extent.slice();var g;e.push(c.n.length);d.push(c);do{c=d.pop();var h=e.pop()-1;if(s(b))for(;0<=h;){var l=c.n[h];if(zd(a,l.extent))if(b&&s(l.wb)&&l.wb===b||!b&&(s(l.wb)||sd(a,l.extent))){s(l.n)?(f=Fl(l,!0,[],l),c.n.splice(h,1)):f=c.n.splice(h,1);Cl(c);b=void 0;c.n.length=c.n.length?(g=Fl(c,!0,g,c),c.n.length=0,d.push(c),e.push(1)):0this.d&&!(b=this.a.$a,c=b.H.z.toString(),c in a&&a[c].contains(b.H));)this.pop()};function nm(){this.bounds=this.o=this.a=null}E(nm,Dd);nm.prototype.ua=function(){if(null===this.bounds){for(var a=od(),b=this.o,c=0,d=b.length;cf&&(f=e),lh&&(h=l);this.Sa=[c,g,f,h]}return this.Sa};m.N=ba("linestring"); +m.qc=function(a){for(var b=this.s(),c=Infinity,d=0,e=1,f=b.length;eh?kd(a,d):1a!=h>a&&b<(g-e)*(a-f)/(h-f)+e)&&(d=!d);return d};function um(a,b){this.a=null;var c=b;s(c)||(c=a[0][0].length,c=new Cd({dimension:c}));this.c=null;this.a=c;var d=a.length;this.b=Array(d);for(var e,f=0;f=c&&l[1]<=c||h[1]<=c&&l[1]>=c)h=(c-h[1])/(l[1]-h[1])*(l[0]-h[0])+h[0],d.push(h);d.sort();for(g=d.length-1;1<=g;--g)e=Math.abs(d[g]-d[g-1]),e>f&&(h=(d[g]+d[g-1])/2,a.mb([h,c])&&(f=e,b=h));a.c=[b,c]}a=a.c;return[[a[0], +a[1],0]]}throw Error("Label rendering not implemented for geometry type: "+c);}function zm(a,b){var c=a.url,d=Am[c],e=!1;if(!s(d))e=!0,d=zg("IMG"),Cc(d,"error",y(Bm,null,b),!1,zm),Cc(d,"load",y(Cm,null,b),!1,zm),d.setAttribute("src",c);else if(null!==d){var c=a.width,f=a.height;s(c)&&s(f)?(d.width=c,d.height=f):s(c)?(d.height*=c/d.width,d.width=c):s(f)&&(d.width*=f/d.height,d.height=f)}return e?null:d}var Am={};function Bm(a,b){if(s(b)){var c=b.target.getAttribute("src");Am[c]=null;Cm(a,b)}} +function Cm(a,b){if(s(b)){var c=b.target.getAttribute("src");Am[c]=b.target}s(a)&&a()};function Dm(a,b){Xj.call(this,a,b);this.i=zg("CANVAS");this.ia=this.i.getContext("2d");this.C=ue();this.sa=zg("CANVAS");this.Ra=ue();this.c=new mm(Em);J(b,["add","change","remove","intentchange"],this.We,!1,this);this.d=null;this.la="point multipoint linestring multilinestring polygon multipolygon".split(" ");this.K=null;this.p=this.q=!1;this.f=null;this.W=new ab(NaN,NaN,NaN,NaN);this.t=y(function(){this.q=!0;Ri(a.f)},this)}E(Dm,gm);m=Dm.prototype;m.ca=k("i");m.cd=k("C"); +m.Ta=function(a,b){this.md(a,function(a,d){b((0,d.Vf)(a),d)})}; +m.md=function(a,b,c){var d=this.a.f,e=[],f=this.b;a=di(d,a);var g=Uj(this.f,a,0).toString();if(km(this.c,g)){var h=this.c.get(g),g=h[1],l=h[2],h=h[3],n=l[0]/2,l=l[1]/2,l=nd([[a[0]-n,a[1]-l],[a[0]+n,a[1]+l]]),d=fm(f,l,d.a().O().ga());if(null===d){s(c)&&p.setTimeout(function(){c()},0);return}var q,r,w,t;for(t in d)if(l=d[t],n=l.G(),q=n.N(),"point"===q||"multipoint"===q)for(r=x(l),q=g[r],r=h[r],w=q[0]/2,q=q[1]/2,q=nd([[a[0]-w-r[0],a[1]-q+r[1]],[a[0]+w-r[0],a[1]+q+r[1]]]),n=n.s(),ia(n[0])||(n=[n]),r= +n.length-1;0<=r;--r){if(rd(q,n[r])){e.push(l);break}}else la(n.mb)?n.mb(a)&&e.push(l):la(n.qc)&&2*n.qc(a)<=g[x(l)][0]&&e.push(l)}p.setTimeout(function(){b(e,f)},0)};m.We=function(a){var b=a.extent;a=this.c;if(s(b))for(var b=sj(this.f,b,0),c=a.T(),d;c--;)d=a.a.Xb,b.contains(Ya(d))?a.pop():a.get(d);else a.clear();this.t()}; +m.Pa=function(a){var b=a.A,c=b.resolution,d=b.projection,e=a.extent,f=this.b,g=this.f,h=[512,512],l=!a.L[0]&&!a.L[1];if(l){var n=0.14929107086948487,q=d.a();q&&(n/=q);var r=Math.max(c,n);r!==this.R&&(g=new pj({origin:[0,0],projection:d,resolutions:[r],tileSize:h}),this.c.clear(),this.f=g)}if(null!==g){var w=g.D(0);l&&tj(g,e,w,this.W);var t=this.C,A=this.W,B,v=g,z=v.Fb(0),H=v.D(0),D=v.Ba(0);B=qd(z[0]+A.a*D[0]*H,z[0]+(A.d+1)*D[0]*H,z[1]+A.c*D[1]*H,z[1]+(A.b+1)*D[1]*H,void 0);var R=yd(B);ye(t);Ce(t, +a.size[0]/2,a.size[1]/2);De(t,w/c,w/c);Ee(t,b.rotation);Ce(t,(R[0]-b.center[0])/w,(b.center[1]-R[1])/w);if(this.q||this.R!==w||!td(this.K,B)){null===this.d&&(this.d=zg("CANVAS"),this.d.width=h[0],this.d.height=h[1]);var U=this.sa,P=h[0]*(A.d-A.a+1),F=h[1]*(A.b-A.c+1),L=this.Ra,aa=P/2,va=F/2;ye(L);Ce(L,aa,va);De(L,1/w,-1/w);Ce(L,-(R[0]+aa*w),-(R[1]-va*w));U.width=P;U.height=F;var ea=new xm(U,L,this.t),ha=this.i;ha.width=P;ha.height=F;var Z=this.ia,Pa={},Ea={},Bb={},Hg=15*w,ff,Yb,nc,Kg,Lg,on=this.la, +Fr=on.length,uj=!1,pn=!1,Mg,Hc,Zb,vj,Ng,Og,qn,Pg,Qg;Kg=A.a;a:for(;Kg<=A.d;++Kg)for(Lg=A.c;Lg<=A.b;++Lg)if(Yb=new Xa(0,Kg,Lg),nc=Yb.toString(),km(this.c,nc))Ea[nc]=Yb;else if(l){Zb=rj(g,Yb);Zb[0]-=Hg;Zb[2]+=Hg;Zb[1]-=Hg;Zb[3]+=Hg;Qg=!1;for(Mg=0;Mgthis.c.d;)this.c.pop();this.p=!1};var Em=128;function Fm(a,b){gk.call(this,0,b);this.b=zg("CANVAS");this.b.height=a.clientHeight;this.b.width=a.clientWidth;this.b.className="ol-unselectable";Dg(a,this.b);this.c=!0;this.e=[a.clientHeight,a.clientWidth];this.g=this.b.getContext("2d")}E(Fm,gk);Fm.prototype.mc=function(a){return a instanceof rk?new hm(this,a):a instanceof sk?new im(this,a):a instanceof cm?new Dm(this,a):null};Fm.prototype.wc=k("b"); +Fm.prototype.Jc=function(a){if(null===a)this.c&&(Ph(this.b,!1),this.c=!1);else{var b=a.size;if(this.e[0]!=b[0]||this.e[1]!=b[1])this.b.width=b[0],this.b.height=b[1],this.e=b;var c=this.g;c.clearRect(0,0,b[0],b[1]);hk(a);var b=a.qa,d=a.Hc,e=a.A.resolution,f,g,h,l,n;f=0;for(g=d.length;f=n.maxResolution||ec;++c)d[c]=b[c].toFixed(6);c=d.join(",")}else c=b.join(",");c="matrix3d("+c+")";d=a.style;d.WebkitTransform=c;d.MozTransform=c;d.a=c;d.transform=c};function Hm(a,b,c){Xj.call(this,a,b);this.target=c}E(Hm,Xj);function Im(a,b){var c=zg("DIV");c.style.position="absolute";Hm.call(this,a,b,c);this.c=null;this.d=we()}E(Im,Hm); +Im.prototype.Pa=function(a){var b=a.A,c=b.center,d=b.resolution,e=b.rotation,f=this.c,g=this.b.ja(),h=a.L;h[0]||h[1]||(b=g.ca(a.extent,d,b.projection),null!==b&&(h=b.a,0==h?(Cc(b,"change",this.k,!1,this),oj(b)):2==h&&(f=b)));if(null!==f){var h=f.ba(),l=f.D(),b=ue();ye(b);Ce(b,a.size[0]/2,a.size[1]/2);Ee(b,e);De(b,l/d,l/d);Ce(b,(h[0]-c[0])/l,(c[1]-h[3])/l);f!=this.c&&(c=nj(f,this),c.style.maxWidth="none",c.style.position="absolute",Bg(this.target),this.target.appendChild(c),this.c=f);Ae(b,this.d)|| +(Gm(this.target,b),xe(this.d,b));ak(a.attributions,f.e);bk(a,g)}};function Jm(a,b){var c=zg("DIV");c.style.position="absolute";Hm.call(this,a,b,c);this.d=!0;this.i=1;this.f=0;this.c={}}E(Jm,Hm); +Jm.prototype.Pa=function(a,b){if(b.visible){var c=a.A,d=c.projection,e=this.b,f=e.ja(),g=f.tileGrid;null===g&&(g=Vj(d));var h=pi(g.a,c.resolution,0),l=g.D(h),n=c.center,q;l==c.resolution?(n=ek(n,l,a.size),q=xd(n,l,c.rotation,a.size)):q=a.extent;var l=tj(g,q,l),r={};r[h]={};var w=y(f.Zc,f,r,dk(function(a){return null!==a&&2==a.a},f,d)),t=od(),A=new ab(0,0,0,0),B,v,z,H;for(z=l.a;z<=l.d;++z)for(H=l.c;H<=l.b;++H)B=f.Db(h,z,H,d),v=B.a,2==v?r[h][B.H.toString()]=B:3!=v&&4!=v&&(v=g.uc(B.H,w,null,A,t),v|| +(B=g.yc(B.H,A,t),null===B||w(h+1,B)));var D;if(this.f!=f.c){for(D in this.c)t=this.c[+D],Eg(t.target);this.c={};this.f=f.c}z=Ka(lc(r),Number);Ua(z);var w={},R;H=0;for(B=z.length;HD&&Dg(this.target,t.target)}else a.L[0]||a.L[1]||Om(t,q,A);else Eg(t.target),delete this.c[D];b.opacity!=this.i&&(Oh(this.target,b.opacity),this.i=b.opacity);b.visible&&!this.d&&(Ph(this.target,!0),this.d=!0);ck(a.gc,f,h,l);fk(a,f,g,d,q,h,e.c());Zj(a,f);bk(a,f)}else this.d&&(Ph(this.target,!1),this.d=!1)}; +function Km(a,b){this.target=zg("DIV");this.target.style.position="absolute";this.d=a;this.c=b;this.f=yd(rj(a,b));this.g=a.D(b.z);this.b={};this.a=null;this.e=we()}function Lm(a,b){var c=b.H,d=c.toString();if(!(d in a.b)){var e=a.d.Ba(c.z),f=b.ca(a),g=f.style;g.maxWidth="none";g.position="absolute";g.left=(c.x-a.c.x)*e[0]+"px";g.top=(a.c.y-c.y)*e[1]+"px";null===a.a&&(a.a=document.createDocumentFragment());a.a.appendChild(f);a.b[d]=b}} +function Mm(a){null!==a.a&&(a.target.appendChild(a.a),a.a=null)}Km.prototype.D=k("g");function Om(a,b,c){var d=sj(a.d,b,a.c.z,c);b=[];for(var e in a.b)c=a.b[e],d.contains(c.H)||b.push(c);var f,d=0;for(f=b.length;dc)break;if(bb&&(-1==e||h=l.minResolution)&&h.Pa(a,l);e=a.size;if(this.C[0]!=e[0]||this.C[1]!=e[1])this.c.width=e[0],this.c.height=e[1],this.C=e;b.bindFramebuffer(36160,null);b.clearColor(0,0,0,0);b.clear(16384); +b.enable(3042);b.viewport(0,0,e[0],e[1]);co(this,this.W);var n=null,q;e=0;for(f=c.length;e=l.maxResolution||dc?(e="\u2032",b*=60):e="\u00b0":"imperial"==f?0.9144>c?(e="in", +b/=0.0254):1609.344>c?(e="ft",b/=0.3048):(e="mi",b/=1609.344):"nautical"==f?(b/=1852,e="nm"):"metric"==f?1>c?(e="mm",b*=1E3):1E3>c?e="m":(e="km",b/=1E3):"us"==f&&(0.9144>c?(e="in",b*=39.37):1609.344>c?(e="ft",b/=0.30480061):(e="mi",b/=1609.3472));for(var f=3*Math.floor(Math.log(a.i*b)/Math.log(10)),g,h;;){g=Oo[f%3]*Math.pow(10,Math.floor(f/3));h=Math.round(g/b);if(h>=a.i)break;++f}g=g+e;a.r!=g&&(a.f.innerHTML=g,a.r=g);a.C!=h&&(a.f.style.width=h+"px",a.C=h);a.c||(Ph(a.g,!0),a.c=!0)}};function Qo(a){db.call(this);this.b=a;this.a={}}E(Qo,db);var Ro=[];Qo.prototype.Xa=function(a,b,c,d,e){ia(b)||(Ro[0]=b,b=Ro);for(var f=0;fthis.Ud)if(K(this,new Xo("start",this,a.clientX,a.clientY,a)))this.sb=!0;else{this.$b||this.rc(a);return}}c=$o(this,b,c);b=c.x;c=c.y;this.sb&&K(this,new Xo("beforedrag",this,a.clientX,a.clientY,a,b,c))&&(ap(this,a,b,c),a.U())}}; +function $o(a,b,c){var d=Ig(qg(a.c));b+=d.x-a.e.x;c+=d.y-a.e.y;a.e=d;a.na+=b;a.ma+=c;b=Yo(a,a.na);a=Zo(a,a.ma);return new og(b,a)}m.Hf=function(a){var b=$o(this,0,0);a.clientX=this.clientX;a.clientY=this.clientY;ap(this,a,b.x,b.y)};function ap(a,b,c,d){a.vd&&Vo(a)?a.target.style.right=c+"px":a.target.style.left=c+"px";a.target.style.top=d+"px";K(a,new Xo("drag",a,b.clientX,b.clientY,b,c,d))} +function Yo(a,b){var c=a.b,d=isNaN(c.left)?null:c.left,c=isNaN(c.width)?0:c.width;return Math.min(null!=d?d+c:Infinity,Math.max(null!=d?d:-Infinity,b))}function Zo(a,b){var c=a.b,d=isNaN(c.top)?null:c.top,c=isNaN(c.height)?0:c.height;return Math.min(null!=d?d+c:Infinity,Math.max(null!=d?d:-Infinity,b))}function Xo(a,b,c,d,e,f,g,h){ib.call(this,a);this.clientX=c;this.clientY=d;this.d=e;this.left=s(f)?f:b.na;this.top=s(g)?g:b.ma;this.b=b;this.a=!!h}E(Xo,ib);function bp(a){a=s(a)?a:{};this.b=void 0;this.c=cp;this.i=!1;this.f=null;a=s(a.className)?a.className:"ol-zoomslider";a=wg("DIV",a+" ol-unselectable",wg("DIV",a+"-thumb ol-unselectable"));null!==this.f&&(Ga(this.f,Fc),this.f=null);var b=new To(a.childNodes[0]);this.f=[J(b,["drag","end"],this.r,void 0,this)];this.g=b;J(a,["touchend","click"],this.k,!1,this);zi.call(this,{element:a})}E(bp,zi);var cp=0;bp.prototype.setMap=function(a){bp.F.setMap.call(this,a);null===a||Yj(a)}; +bp.prototype.d=function(a){if(null!==a.b){if(!this.i){var b=this.element,c=Fg(b);var d=sg(b),e=G&&b.currentStyle;e&&Gg(qg(d))&&"auto"!=e.width&&"auto"!=e.height&&!e.boxSizing?(d=Uh(b,e.width,"width","pixelWidth"),b=Uh(b,e.height,"height","pixelHeight"),b=new pg(d,b)):(e=new pg(b.offsetWidth,b.offsetHeight),d=Sh(b,"padding"),b=Th(b),b=new pg(e.width-b.left-d.left-d.right-b.right,e.height-b.top-d.top-d.bottom-b.bottom));var e=Ih(c),d=Mh(c),e=new Bh(e.x,e.y,d.width,d.height),d=Sh(c,"margin"),f=Th(c), +c=b.width-d.left-d.right-f.left-f.right-e.width,e=b.height-d.top-d.bottom-f.top-f.bottom-e.height;b.width>b.height?(this.c=1,c=new Bh(0,0,c,0)):(this.c=cp,c=new Bh(0,0,0,e));this.g.b=c||new Bh(NaN,NaN,NaN,NaN);this.i=!0}a=a.b.A.resolution;a!==this.b&&(this.b=a,a=-1*(xi(this.a.a().O())(a)-1),c=this.g,b=Fg(this.element),1==this.c?Eh(b,c.b.left+c.b.width*a):Eh(b,c.b.left,c.b.top+c.b.height*a))}};bp.prototype.k=function(){}; +bp.prototype.r=function(a){var b=this.a,c=b.a().O();if("drag"===a.type){var b=this.g.b,d=0,d=1===this.c?(a.left-b.left)/b.width:(a.top-b.top)/b.height;a=-1*(Zc(d,0,1)-1);a=wi(this.a.a().O())(a);a!==this.b&&(this.b=a,c.kb(a))}else b.Ga(vf({resolution:this.b,duration:200,easing:af})),a=c.Ha(this.b),c.kb(a)};function dp(a){a=s(a)?a:{};this.b=s(a.extent)?a.extent:null;var b=wg("DIV",{"class":(s(a.className)?a.className:"ol-zoom-extent")+" ol-unselectable"}),c=wg("A",{href:"#zoomExtent"});b.appendChild(c);J(b,["touchend","click"],this.c,!1,this);zi.call(this,{element:b,target:a.target})}E(dp,zi);dp.prototype.c=function(a){a.U();a=this.a;var b=a.a().O(),c=null===this.b?b.ga().ba():this.b;b.$c(c,a.c())};function ep(a){M.call(this);this.a=a;J(this.a,"change",this.k,!1,this);J(this,Uc("value"),this.r,!1,this);J(this,Uc("valueAsNumber"),this.p,!1,this);J(this,Uc("checked"),this.i,!1,this)}E(ep,M);ep.prototype.b=function(){return this.get("checked")};ep.prototype.getChecked=ep.prototype.b;ep.prototype.d=function(){return this.get("value")};ep.prototype.getValue=ep.prototype.d;ep.prototype.c=function(){return this.get("valueAsNumber")};ep.prototype.getValueAsNumber=ep.prototype.c; +ep.prototype.f=function(a){this.l("value",a)};ep.prototype.setValue=ep.prototype.f;ep.prototype.g=function(a){this.l("valueAsNumber",a)};ep.prototype.setValueAsNumber=ep.prototype.g;ep.prototype.e=function(a){this.l("checked",a)};ep.prototype.setChecked=ep.prototype.e;ep.prototype.k=function(){"checkbox"===this.a.type||"radio"===this.a.type?this.e(this.a.checked):(this.f(this.a.value),this.g(this.a.valueAsNumber))};ep.prototype.i=function(){this.a.checked=this.b()?"checked":void 0}; +ep.prototype.r=function(){this.a.value=this.d()};ep.prototype.p=function(){this.a.value=this.c()};function fp(a,b){this.x=a;this.y=b}E(fp,og);fp.prototype.ea=function(){return new fp(this.x,this.y)};fp.prototype.scale=og.prototype.scale;fp.prototype.add=function(a){this.x+=a.x;this.y+=a.y;return this};function gp(a){a=s(a)?a:{};Pi.call(this);this.V=s(a.condition)?a.condition:Ni;this.a=this.b=void 0;this.f=0}E(gp,Pi);gp.prototype.Bc=function(a){var b=a.a;a=a.map;var c=a.c(),c=new fp(b.Ld-c[0]/2,c[1]/2-b.Md),b=Math.atan2(c.y,c.x),c=Math.sqrt(c.x*c.x+c.y*c.y),d=a.a().O(),e=yi(d);Ri(a);s(this.b)&&Fi(a,d,e.rotation-(b-this.b));this.b=b;s(this.a)&&Ii(a,d,this.a*(e.resolution/c));s(this.a)&&(this.f=this.a/c);this.a=c}; +gp.prototype.Tb=function(a){var b=a.map,c=b.a().O(),d=yi(c),e=this.f-1;Gi(b,function(){var a=d.rotation,a=c.lc(a,0);Fi(b,c,a,void 0,void 0);a=d.resolution;a=c.Ha(a,0,e);Ii(b,c,a,void 0,400)});this.f=0;return!0};gp.prototype.Ub=function(a){return this.V(a)?(this.a=this.b=void 0,!0):!1};function hp(a){a=s(a)?a:{};this.d=s(a.condition)?a.condition:Li;this.b={};this.a={};this.c=s(a.layerFilter)?a.layerFilter:null}E(hp,Ei); +hp.prototype.xb=function(a){if(this.d(a)){var b=a.map,c=b.Ua().Ob();null===this.c||(c=Ha(c,this.c));var d=!Ni(a),e=this;b.Jd({layers:c,pixel:a.e(),success:function(a){var g=c,h=x(b);h in e.a||(e.a[h]={map:b,layers:{}});for(var l=0,n=a.length;l=b.Vc&&b.cancel())}this.k?this.k.call(this.g,this):this.rd=!0;this.nb||this.Bb(new wp(this))}};m.Cd=function(a,b){this.Uc=!1;xp(this,a,b)};function xp(a,b,c){a.nb=!0;a.b=c;a.Sb=!b;yp(a)}function zp(a){if(a.nb){if(!a.rd)throw new Ap(a);a.rd=!1}} +m.aa=function(a){zp(this);xp(this,!0,a)};m.Bb=function(a){zp(this);xp(this,!1,a)};function Bp(a,b,c){return Cp(a,b,null,c)}function Cp(a,b,c,d){a.c.push([b,c,d]);a.nb&&yp(a);return a}function Dp(a){return La(a.c,function(a){return la(a[1])})} +function yp(a){a.f&&(a.nb&&Dp(a))&&(p.clearTimeout(a.f),delete a.f);a.a&&(a.a.Vc--,delete a.a);for(var b=a.b,c=!1,d=!1;a.c.length&&!a.Uc;){var e=a.c.shift(),f=e[0],g=e[1],e=e[2];if(f=a.Sb?g:f)try{var h=f.call(e||a.g,b);s(h)&&(a.Sb=a.Sb&&(h==b||h instanceof Error),a.b=b=h);b instanceof vp&&(d=!0,a.Uc=!0)}catch(l){b=l,a.Sb=!0,Dp(a)||(c=!0)}}a.b=b;d&&(Cp(b,y(a.Cd,a,!0),y(a.Cd,a,!1)),b.Be=!0);c&&(a.f=p.setTimeout(Se(b),0))}function Ap(a){ta.call(this);this.a=a}E(Ap,ta);Ap.prototype.message="Deferred has already fired"; +Ap.prototype.name="AlreadyCalledError";function wp(a){ta.call(this);this.a=a}E(wp,ta);wp.prototype.message="Deferred was canceled";wp.prototype.name="CanceledError";function Ep(a,b,c,d,e,f){vp.call(this,e,f);this.e=a;this.d=[];this.V=!!b;this.r=!!c;this.p=!!d;for(b=this.q=0;bb&&(b+=12);var d;a:{switch(b){case 1:d=0!=c%4||0==c%100&&0!=c%400?28:29;break a;case 5:case 8:case 10:case 3:d=30;break a}d=31}d=Math.min(d,this.getDate());this.a.setDate(1);this.a.setFullYear(c);this.a.setMonth(b);this.a.setDate(d)}a.a&&(a=new Date((new Date(this.getFullYear(),this.getMonth(),this.getDate(),12)).getTime()+864E5*a.a),this.a.setDate(1),this.a.setFullYear(a.getFullYear()), +this.a.setMonth(a.getMonth()),this.a.setDate(a.getDate()),Sp(this,a.getDate()))};m.zc=function(a,b){return[this.getFullYear(),Ca(this.getMonth()+1),Ca(this.getDate())].join(a?"-":"")+(b?Tp(this):"")};m.toString=function(){return this.zc()};function Sp(a,b){a.getDate()!=b&&a.a.setUTCHours(a.a.getUTCHours()+(a.getDate()=g?1-g:8-g)+(Number(q)+7*(Number(f)-1))-1))):(h&&(d.a.setDate(1),d.a.setMonth(h-1)),l&&d.a.setDate(l));f=!0}else f=!1;f&&!(f=2>e.length)&&(e=e[1],f=e.match(Jp),q=0,f&&("Z"!=f[0]&&(q=60*f[2]+Number(f[3]),q*="-"==f[1]?1:-1), +q-=d.a.getTimezoneOffset(),e=e.substr(0,e.length-f[0].length)),(f=e.match(Ip))?(d.a.setHours(Number(f[1])),d.a.setMinutes(Number(f[2])||0),d.a.setSeconds(Number(f[3])||0),d.a.setMilliseconds(f[4]?1E3*f[4]:0),0!=q&&d.a.setTime(d.getTime()+6E4*q),f=!0):f=!1);d=f?d:null;null===d||(d=new Date(d.getTime()));c.zb.push(d)},_trackPointAttribute:function(a,c){var d=a.nodeName.split(":").pop();c.attributes[d].push(Y(a))},Style:function(a,c){if(!0===this.extractStyles){c.styles||(c.styles=[]);var d={symbolizers:[], +ids:[]},e=a.getAttribute("id");null===e||(d.id=e);X(this,a,d);c.styles.push(d)}},LineStyle:function(a,c){var d={},e={};X(this,a,d);d.color&&(e.color=d.color.color,e.opacity=d.color.opacity);d.width&&(e.width=parseFloat(d.width));c.ids.push(a.getAttribute("id"));c.symbolizers.push(new Rl(e))},PolyStyle:function(a,c){var d={},e={};X(this,a,d);"0"!==d.fill&&"false"!==d.fill&&(d.color?(e.color=d.color.color,e.opacity=d.color.opacity):(e.color="#ffffff",e.opacity=1),c.symbolizers.push(new Jl(e)));"0"!== +d.outline&&"false"!==d.outline&&(d.color?(e.color=d.color.color,e.opacity=d.color.opacity):(e.color="#ffffff",e.opacity=1),c.symbolizers.push(new Rl(e)));c.ids.push(a.getAttribute("id"))},fill:function(a,c){c.fill=Y(a)},outline:function(a,c){c.outline=Y(a)},scale:function(a,c){c.scale=parseFloat(Y(a))},Icon:function(a,c){c.ub={};X(this,a,c.ub)},href:function(a,c){c.href=Y(a)},w:function(a,c){c.ag=Y(a)},h:function(a,c){c.Ue=Y(a)},x:function(a,c){c.x=Y(a)},y:function(a,c){c.y=Y(a)},hotSpot:function(a, +c){c.Vb={x:parseFloat(a.getAttribute("x")),y:parseFloat(a.getAttribute("y")),cg:a.getAttribute("xunits"),dg:a.getAttribute("yunits")}},IconStyle:function(a,c){var d={},e={};X(this,a,d);var f=d.scale||1,g=32*f,h=32*f,l,n;if(s(d.ub)&&(l=d.ub.href,s(l))){n=d.ub.ag;var q=d.ub.Ue;0!=l.lastIndexOf("http://maps.google.com/mapfiles/kml",0)||(s(n)||s(q))||(q=n=64,f/=2);n=n||q;q=q||n;n&&(g=parseInt(n,10)*f);q&&(h=parseInt(q,10)*f);if(n=l.match(this.S.zf)){var q=n[1],r=n[2];l=d.ub.x;n=d.ub.y;l="http://maps.google.com/mapfiles/kml/pal"+ +q+"/icon"+(8*(n?7-n/32:7)+(l?l/32:0))+r}e.opacity=1;e.url=l}s(d.Vb)&&(l=d.Vb.x,n=d.Vb.y,q=d.Vb.cg,d=d.Vb.dg,"pixels"===q?e.xOffset=-l*f:"insetPixels"===q?e.xOffset=-g+l*f:"fraction"===q&&(e.xOffset=-g*l),"pixels"==d?e.yOffset=-h+n*f+1:"insetPixels"==d?e.yOffset=-(n*f)+1:"fraction"==d&&(e.yOffset=-h*(1-n)+1));e.width=g;e.height=h;c.ids.push(a.getAttribute("id"));c.symbolizers.push(new Vp(e))},color:function(a,c){var d=Y(a);d&&(d=d.match(this.S.yf))&&(c.color={color:"#"+d[4]+d[3]+d[2],opacity:parseInt(d[1], +16)/255})},width:function(a,c){c.width=Y(a)}},"http://www.google.com/kml/ext/2.2":{Track:function(a,c){c.ka={zb:[],Hb:[],ab:[]};if(this.trackAttributes){var d;c.ka.attributes={};for(var e=0,f=this.trackAttributes.length;ethis.a.d};m.Nb=function(a){this.a.Nb(a)}; +m.Db=function(a,b,c,d){var e=this.eb(a,b,c);if(km(this.a,e))return this.a.get(e);a=new Xa(a,b,c);d=this.tileUrlFunction(a,d);d=new pe(a,s(d)?0:4,s(d)?d:"",this.k,this.p);lm(this.a,e,d);return d};m.ec=function(a){this.a.clear();this.tileUrlFunction=a;Xe(this)};m.ne=function(a,b,c){a=this.eb(a,b,c);km(this.a,a)&&this.a.get(a)};function fr(a){var b=Array(a.maxZoom+1),c,d=2*ij/256;for(c=0;c<=a.maxZoom;++c)b[c]=d/Math.pow(2,c);pj.call(this,{minZoom:a.minZoom,origin:[-ij,ij],resolutions:b,tileSize:[256,256]})}E(fr,pj); +function gr(a,b){var c=s(b)?b:{},d=a.minZoom,e=a.maxZoom,f=s(c.bg)?c.bg:!0,g=new Xa(0,0,0),h=null;if(s(c.extent)){var h=Array(e+1),l;for(l=0;l<=e;++l)h[l]=lt||l<=t)return null;a=a.y;return a<-l||-1=this.minZoom;--a)if(d.a=d.d>>=1,d.c=d.b>>=1,b.call(c,a,d))return!0;return!1};function hr(a){dr.call(this,{crossOrigin:"anonymous",opaque:!0,projection:ke("EPSG:3857")});this.e=s(a.culture)?a.culture:"en-us";this.b=!1;var b=new Lf("//dev.virtualearth.net/REST/v1/Imagery/Metadata/"+a.style),b=new Sq(b,"jsonp"),c={include:"ImageryProviders",key:a.key};a=y(this.i,this);var d=c||null,c="_"+(Tq++).toString(36)+sa().toString(36);p._callbacks_||(p._callbacks_={});var e=b.b.ea();if(d)for(var f in d)d.hasOwnProperty&&!d.hasOwnProperty(f)||Yf(e,f,d[f]);a&&(p._callbacks_[c]=Wq(c,a),Yf(e, +b.a,"_callbacks_."+c));f=Lq(e.toString(),{timeout:b.yb,Ad:!0});Cp(f,null,Vq(c),void 0)}E(hr,dr); +hr.prototype.i=function(a){var b=a.brandLogoUri,c=a.resourceSets[0].resources[0],d=new fr({minZoom:c.zoomMin,maxZoom:c.zoomMax,tileSize:[c.imageWidth,c.imageHeight]});this.tileGrid=d;var e=this.e;this.tileUrlFunction=br(gr(d),Zq(Ka(c.imageUrlSubdomains,function(a){var b=c.imageUrl.replace("{subdomain}",a).replace("{culture}",e);return function(a){return null===a?void 0:b.replace("{quadkey}",$a(a))}})));var f=Od(ke("EPSG:4326"),this.ga());this.d=Ka(c.imageryProviders,function(a){var b=a.attribution, +c={};Ga(a.coverageAreas,function(a){var b=a.zoomMin,e=a.zoomMax;a=a.bbox;a=Bd([a[1],a[3],a[0],a[2]],f);var g,h;for(g=b;g<=e;++g)h=g.toString(),b=sj(d,a,g),h in c?c[h].push(b):c[h]=[b]});return new cb({html:b,tileRanges:c})});this.f=b;this.b=!0;Xe(this)};hr.prototype.Ma=k("b");function ir(a){var b=jr(a.url),c=a.imageExtent,d=a.imageSize,e=(c[3]-c[1])/d[1],f=ke(a.projection);pk.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin,extent:a.extent,projection:a.projection,Eb:b,resolutions:[e]});this.a=qk(this,c,e,d,f)}E(ir,pk);ir.prototype.ca=function(a){return zd(a,this.a.ba())?this.a:null};function jr(a){return function(){return a}};function nk(a,b,c,d,e){d={SERVICE:"WMS",VERSION:"1.3.0",REQUEST:"GetMap",FORMAT:"image/png",TRANSPARENT:!0,WIDTH:Math.round(d[0]),HEIGHT:Math.round(d[1])};I(d,b);d.STYLES=b.STYLES||new String("");b="1.3"this.a.d};Ar.prototype.Nb=function(a){this.a.Nb(a)};Ar.prototype.Db=function(a,b,c){var d=this.eb(a,b,c);if(km(this.a,d))return this.a.get(d);a=new zr(new Xa(a,b,c),this.tileGrid);lm(this.a,d,a);return a};var Br=[];C("grid",function(a){Br.push(a)});function Cr(a){dr.call(this,{crossOrigin:a.crossOrigin,projection:ke("EPSG:3857")});this.b=!1;this.Wc=Lq(a.url,{Ad:!0});Bp(this.Wc,this.e,this)}E(Cr,dr); +Cr.prototype.e=function(){var a=Br.pop(),b=ke("EPSG:4326"),c;if(s(a.bounds)){var d=Od(b,this.ga());this.g=c=Bd(a.bounds,d)}var e=a.minzoom||0,d=a.maxzoom||22,f=new fr({maxZoom:d,minZoom:e});this.tileGrid=f;this.tileUrlFunction=br(gr(f,{extent:c}),Yq(a.tiles));if(s(a.attribution)){b=s(c)?c:b.ba();c={};for(var g;e<=d;++e)g=e.toString(),c[g]=[sj(f,b,e)];this.d=[new cb({html:a.attribution,tileRanges:c})]}this.b=!0;Xe(this)};Cr.prototype.Ma=k("b");function Dr(a){var b=ar,c=a.urls;!s(c)&&s(a.url)&&(c=cr(a.url));this.b=a.params;this.e="";Er(this);s(c)&&(b=Ka(c,function(a){return $q(a,this.b)},this),b=Zq(b));var d=a.extent;dr.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin,extent:d,tileGrid:a.tileGrid,opaque:!(s(a.params.TRANSPARENT)?a.params.TRANSPARENT:1),projection:a.projection,tileUrlFunction:br(function(a,b){var c=this.tileGrid;null===c&&(c=Vj(b));if(c.Pb().length<=a.z)return null;var h=a.x,l=rj(c,a),n=b.ba();d=s(d)?d:n; +null!==d&&(b.Kd&&d[0]===n[0]&&d[2]===n[2])&&(l=Math.ceil((d[2]-d[0])/(l[2]-l[0])),h=$c(h,l),l=rj(c,new Xa(a.z,h,a.y)));return null===d||zd(l,d)&&!Ad(l,d)?new Xa(a.z,h,a.y):null},b)});this.i=s(a.ad)?a.ad:{}}E(Dr,dr);Dr.prototype.eb=function(a,b,c){return this.e+Dr.F.eb.call(this,a,b,c)};Dr.prototype.r=k("b"); +Dr.prototype.Ta=function(a,b,c,d){var e=di(b,a),f=b.a().O(),g=f.ga(),h=null===this.tileGrid?Vj(g):this.tileGrid,f=f.D(),e=Sj(h,e[0],e[1],f,!1,void 0),h=rj(h,e);b=Si(b,yd(h));g=this.tileUrlFunction(e,g);kr(g,[a[0]-b[0],a[1]-b[1]],this.i,c,d)};function Er(a){var b=0,c=[],d;for(d in a.b)c[b++]=d+"-"+a.b[d];a.e=c.join("/")}Dr.prototype.t=function(a){I(this.b,a);Er(this);Xe(this)};function Sr(a){this.c=a.matrixIds;pj.call(this,{origin:a.origin,origins:a.origins,resolutions:a.resolutions,tileSize:a.tileSize,tileSizes:a.tileSizes})}E(Sr,pj);Sr.prototype.g=k("c"); +function Tr(a){var b=[],c=[],d=[],e=[],f=ke(a.supportedCRS).a();Ua(a.matrixIds,function(a,b){return b.scaleDenominator-a.scaleDenominator});Ga(a.matrixIds,function(a){c.push(a.identifier);d.push(a.topLeftCorner);b.push(2.8E-4*a.scaleDenominator/f);e.push([a.tileWidth,a.tileHeight])});return new Sr({origins:d,resolutions:b,matrixIds:c,tileSizes:e})};var Ur="KVP"; +function Vr(a){function b(a){a=e==Ur?If(Kf([a],g)):a.replace(/\{(\w+?)\}/g,function(a,b){return b in g?g[b]:a});return function(b){if(null!==b){var c={TileMatrix:f.c[b.z],TileCol:b.x,TileRow:b.y};I(c,this.b);b=a;return b=e==Ur?If(Kf([b],c)):b.replace(/\{(\w+?)\}/g,function(a,b){return c[b]})}}}var c=s(a.version)?a.version:"1.0.0",d=s(a.format)?a.format:"image/jpeg";this.b=a.dimensions||{};this.e="";Wr(this);var e=s(a.requestEncoding)?a.requestEncoding:Ur,f=a.tileGrid,g={Layer:a.layer,style:a.style, +Style:a.style,TileMatrixSet:a.matrixSet};e==Ur&&I(g,{Service:"WMTS",Request:"GetTile",Version:c,Format:d});c=ar;d=a.urls;!s(d)&&s(a.url)&&(d=cr(a.url));s(d)&&(c=Zq(Ka(d,b)));var h=od(),l=new Xa(0,0,0),c=br(function(b,c){var d=this.tileGrid;if(d.Pb().length<=b.z)return null;var e=b.x,f=-b.y-1,g=rj(d,b),B=c.ba(),v=s(a.extent)?a.extent:B;null!==v&&(c.Kd&&v[0]===B[0]&&v[2]===B[2])&&(g=Math.ceil((v[2]-v[0])/(g[2]-g[0])),e=$c(e,g),l.z=b.z,l.x=e,l.y=b.y,g=rj(d,l,h));return!zd(g,v)||Ad(g,v)?null:new Xa(b.z, +e,f)},c);dr.call(this,{attributions:a.attributions,crossOrigin:a.crossOrigin,extent:a.extent,projection:a.projection,tileGrid:f,tileUrlFunction:c})}E(Vr,dr);Vr.prototype.i=k("b");Vr.prototype.eb=function(a,b,c){return this.e+Vr.F.eb.call(this,a,b,c)};function Wr(a){var b=0,c=[],d;for(d in a.b)c[b++]=d+"-"+a.b[d];a.e=c.join("/")}Vr.prototype.r=function(a){I(this.b,a);Wr(this);Xe(this)};function Xr(a){this.c=s(a.color)?a.color instanceof tk?a.color:new V(a.color):new V(Yr);this.a=s(a.fontFamily)?a.fontFamily instanceof tk?a.fontFamily:new V(a.fontFamily):new V(Zr);this.b=s(a.fontSize)?a.fontSize instanceof tk?a.fontSize:new V(a.fontSize):new V($r);this.e=a.text instanceof tk?a.text:new V(a.text);this.d=s(a.opacity)?a.opacity instanceof tk?a.opacity:new V(a.opacity):new V(as)}E(Xr,Il); +Xr.prototype.cb=function(a){var b;a instanceof O&&(b=a,b.G());a=$k(this.c,b);var c=$k(this.a,b),d=Number($k(this.b,b)),e=$k(this.e,b);b=Number($k(this.d,b));return new am({color:a,fontFamily:c,fontSize:d,text:e,opacity:b})};var Yr="#000",Zr="sans-serif",$r=10,as=1;function bs(a){null!=a&&(a.html=a.html,a.tileRanges=a.tileRanges);cb.call(this,a)}E(bs,cb);C("ol.Attribution",bs);C("ol.Collection",N);N.prototype.clear=N.prototype.clear;N.prototype.extend=N.prototype.Cf;N.prototype.forEach=N.prototype.forEach;N.prototype.getArray=N.prototype.Df;N.prototype.getAt=N.prototype.Fe;N.prototype.getLength=N.prototype.xc;N.prototype.insertAt=N.prototype.Ec;N.prototype.pop=N.prototype.pop;N.prototype.push=N.prototype.push;N.prototype.remove=N.prototype.remove; +N.prototype.removeAt=N.prototype.qd;N.prototype.setAt=N.prototype.Qf;Xc.prototype.getElement=Xc.prototype.b;function cs(a){null!=a&&(a.tracking=a.tracking);fd.call(this,a)}E(cs,fd);C("ol.DeviceOrientation",cs);C("ol.Feature",O);O.prototype.getAttributes=O.prototype.ob;O.prototype.getGeometry=O.prototype.G;O.prototype.getId=O.prototype.Je;O.prototype.set=O.prototype.l;O.prototype.setGeometry=O.prototype.Ea; +function ds(a){null!=a&&(a.projection=a.projection,a.tracking=a.tracking,a.trackingOptions=a.trackingOptions);Q.call(this,a)}E(ds,Q);C("ol.Geolocation",ds);pe.prototype.getImage=pe.prototype.ca;C("ol.Kinetic",wf);function es(a){null!=a&&(a.controls=a.controls,a.interactions=a.interactions,a.layers=a.layers,a.overlays=a.overlays,a.renderer=a.renderer,a.renderers=a.renderers,a.target=a.target,a.view=a.view);W.call(this,a)}E(es,W);C("ol.Map",es);W.prototype.addControl=W.prototype.ye; +W.prototype.addLayer=W.prototype.yd;W.prototype.addOverlay=W.prototype.ze;W.prototype.beforeRender=W.prototype.Ga;W.prototype.getControls=W.prototype.He;W.prototype.getFeatureInfo=W.prototype.Ie;W.prototype.getFeatures=W.prototype.Jd;W.prototype.getInteractions=W.prototype.Ke;W.prototype.getLayers=W.prototype.te;W.prototype.getOverlays=W.prototype.Me;W.prototype.getRenderer=W.prototype.Ne;W.prototype.removeControl=W.prototype.Kf;W.prototype.removeLayer=W.prototype.he;W.prototype.removeOverlay=W.prototype.Lf; +W.prototype.updateSize=W.prototype.sa;ci.prototype.getCoordinate=ci.prototype.d;ci.prototype.getPixel=ci.prototype.e;ci.prototype.preventDefault=ci.prototype.U;ci.prototype.stopPropagation=ci.prototype.rb;C("ol.Object",M);M.prototype.bindTo=M.prototype.Ae;M.prototype.get=M.prototype.get;M.prototype.notify=M.prototype.Zd;M.prototype.on=M.prototype.Gf;M.prototype.once=M.prototype.If;M.prototype.set=M.prototype.l;M.prototype.setValues=M.prototype.Zb;M.prototype.un=M.prototype.Wf; +M.prototype.unByKey=M.prototype.Xf;M.prototype.unbind=M.prototype.td;M.prototype.unbindAll=M.prototype.Yf;function fs(a){null!=a&&(a.element=a.element,a.position=a.position,a.positioning=a.positioning);Bo.call(this,a)}E(fs,Bo);C("ol.Overlay",fs);C("ol.OverlayPositioning",Ao);Ao.BOTTOM_LEFT="bottom-left";Ao.BOTTOM_RIGHT="bottom-right";Ao.TOP_LEFT="top-left";Ao.TOP_RIGHT="top-right";C("ol.RendererHint",xo);xo.CANVAS="canvas";xo.DOM="dom";xo.WEBGL="webgl";C("ol.RendererHints",wo); +wo.createFromQueryData=wo.Ce;oe.prototype.getTileCoord=oe.prototype.g;Xa.prototype.getZXY=Xa.prototype.a;function gs(a){null!=a&&(a.center=a.center,a.maxResolution=a.maxResolution,a.maxZoom=a.maxZoom,a.projection=a.projection,a.resolution=a.resolution,a.resolutions=a.resolutions,a.rotation=a.rotation,a.zoom=a.zoom,a.zoomFactor=a.zoomFactor);T.call(this,a)}E(gs,T);C("ol.View2D",gs);T.prototype.calculateExtent=T.prototype.i;T.prototype.constrainResolution=T.prototype.Ha; +T.prototype.constrainRotation=T.prototype.lc;T.prototype.fitExtent=T.prototype.$c;T.prototype.getView2D=T.prototype.O;T.prototype.getZoom=T.prototype.Qe;T.prototype.setZoom=T.prototype.p;C("ol.animation.bounce",function(a){null!=a&&(a.duration=a.duration,a.easing=a.easing,a.resolution=a.resolution,a.start=a.start);return ef(a)});C("ol.animation.pan",function(a){null!=a&&(a.duration=a.duration,a.easing=a.easing,a.source=a.source,a.start=a.start);return tf(a)}); +C("ol.animation.rotate",function(a){null!=a&&(a.duration=a.duration,a.easing=a.easing,a.rotation=a.rotation,a.start=a.start);return uf(a)});C("ol.animation.zoom",function(a){null!=a&&(a.duration=a.duration,a.easing=a.easing,a.resolution=a.resolution,a.start=a.start);return vf(a)});function hs(a){null!=a&&(a.className=a.className,a.target=a.target);Ai.call(this,a)}E(hs,Ai);C("ol.control.Attribution",hs);Ai.prototype.setMap=Ai.prototype.setMap; +function is(a){null!=a&&(a.element=a.element,a.target=a.target);zi.call(this,a)}E(is,zi);C("ol.control.Control",is);zi.prototype.getMap=zi.prototype.W;zi.prototype.setMap=zi.prototype.setMap;function js(a){null!=a&&(a.className=a.className,a.keys=a.keys,a.target=a.target);Jo.call(this,a)}E(js,Jo);C("ol.control.FullScreen",js);function ks(a){null!=a&&(a.className=a.className,a.target=a.target);Bi.call(this,a)}E(ks,Bi);C("ol.control.Logo",ks);Bi.prototype.setMap=Bi.prototype.setMap; +function ls(a){null!=a&&(a.className=a.className,a.coordinateFormat=a.coordinateFormat,a.projection=a.projection,a.target=a.target,a.undefinedHTML=a.undefinedHTML);Ko.call(this,a)}E(ls,Ko);C("ol.control.MousePosition",ls);Ko.prototype.setMap=Ko.prototype.setMap;function ms(a){null!=a&&(a.className=a.className,a.minWidth=a.minWidth,a.target=a.target,a.units=a.units);No.call(this,a)}E(ms,No);C("ol.control.ScaleLine",ms);No.prototype.setMap=No.prototype.setMap;C("ol.control.ScaleLineUnits",Mo); +Mo.DEGREES="degrees";Mo.IMPERIAL="imperial";Mo.METRIC="metric";Mo.NAUTICAL="nautical";Mo.US="us";function ns(a){null!=a&&(a.className=a.className,a.delta=a.delta,a.target=a.target);Ci.call(this,a)}E(ns,Ci);C("ol.control.Zoom",ns);Ci.prototype.setMap=Ci.prototype.setMap;function os(a){null!=a&&(a.className=a.className,a.maxResolution=a.maxResolution,a.minResolution=a.minResolution);bp.call(this,a)}E(os,bp);C("ol.control.ZoomSlider",os); +function ps(a){null!=a&&(a.className=a.className,a.extent=a.extent,a.target=a.target);dp.call(this,a)}E(ps,dp);C("ol.control.ZoomToExtent",ps); +C("ol.control.defaults",function(a){if(null!=a){a.attribution=a.attribution;var b=a.attributionOptions;null!=a.attributionOptions&&(b.className=a.attributionOptions.className,b.target=a.attributionOptions.target);a.attributionOptions=b;a.logo=a.logo;b=a.logoOptions;null!=a.logoOptions&&(b.className=a.logoOptions.className,b.target=a.logoOptions.target);a.logoOptions=b;a.zoom=a.zoom;b=a.zoomOptions;null!=a.zoomOptions&&(b.className=a.zoomOptions.className,b.delta=a.zoomOptions.delta,b.target=a.zoomOptions.target); +a.zoomOptions=b}return Di(a)});C("ol.coordinate.createStringXY",function(a){return function(b){return ld(b,a)}});C("ol.coordinate.fromProjectedArray",md);C("ol.coordinate.toStringHDMS",function(a){return s(a)?id(a[1],"NS")+" "+id(a[0],"EW"):""});C("ol.coordinate.toStringXY",ld);C("ol.dom.Input",ep);C("ol.easing.bounce",function(a){a<1/2.75?a*=7.5625*a:a<2/2.75?(a-=1.5/2.75,a=7.5625*a*a+0.75):a<2.5/2.75?(a-=2.25/2.75,a=7.5625*a*a+0.9375):(a-=2.625/2.75,a=7.5625*a*a+0.984375);return a}); +C("ol.easing.easeIn",function(a){return a*a*a});C("ol.easing.easeOut",af);C("ol.easing.elastic",function(a){return Math.pow(2,-10*a)*Math.sin((a-0.075)*2*Math.PI/0.3)+1});C("ol.easing.inAndOut",bf);C("ol.easing.linear",cf);C("ol.easing.upAndDown",df);C("ol.expr.parse",function(a){return Wk(a)});C("ol.expr.register",function(a,b){al[a]=b});C("ol.extent.boundingExtent",nd);C("ol.extent.containsCoordinate",rd);C("ol.extent.containsExtent",sd);C("ol.extent.equals",td);C("ol.extent.extend",ud); +C("ol.extent.getBottomLeft",vd);C("ol.extent.getBottomRight",function(a){return[a[2],a[1]]});C("ol.extent.getCenter",wd);C("ol.extent.getHeight",function(a){return a[3]-a[1]});C("ol.extent.getSize",function(a){return[a[2]-a[0],a[3]-a[1]]});C("ol.extent.getTopLeft",yd);C("ol.extent.getTopRight",function(a){return[a[2],a[3]]});C("ol.extent.getWidth",function(a){return a[2]-a[0]});C("ol.extent.intersects",zd);C("ol.extent.isEmpty",function(a){return a[2]f&&(f=0);var f=c.styles[f].identifier,g={};Ga(c.dimensions,function(a){var b=a.identifier,c=a["default"];s(c)||(c=a.values[0]);g[b]=c});var h=a.contents.tileMatrixSets[d],l=Tr(h),h=ke(h.supportedCRS),n=a.operationsMetadata.GetTile.dcp.http.get,q,r;switch(lc(n[0].constraints.GetEncoding.allowedValues)[0]){case "REST":case "RESTful":r= +"REST";q=c.resourceUrls.tile[e];break;case "KVP":r=Ur,q=[],Ga(n,function(a){a.constraints.GetEncoding.allowedValues.hasOwnProperty(Ur)&&q.push(a.url)})}return{urls:q,layer:b,matrixSet:d,format:e,projection:h,requestEncoding:r,tileGrid:l,style:f,dimensions:g}});Vr.prototype.getDimensions=Vr.prototype.i;Vr.prototype.updateDimensions=Vr.prototype.r; +function Os(a){null!=a&&(a.attributions=a.attributions,a.crossOrigin=a.crossOrigin,a.extent=a.extent,a.logo=a.logo,a.maxZoom=a.maxZoom,a.minZoom=a.minZoom,a.projection=a.projection,a.tileLoadFunction=a.tileLoadFunction,a.tileUrlFunction=a.tileUrlFunction,a.url=a.url,a.urls=a.urls);or.call(this,a)}E(Os,or);C("ol.source.XYZ",Os);or.prototype.setUrl=or.prototype.b;function Ps(a){null!=a&&(a.color=a.color,a.opacity=a.opacity);Jl.call(this,a)}E(Ps,Jl);C("ol.style.Fill",Ps); +function Qs(a){null!=a&&(a.height=a.height,a.opacity=a.opacity,a.rotation=a.rotation,a.url=a.url,a.width=a.width,a.xOffset=a.xOffset,a.yOffset=a.yOffset);Vp.call(this,a)}E(Qs,Vp);C("ol.style.Icon",Qs);function Rs(a){null!=a&&(a.filter=a.filter,a.symbolizers=a.symbolizers);Ml.call(this,a)}E(Rs,Ml);C("ol.style.Rule",Rs);function Ss(a){null!=a&&(a.fill=a.fill,a.size=a.size,a.stroke=a.stroke,a.type=a.type);Vl.call(this,a)}E(Ss,Vl);C("ol.style.Shape",Ss);C("ol.style.ShapeType",Ol);Ol.CIRCLE="circle"; +function Ts(a){null!=a&&(a.color=a.color,a.opacity=a.opacity,a.width=a.width);Rl.call(this,a)}E(Ts,Rl);C("ol.style.Stroke",Ts);function Us(a){null!=a&&(a.rules=a.rules,a.symbolizers=a.symbolizers);Yl.call(this,a)}E(Us,Yl);C("ol.style.Style",Us);function Vs(a){null!=a&&(a.color=a.color,a.fontFamily=a.fontFamily,a.fontSize=a.fontSize,a.opacity=a.opacity,a.text=a.text);Xr.call(this,a)}E(Vs,Xr);C("ol.style.Text",Vs); +function Ws(a){null!=a&&(a.minZoom=a.minZoom,a.origin=a.origin,a.origins=a.origins,a.resolutions=a.resolutions,a.tileSize=a.tileSize,a.tileSizes=a.tileSizes);pj.call(this,a)}E(Ws,pj);C("ol.tilegrid.TileGrid",Ws);pj.prototype.getMinZoom=pj.prototype.Le;pj.prototype.getOrigin=pj.prototype.Fb;pj.prototype.getResolutions=pj.prototype.Pb;pj.prototype.getTileSize=pj.prototype.Ba; +function Xs(a){null!=a&&(a.matrixIds=a.matrixIds,a.origin=a.origin,a.origins=a.origins,a.resolutions=a.resolutions,a.tileSize=a.tileSize,a.tileSizes=a.tileSizes);Sr.call(this,a)}E(Xs,Sr);C("ol.tilegrid.WMTS",Xs);Sr.prototype.getMatrixIds=Sr.prototype.g;function Ys(a){null!=a&&(a.maxZoom=a.maxZoom);fr.call(this,a)}E(Ys,fr);C("ol.tilegrid.XYZ",Ys);})(); diff --git a/package.json b/package.json new file mode 100644 index 00000000..6f143134 --- /dev/null +++ b/package.json @@ -0,0 +1,35 @@ +{ + "author": "LMN Solutions", + "name": "MapLoom", + "version": "0.0.1", + "homepage": "http://www.lmnsolutions.com", + "licenses": { + "type": "BSD", + "url": "http://www.tldrlegal.com/license/bsd-2-clause-license-(freebsd)" + }, + "bugs": "https://github.com/ROGUE-JCTD/MapLoom/issues", + "repository": { + "type": "git", + "url": "git@github.com:ROGUE-JCTD/MapLoom.git" + }, + "dependencies": {}, + "devDependencies": { + "grunt": "~0.4.1", + "grunt-recess": "~0.3.0", + "grunt-contrib-clean": "~0.4.1", + "grunt-contrib-copy": "~0.4.1", + "grunt-contrib-jshint": "~0.4.3", + "grunt-contrib-concat": "~0.3.0", + "grunt-contrib-watch": "~0.4.0", + "grunt-contrib-uglify": "~0.2.0", + "grunt-karma": "~0.5.0", + "grunt-ngmin": "0.0.2", + "grunt-html2js": "~0.1.3", + "grunt-contrib-coffee": "~0.7.0", + "grunt-coffeelint": "0.0.6", + "grunt-conventional-changelog": "~0.1.1", + "grunt-bump": "0.0.6", + "closure-linter-wrapper": "~0.2.8", + "grunt-gjslint": "~0.1.3" + } +} diff --git a/quicksetup.sh b/quicksetup.sh new file mode 100755 index 00000000..0c654678 --- /dev/null +++ b/quicksetup.sh @@ -0,0 +1,4 @@ +sudo npm -g install grunt-cli karma bower +npm install +bower install +grunt \ No newline at end of file diff --git a/src/README.md b/src/README.md new file mode 100644 index 00000000..80c247f9 --- /dev/null +++ b/src/README.md @@ -0,0 +1,48 @@ +# The `src` Directory + +## Overview + +The `src/` directory contains all code used in the application along with all +tests of such code. + +``` +src/ + |- app/ + | |- about/ + | |- home/ + | |- app.js + | |- app.spec.js + |- assets/ + |- common/ + | |- plusOne/ + |- less/ + | |- main.less + | |- variables.less + |- index.html +``` + +- `src/app/` - application-specific code, i.e. code not likely to be reused in + another application. [Read more »](app/README.md) +- `src/assets/` - static files like fonts and images. + [Read more »](assets/README.md) +- `src/common/` - third-party libraries or components likely to be reused in + another application. [Read more »](common/README.md) +- `src/less/` - LESS CSS files. [Read more »](less/README.md) +- `src/index.html` - this is the HTML document of the single-page application. + See below. + +See each directory for a detailed explanation. + +## `index.html` + +The `index.html` file is the HTML document of the single-page application (SPA) +that should contain all markup that applies to everything in the app, such as +the header and footer. It declares with `ngApp` that this is `ngBoilerplate`, +specifies the main `AppCtrl` controller, and contains the `ngView` directive +into which route templates are placed. + +Unlike any other HTML document (e.g. the templates), `index.html` is compiled as +a Grunt template, so variables from `Gruntfile.js` and `package.json` can be +referenced from within it. Changing `name` in `package.json` from +"ng-boilerplate" will rename the resultant CSS and JavaScript placed in `build/`, +so this HTML references them by variable for convenience. diff --git a/src/app/DiffPanelController.js b/src/app/DiffPanelController.js new file mode 100644 index 00000000..59cd9472 --- /dev/null +++ b/src/app/DiffPanelController.js @@ -0,0 +1,19 @@ +(function() { + var module = angular.module('loom_diff_controller', []); + + module.controller('LoomDiffController', + function($scope, diffService) { + function updateScopeVariables() { + if (!$scope.$$phase) { + $scope.$apply(function() { + $scope.hasDifferences = diffService.hasDifferences(); + }); + } else { + $scope.hasDifferences = diffService.hasDifferences(); + } + } + + $scope.$on('diff_performed', updateScopeVariables); + $scope.$on('diff_cleared', updateScopeVariables); + }); +})(); diff --git a/src/app/LoomModule.js b/src/app/LoomModule.js new file mode 100644 index 00000000..5fca9477 --- /dev/null +++ b/src/app/LoomModule.js @@ -0,0 +1,10 @@ +(function() { + angular.module('loom', [ + 'loom_notifications', + 'loom_notification_poster', + 'loom_update_notification', + 'loom_diff', + 'loom_diff_controller' + ]); + +}()); diff --git a/src/app/README.md b/src/app/README.md new file mode 100644 index 00000000..7c05fdae --- /dev/null +++ b/src/app/README.md @@ -0,0 +1,94 @@ +# The `src/app` Directory + +## Overview + +``` +src/ + |- app/ + | |- home/ + | |- about/ + | |- app.js + | |- app.spec.js +``` + +The `src/app` directory contains all code specific to this application. Apart +from `app.js` and its accompanying tests (discussed below), this directory is +filled with subdirectories corresponding to high-level sections of the +application, often corresponding to top-level routes. Each directory can have as +many subdirectories as it needs, and the build system will understand what to +do. For example, a top-level route might be "products", which would be a folder +within the `src/app` directory that conceptually corresponds to the top-level +route `/products`, though this is in no way enforced. Products may then have +subdirectories for "create", "view", "search", etc. The "view" submodule may +then define a route of `/products/:id`, ad infinitum. + +As `ngBoilerplate` is quite minimal, take a look at the two provided submodules +to gain a better understanding of how these are used as well as to get a +glimpse of how powerful this simple construct can be. + +## `app.js` + +This is our main app configuration file. It kickstarts the whole process by +requiring all the modules from `src/app` that we need. We must load these now to +ensure the routes are loaded. If as in our "products" example there are +subroutes, we only require the top-level module, and allow the submodules to +require their own submodules. + +As a matter of course, we also require the template modules that are generated +during the build. + +However, the modules from `src/common` should be required by the app +submodules that need them to ensure proper dependency handling. These are +app-wide dependencies that are required to assemble your app. + +```js +angular.module( 'ngBoilerplate', [ + 'templates-app', + 'templates-common', + 'ngBoilerplate.home', + 'ngBoilerplate.about' + 'ui.state', + 'ui.route' +]) +``` + +With app modules broken down in this way, all routing is performed by the +submodules we include, as that is where our app's functionality is really +defined. So all we need to do in `app.js` is specify a default route to follow, +which route of course is defined in a submodule. In this case, our `home` module +is where we want to start, which has a defined route for `/home` in +`src/app/home/home.js`. + +```js +.config( function myAppConfig ( $stateProvider, $urlRouterProvider ) { + $urlRouterProvider.otherwise( '/home' ); +}) +``` + +Use the main applications run method to execute any code after services +have been instantiated. + +```js +.run( function run () { +}) +``` + +And then we define our main application controller. This is a good place for logic +not specific to the template or route, such as menu logic or page title wiring. + +```js +.controller( 'AppCtrl', function AppCtrl ( $scope, $location ) { + $scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams){ + if ( angular.isDefined( toState.data.pageTitle ) ) { + $scope.pageTitle = toState.data.pageTitle + ' | ngBoilerplate' ; + } + }); +}) +``` + +### Testing + +One of the design philosophies of `ngBoilerplate` is that tests should exist +alongside the code they test and that the build system should be smart enough to +know the difference and react accordingly. As such, the unit test for `app.js` +is `app.spec.js`, though it is quite minimal. diff --git a/src/app/app.js b/src/app/app.js new file mode 100644 index 00000000..faf6e898 --- /dev/null +++ b/src/app/app.js @@ -0,0 +1,19 @@ +angular.module('ngBoilerplate', [ + 'templates-app', + 'templates-common', + 'loom', + 'ui.bootstrap', + 'ui.router' +]) + +.run(function run() { +}) + +.controller('AppCtrl', function AppCtrl($scope, $location) { + $scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) { + if (angular.isDefined(toState.data.pageTitle)) { + $scope.pageTitle = toState.data.pageTitle + ' | ngBoilerplate'; + } + }); +}); + diff --git a/src/app/app.less b/src/app/app.less new file mode 100644 index 00000000..4debb8ca --- /dev/null +++ b/src/app/app.less @@ -0,0 +1,157 @@ +.loom-notification-poster { + position:absolute; + z-index:1000; + left:325px; +} + +html, body { + -webkit-user-select: none; /* prevent copy paste, to allow, change 'none' to 'text' */ + margin : 0; + padding : 0; + height : 100%; + /* width : 100%; */ +} + +#pulldown { + position: absolute; + left: 0; + width: 320px; + z-index: 1000; + top: 0px; +} + +#pulldown .panel { + margin: 0; + border: 0; + font-weight: normal; + overflow: visible; + background-color:#97B3CD; +} + +.panel-body { + padding: 0px 15px; +} + +#pulldown-content .panel-heading { + background-color: #155481; + color: #fff; + display: block; + text-decoration: none; + border-bottom: 1px solid #80a0b0; +} + +#pulldown-content { + max-height: 80%; + overflow: hidden; +} + +#pulldown-shadow { + .box-shadow(6px 6px 12px rgba(0, 0, 0, 0.175)); +} + +.notification-panel-heading { + background-color: #4977A3 !important; +} + +#map { + min-height:100%; + height: 100%; + width: 100%; +} + +.panel { + margin: 0; + border: 0; + font-weight: normal; + /*overflow: visible;*/ + background-color:#97B3CD; +} + +.modal-header { + color: #fff; + background-color:#155481; + border-bottom: 1px solid #80a0b0; +} +.modal-footer { + background-color:#97B3CD; + border-top: 1px solid #80a0b0; + margin-top: 0; +} +.modal-body { + background-color:#97B3CD; +} + +.panel-group .panel-heading + .panel-collapse .panel-body{ + border-top: 1px solid #80a0b0; + border-bottom: 1px solid #155481; +} +.close { + color:#fff; +} +.flat { + border-radius: 0px; +} + +hr { + border-top: 1px solid #80a0b0; +} + +.rotate-45deg { + -webkit-transform:rotate(45deg); + -moz-transform:rotate(45deg); + -o-transform:rotate(45deg); + -ms-transform:rotate(45deg); +} + +/* Overwriting these because the default rounded corners didn't look quite right */ +.panel-heading, .flat-top { + border-top-left-radius: 0px; + border-top-right-radius: 0px; +} + +#layerPanel a.accordion-toggle { + display: inline-block; +} + +.badge { + background-color:#AA0000; + color:#FFF; + font-size: 14px; + padding:5px 10px; + border-radius: 20px; +} + +#pulldown-content .badge { + position: relative; + top: -2px; +} + +.layerSpan { +} + +.list-group { + margin-bottom:0px; +} + +.list-group-item { + background-color:#97B3CD; + border: 1px solid #80a0b0; +} + +.notification-text { + margin: 0px 0px 0px 0px; +} + +.notification-panel-heading { + font-weight:900; +} + +.notification-panel-heading.read { + font-weight:100; +} + +/*.notification-content.in { + max-height: 400px; + overflow: hidden; + overflow-y: auto; +}*/ \ No newline at end of file diff --git a/src/app/app.spec.js b/src/app/app.spec.js new file mode 100644 index 00000000..61d72e91 --- /dev/null +++ b/src/app/app.spec.js @@ -0,0 +1,17 @@ +describe( 'AppCtrl', function() { + describe( 'isCurrentUrl', function() { + var AppCtrl, $location, $scope; + + beforeEach( module( 'ngBoilerplate' ) ); + + beforeEach( inject( function( $controller, _$location_, $rootScope ) { + $location = _$location_; + $scope = $rootScope.$new(); + AppCtrl = $controller( 'AppCtrl', { $location: $location, $scope: $scope }); + })); + + it( 'should pass a dummy test', inject( function() { + expect( AppCtrl ).toBeTruthy(); + })); + }); +}); diff --git a/src/assets/README.md b/src/assets/README.md new file mode 100644 index 00000000..3040eacd --- /dev/null +++ b/src/assets/README.md @@ -0,0 +1,4 @@ +# The `src/assets` Directory + +There's really not much to say here. Every file in this directory is recursively transferred to `dist/assets/`. + diff --git a/src/common/README.md b/src/common/README.md new file mode 100644 index 00000000..2c68a757 --- /dev/null +++ b/src/common/README.md @@ -0,0 +1,24 @@ +# The `src/common/` Directory + +The `src/common/` directory houses internal and third-party re-usable +components. Essentially, this folder is for everything that isn't completely +specific to this application. + +Each component resides in its own directory that may then be structured any way +the developer desires. The build system will read all `*.js` files that do not +end in `.spec.js` as source files to be included in the final build, all +`*.spec.js` files as unit tests to be executed, and all `*.tpl.html` files as +templates to compiled into the `$templateCache`. There is currently no way to +handle components that do not meet this pattern. + +``` +src/ + |- common/ + | |- plusOne/ +``` + +- `plusOne` - a simple directive to load a Google +1 Button on an element. + +Every component contained here should be drag-and-drop reusable in any other +project; they should depend on no other components that aren't similarly +drag-and-drop reusable. diff --git a/src/common/diff/DiffListDirective.js b/src/common/diff/DiffListDirective.js new file mode 100644 index 00000000..c5a4b4a2 --- /dev/null +++ b/src/common/diff/DiffListDirective.js @@ -0,0 +1,17 @@ +(function() { + var module = angular.module('loom_diff_list_directive', []); + + module.directive('loomDiffList', function() { + return { + restrict: 'C', + replace: true, + scope: { + addList: '=', + modifyList: '=', + deleteList: '=', + clickCallback: '=' + }, + templateUrl: 'diff/partial/difflist.tpl.html' + }; + }); +}()); diff --git a/src/common/diff/DiffModule.js b/src/common/diff/DiffModule.js new file mode 100644 index 00000000..99c5466f --- /dev/null +++ b/src/common/diff/DiffModule.js @@ -0,0 +1,7 @@ +(function() { + angular.module('loom_diff', [ + 'loom_diff_list_directive', + 'loom_diff_service', + 'loom_diff_panel_directive' + ]); +}()); diff --git a/src/common/diff/DiffPanelDirective.js b/src/common/diff/DiffPanelDirective.js new file mode 100644 index 00000000..98eb0493 --- /dev/null +++ b/src/common/diff/DiffPanelDirective.js @@ -0,0 +1,31 @@ +(function() { + var module = angular.module('loom_diff_panel_directive', []); + + module.directive('loomDiffPanel', function($rootScope, diffService) { + return { + restrict: 'C', + replace: true, + templateUrl: 'diff/partial/diffpanel.tpl.html', + link: function(scope) { // Unused: element, attrs + function updateScopeVariables() { + if (!scope.$$phase && !$rootScope.$$phase) { + scope.$apply(function() { + scope.adds = diffService.getAdds(); + scope.modifies = diffService.getModifies(); + scope.deletes = diffService.getDeletes(); + }); + } else { + scope.adds = diffService.getAdds(); + scope.modifies = diffService.getModifies(); + scope.deletes = diffService.getDeletes(); + } + } + + updateScopeVariables(); + + scope.$on('diff_performed', updateScopeVariables); + scope.$on('diff_cleared', updateScopeVariables); + } + }; + }); +}()); diff --git a/src/common/diff/DiffService.js b/src/common/diff/DiffService.js new file mode 100644 index 00000000..d3df45c0 --- /dev/null +++ b/src/common/diff/DiffService.js @@ -0,0 +1,54 @@ +(function() { + var module = angular.module('loom_diff_service', []); + + // Private Variables + var adds = []; + var modifies = []; + var deletes = []; + var rootScope = null; + + module.provider('diffService', function() { + this.$get = function($rootScope) { + rootScope = $rootScope; + return this; + }; + + this.getAdds = function() { + return adds; + }; + + this.getModifies = function() { + return modifies; + }; + + this.getDeletes = function() { + return deletes; + }; + + this.performDiff = function(repo, from, to) { + adds = [ + {repo: 'repo1', layer: 'layer1', feature: 'fid-34f32ac32'} + ]; + modifies = [ + {repo: 'repo1', layer: 'layer1', feature: 'fid-ffc2380ba'}, + {repo: 'repo1', layer: 'layer2', feature: 'fid-87291defa'} + ]; + deletes = [ + {repo: 'repo1', layer: 'layer2', feature: 'fid-23cdfa320'} + ]; + rootScope.$broadcast('diff_performed', repo, from, to); + }; + + this.clearDiff = function() { + adds = []; + modifies = []; + deletes = []; + rootScope.$broadcast('diff_cleared'); + }; + + this.hasDifferences = function() { + return (adds.length + modifies.length + deletes.length !== 0); + }; + }); + +}()); diff --git a/src/common/diff/partial/difflist.tpl.html b/src/common/diff/partial/difflist.tpl.html new file mode 100644 index 00000000..c17cfefc --- /dev/null +++ b/src/common/diff/partial/difflist.tpl.html @@ -0,0 +1,13 @@ +
+
    +
  • + '{{add.feature}}' to {{add.layer}} +
  • +
  • + '{{modify.feature}}' in {{modify.layer}} +
  • +
  • + '{{delete.feature}}' from {{delete.layer}} +
  • +
+
\ No newline at end of file diff --git a/src/common/diff/partial/diffpanel.tpl.html b/src/common/diff/partial/diffpanel.tpl.html new file mode 100644 index 00000000..3f6055ad --- /dev/null +++ b/src/common/diff/partial/diffpanel.tpl.html @@ -0,0 +1,3 @@ +
+
+
\ No newline at end of file diff --git a/src/common/diff/style/difflist.less b/src/common/diff/style/difflist.less new file mode 100644 index 00000000..5ed769a6 --- /dev/null +++ b/src/common/diff/style/difflist.less @@ -0,0 +1,9 @@ +.add { + color: #008800; +} +.modify { + color: #666600; +} +.delete { + color: #880000; +} \ No newline at end of file diff --git a/src/common/notificationposter/NotificationPosterDirective.js b/src/common/notificationposter/NotificationPosterDirective.js new file mode 100644 index 00000000..6b72b5df --- /dev/null +++ b/src/common/notificationposter/NotificationPosterDirective.js @@ -0,0 +1,67 @@ +(function() { + var module = angular.module('loom_notification_poster_directive', []); + + module.directive('loomNotificationPoster', + function($rootScope, notificationService, diffService) { + return{ + restrict: 'C', + replace: true, + template: '
' + + '
' + + ' ' + + ' ' + + ' ' + + '
' + + '
', + // The linking function will add behavior to the template + link: function(scope) { //Unused: element, attrs + function addNotification() { + notificationService.addNotification({ + text: '1 Added, 3 Modified, 1 Deleted', + read: false, + type: 'loom-update-notification', + repos: [ + { + name: 'geogit_repo', + layers: [ + { + name: 'layer1', + adds: [], + modifies: ['feature3'], + deletes: ['feature5'] + }, + { + name: 'layer2', + adds: ['feature6'], + modifies: ['feature2', 'feature4'], + deletes: [] + } + ] + } + ], + callback: function(feature) { + alert(feature.feature + ' was clicked!'); + } + }); + } + + scope.addNotification = addNotification; + + function performDiff() { + diffService.performDiff('repo', 'from', 'to'); + } + + scope.performDiff = performDiff; + + function clearDiff() { + diffService.clearDiff(); + } + + scope.clearDiff = clearDiff; + } + }; + }); +}()); diff --git a/src/common/notificationposter/NotificationPosterModule.js b/src/common/notificationposter/NotificationPosterModule.js new file mode 100644 index 00000000..7e76b6f1 --- /dev/null +++ b/src/common/notificationposter/NotificationPosterModule.js @@ -0,0 +1,5 @@ +(function() { + angular.module('loom_notification_poster', [ + 'loom_notification_poster_directive' + ]); +}()); diff --git a/src/common/notificationposter/style/notificationposter.less b/src/common/notificationposter/style/notificationposter.less new file mode 100644 index 00000000..e69de29b diff --git a/src/common/notifications/NotificationBadgeDirective.js b/src/common/notifications/NotificationBadgeDirective.js new file mode 100644 index 00000000..8e93211f --- /dev/null +++ b/src/common/notifications/NotificationBadgeDirective.js @@ -0,0 +1,27 @@ +(function() { + var module = angular.module('loom_notification_badge_directive', []); + + module.directive('loomNotificationBadge', + function($rootScope, notificationService) { + return { + restrict: 'C', + replace: true, + templateUrl: 'notifications/partial/notificationbadge.tpl.html', + // The linking function will add behavior to the template + link: function(scope) { // Unused: element, attrs + function updateScopeVariables() { + if (!scope.$$phase && !$rootScope.$$phase) { + scope.$apply(function() { + scope.notificationService = notificationService; + }); + } + } + + scope.notificationService = notificationService; + scope.$on('notification_added', updateScopeVariables); + scope.$on('notification_updated', updateScopeVariables); + scope.$on('notification_removed', updateScopeVariables); + } + }; + }); +}()); diff --git a/src/common/notifications/NotificationsDirective.js b/src/common/notifications/NotificationsDirective.js new file mode 100644 index 00000000..3d8a248b --- /dev/null +++ b/src/common/notifications/NotificationsDirective.js @@ -0,0 +1,45 @@ +(function() { + var module = angular.module('loom_notifications_directive', []); + + module.directive('loomNotifications', + function($rootScope, notificationService) { + return { + restrict: 'C', + replace: true, + scope: {emptyText: '@notificationEmptyText' }, + templateUrl: 'notifications/partial/notifications.tpl.html', + // The linking function will add behavior to the template + link: function(scope) { //Unused: element, attrs + function removeNotification(id) { + notificationService.removeNotification(id); + } + + scope.removeNotification = removeNotification; + + function markAsRead(id) { + notificationService.markAsRead( + notificationService.getNotification(id) + ); + } + + scope.markAsRead = markAsRead; + + function updateScopeVariables() { + if (!scope.$$phase && !$rootScope.$$phase) { + scope.$apply(function() { + scope.notificationService = notificationService; + }); + } else { + scope.notificationService = notificationService; + } + } + + scope.notificationService = notificationService; + + scope.$on('notification_added', updateScopeVariables); + scope.$on('notification_updated', updateScopeVariables); + scope.$on('notification_removed', updateScopeVariables); + } + }; + }); +}()); diff --git a/src/common/notifications/NotificationsModule.js b/src/common/notifications/NotificationsModule.js new file mode 100644 index 00000000..b529e9fb --- /dev/null +++ b/src/common/notifications/NotificationsModule.js @@ -0,0 +1,7 @@ +(function() { + angular.module('loom_notifications', [ + 'loom_notifications_directive', + 'loom_notifications_service', + 'loom_notification_badge_directive' + ]); +}()); diff --git a/src/common/notifications/NotificationsService.js b/src/common/notifications/NotificationsService.js new file mode 100644 index 00000000..336c072c --- /dev/null +++ b/src/common/notifications/NotificationsService.js @@ -0,0 +1,71 @@ +(function() { + var module = angular.module('loom_notifications_service', []); + + // Private Variables + var notifications = []; + var nextNotificationId = 0; + var rootScope = null; + + module.provider('notificationService', function() { + this.$get = function($rootScope) { + rootScope = $rootScope; + return this; + }; + + this.getNotifications = function() { + return notifications; + }; + + this.addNotification = function(notification) { + notification.id = nextNotificationId; + nextNotificationId = nextNotificationId + 1; + notifications.push(notification); + rootScope.$broadcast('notification_added', notification); + }; + + this.unreadCount = function() { + var unread = 0, i; + + for (i = 0; i < notifications.length; i = i + 1) { + if (notifications[i].read === false) { + unread = unread + 1; + } + } + return unread; + }; + + this.markAsRead = function(notification) { + var i; + for (i = 0; i < notifications.length; i = i + 1) { + if (notifications[i].id === notification.id) { + notifications[i].read = true; + } + } + rootScope.$broadcast('notification_updated', notification); + }; + + this.getNotification = function(id) { + var i; + for (i = 0; i < notifications.length; i = i + 1) { + if (notifications[i].id === id) { + return notifications[i]; + } + } + return null; + }; + + this.removeNotification = function(id) { + var index = -1, i; + for (i = 0; i < notifications.length; i = i + 1) { + if (notifications[i].id === id) { + index = i; + } + } + if (index > -1) { + notifications.splice(index, 1); + } + rootScope.$broadcast('notification_removed', id); + }; + }); + +}()); diff --git a/src/common/notifications/partial/notificationbadge.tpl.html b/src/common/notifications/partial/notificationbadge.tpl.html new file mode 100644 index 00000000..07efb5ab --- /dev/null +++ b/src/common/notifications/partial/notificationbadge.tpl.html @@ -0,0 +1,3 @@ +
+ {{notificationService.unreadCount()}} +
\ No newline at end of file diff --git a/src/common/notifications/partial/notifications.tpl.html b/src/common/notifications/partial/notifications.tpl.html new file mode 100644 index 00000000..49347339 --- /dev/null +++ b/src/common/notifications/partial/notifications.tpl.html @@ -0,0 +1,16 @@ +
+
+
{{emptyText}}
+
+
+
+ +

{{notification.text}}

+
+
+
+
+
{{notification.text}}
+
+
+
\ No newline at end of file diff --git a/src/common/notifications/style/notifications.less b/src/common/notifications/style/notifications.less new file mode 100644 index 00000000..243af162 --- /dev/null +++ b/src/common/notifications/style/notifications.less @@ -0,0 +1,13 @@ +#notification-content .panel-heading { + color: #fff; + background-color: #155481; + display: block; + text-decoration: none; + border-bottom: 1px solid #80a0b0; +} + +.close-notification { + position:absolute; + right:-15px; + font-size:18px; +} \ No newline at end of file diff --git a/src/common/updatenotification/UpdateNotificationDirective.js b/src/common/updatenotification/UpdateNotificationDirective.js new file mode 100644 index 00000000..099cc881 --- /dev/null +++ b/src/common/updatenotification/UpdateNotificationDirective.js @@ -0,0 +1,66 @@ +(function() { + var module = angular.module('loom_update_notification_directive', []); + + module.directive('loomUpdateNotification', + function() { + return { + restrict: 'C', + replace: true, + scope: { notification: '=' }, + templateUrl: 'updatenotification/partial/updatenotification.tpl.html', + // The linking function will add behavior to the template + link: function(scope) { // Unused: element, attrs + + var headerElement = angular.element('#update-notification-header-' + scope.notification.id); + headerElement.attr('data-toggle', 'collapse'); + headerElement.attr('data-target', '#notification-description-' + scope.notification.id); + headerElement.attr('data-parent', '#notification-collapse-group'); + headerElement.addClass('toggle'); + headerElement.addClass('collapsed'); + + var repos = scope.notification.repos; + var adds = []; + var modifies = []; + var deletes = []; + + var i, j, k; + for (i = 0; i < repos.length; i += 1) { + var layers = repos[i].layers; + for (j = 0; j < layers.length; j += 1) { + var layer = layers[j]; + if (layer.adds) { + for (k = 0; k < layer.adds.length; k += 1) { + adds.push({ + repo: repos[i].name, + layer: layer.name, + feature: layer.adds[k] + }); + } + } + if (layer.modifies) { + for (k = 0; k < layer.modifies.length; k += 1) { + modifies.push({ + repo: repos[i].name, + layer: layer.name, + feature: layer.modifies[k] + }); + } + } + if (layer.deletes) { + for (k = 0; k < layer.deletes.length; k += 1) { + deletes.push({ + repo: repos[i].name, + layer: layer.name, + feature: layer.deletes[k] + }); + } + } + } + } + scope.adds = adds; + scope.modifies = modifies; + scope.deletes = deletes; + } + }; + }); +}()); diff --git a/src/common/updatenotification/UpdateNotificationModule.js b/src/common/updatenotification/UpdateNotificationModule.js new file mode 100644 index 00000000..54029426 --- /dev/null +++ b/src/common/updatenotification/UpdateNotificationModule.js @@ -0,0 +1,5 @@ +(function() { + angular.module('loom_update_notification', [ + 'loom_update_notification_directive' + ]); +}()); diff --git a/src/common/updatenotification/partial/updatenotification.tpl.html b/src/common/updatenotification/partial/updatenotification.tpl.html new file mode 100644 index 00000000..7eb265c0 --- /dev/null +++ b/src/common/updatenotification/partial/updatenotification.tpl.html @@ -0,0 +1,3 @@ +
+
+
\ No newline at end of file diff --git a/src/common/updatenotification/style/updatenotification.less b/src/common/updatenotification/style/updatenotification.less new file mode 100644 index 00000000..e69de29b diff --git a/src/index.html b/src/index.html new file mode 100644 index 00000000..5909dddc --- /dev/null +++ b/src/index.html @@ -0,0 +1,70 @@ + + + + + + + + + + + + + <% styles.forEach( function ( file ) { %> + <% }); %> + + <% scripts.forEach( function ( file ) { %> + <% }); %> + + +
+
+
+
+
+ + New Map + + +
+
+
+
+
+ Notifications + +
+
+
+
+
+
+
+ Differences +
+
Diffs go here.
+
+
+
+
+ +
+
+
+
+ + + diff --git a/src/less/README.md b/src/less/README.md new file mode 100644 index 00000000..a7673152 --- /dev/null +++ b/src/less/README.md @@ -0,0 +1,28 @@ +# The `src/less` Directory + +This folder is actually fairly self-explanatory: it contains your LESS/CSS files to be compiled during the build. +The only important thing to note is that *only* `main.less` will be processed during the build, meaning that all +other stylesheets must be *imported* into that one. + +This should operate somewhat like the routing; the `main.less` file contains all of the site-wide styles, while +any styles that are route-specific should be imported into here from LESS files kept alongside the JavaScript +and HTML sources of that component. For example, the `home` section of the site has some custom styles, which +are imported like so: + +```css +@import '../app/home/home.less'; +``` + +The same principal, though not demonstrated in the code, would also apply to reusable components. CSS or LESS +files from external components would also be imported. If, for example, we had a Twitter feed directive with +an accompanying template and style, we would similarly import it: + +```css +@import '../common/twitterFeed/twitterFeedDirective.less'; +``` + +Using this decentralized approach for all our code (JavaScript, HTML, and CSS) creates a framework where a +component's directory can be dragged and dropped into *any other project* and it will "just work". + +I would like to eventually automate the importing during the build so that manually importing it here would no +longer be required, but more thought must be put in to whether this is the best approach. diff --git a/src/less/main.less b/src/less/main.less new file mode 100644 index 00000000..71436c4e --- /dev/null +++ b/src/less/main.less @@ -0,0 +1,37 @@ +/** + * This is the main application stylesheet. It should include or import all + * stylesheets used throughout the application as this is the only stylesheet in + * the Grunt configuration that is automatically processed. + */ + + +/** + * First, we include the Twitter Bootstrap LESS files. Only the ones used in the + * project should be imported as the rest are just wasting space. + */ + +@import '../../vendor/bootstrap/less/bootstrap.less'; + + +/** + * This is our main variables file. It in turn imports the `variables` file from + * Twitter Bootstrap. We must include it last so we can overwrite any variable + * definitions in our imported stylesheets. + */ + +@import 'variables.less'; + + +/** + * Now that all app-wide styles have been applied, we can load the styles for + * all the submodules and components we are using. + * + * TODO: In a later version of this boilerplate, I'd like to automate this. + */ + +@import '../common/diff/style/difflist.less'; +@import '../common/notificationposter/style/notificationposter.less'; +@import '../common/notifications/style/notifications.less'; +@import '../common/updatenotification/style/updatenotification.less'; +@import '../app/app.less'; + diff --git a/src/less/variables.less b/src/less/variables.less new file mode 100644 index 00000000..b923ac77 --- /dev/null +++ b/src/less/variables.less @@ -0,0 +1,14 @@ +/** + * These are the variables used throughout the application. This is where + * overwrites that are not specific to components should be maintained. + */ + +@import '../../vendor/bootstrap/less/variables.less'; + + +/** + * Typography-related. + */ + +@sansFontFamily: 'Roboto', sans-serif; + diff --git a/tools.md b/tools.md new file mode 100644 index 00000000..4547347e --- /dev/null +++ b/tools.md @@ -0,0 +1,223 @@ +# The Tools Used in `ngBoilerplate` + +## Introduction + +`ngBoilerplate` is standards-based, so it uses all the usual tools to manage +and develop client-side code. If you've developed modern, highly-organized +JavaScript projects before, you are probably already familiar with at least most +of these tools. What follows is a simple description of the tools of which this +project makes use and how they fit in to the `ngBoilerplate` picture. + +## Git + +[Git](http://git-scm.com/) is a distributed version control system. +`ngBoilerplate` uses git to manage its codebase. While in theory you don't have +to use Git once you download `ngBoilerplate`, this project makes the assumption +that you do. If you're on GitHub, I assume you already have a basic +understanding of Git, which is all you need to make effective use of this +project. You just need to be able to commit and push and junk - nothing funky. +If you're not familiar with it, check out the documentation linked to above. +GitHub also has a great [help section](https://help.github.com/). + +## Node.js & NPM + +[Node.js](http://nodejs.org) is a platform based on Chrome's JavaScript runtime, +called [V8](http://code.google.com/p/v8/). It allows you to develop all kinds of +software using the JavaScript you already know and love. + +A great feature of Node.js is its wide variety of existing libraries and tools. +As the developer community is absolutely massive and incredibly active, Node.js +has a basic package manager called NPM that you can use to install Node.js-based +software and libraries from the command line. + +While `ngBoilerplate` makes heavy use of Node.js behind the scenes, you as the +application developer don't need to really think about it much. Most of the +interaction with Node.js will occur through Grunt (see next section), so you +really only need to know how get the initial setup working. + +`package.json` is an NPM package description file written in JSON. It contains +basic metadata about your application, like its name, version, and dependencies. +By default, several packages are required for the build process to work; so when +you first start with `ngBoilerplate` you have to tell NPM to install the +packages; this is covered in detail in the [main README](README.md). Some of +the required packages are Grunt build tasks (see below), while others are +command-line tools either we (or the build system) need, like Karma, Grunt, and +Bower. + +Don't worry about knowing Node.js in order to use `ngBoilerplate`; Grunt is +where the magic happens. + +## Grunt.js + +[Grunt](http://gruntjs.com) is a JavaScript task runner that runs on top of +Node.js. Most importantly, Grunt brings us automation. There are lots of steps +that go into taking our manageable codebase and making it into a +production-ready website; we must gather, lint, test, annotate, and copy files +about. Instead of doing all of that manually, we write (and use others') Grunt +tasks to do things for us. + +When we want to build our site, we can just type: + +```sh +$ grunt +``` + +This will do everything needed and place our built code inside a folder called +`bin/`. Even more magical, we can tell Grunt to watch for file changes we make +so it can re-build our site on-the-fly: + +```sh +$ grunt watch +``` + +The built files will be in `build/`. See the main [README](README.md) for more +info. + +The next time we change a source file, Grunt will re-build the changed parts of +the site. If you have a Live Reload plugin installed in your browser, it will +even auto-refresh your browser for you. You lazy bum. + +Grunt is controlled through `Gruntfile.js`. This file is heavily documented in +the source, so I will only provide a high-altitude overview here. Also note that +unless you need to modify the build process, you don't need to know anything +else from this section. The two commands above really are all you need to know +to get started with `ngBoilerplate`. But for those curious or looking to go a +little more advanced, here's what you'll find. + +First, we tell Grunt which tasks we might want to use: + +```js +// ... +grunt.loadNpmTasks('grunt-recess'); +grunt.loadNpmTasks('grunt-contrib-clean'); +grunt.loadNpmTasks('grunt-contrib-copy'); +grunt.loadNpmTasks('grunt-contrib-jshint'); +// ... +``` + +Each of these tasks must already be installed. Remember the dependencies from +`package.json` that NPM installed for us? Well, this is where they get used! + +Then we get the opportunity to tell the tasks to behave like we want by +defining a configuration object. While we can (and do) define all sorts of +custom configuration values that we reference later on, tasks look for +configuration properties of their own name. For example, the `clean` task just +takes an array of files to delete when the task runs: + +```js +clean: [ '<%= build_dir %>', '<%= compile_dir %>' ], +``` + +In Grunt, the `<%= varName %>` is a way of re-using configuration variables. +In the `build.config.js`, we defined what `build_dir` meant: + +```js +build_dir: 'build', +``` + +When the clean task runs, it will delete the `build/` folder entirely so that +when our new build runs, we don't encounter any problems with stale or old +files. Most tasks, however, have considerably more complicated configuration +requirements, but I've tried to document what each one is doing and what the +configuration properties mean. If I was vague or ambiguous or just plain +unclear, please file an issue and I'll get it fixed. Boom - problem solved. + +After our configuration is complete, we can define some of our own tasks. For +example, we could do the build by running all of the separate tasks that we +installed from NPM and configured as above: + +```sh +$ grunt clean +$ grunt html2js +$ grunt jshint +$ grunt karma:continuous +$ grunt concat +$ grunt ngmin:dist +$ grunt uglify +$ grunt recess +$ grunt index +$ grunt copy +``` + +But how automated is that? So instead we define a composite task that executes +all that for us. The commands above make up the `default` tasks, which can be +run by typing *either* of these commands: + +```js +$ grunt +$ grunt default +``` + +We also define the `watch` task discussed earlier. This is covered in more +detail in the main (README)[README.md]. + +Grunt is the engine behind `ngBoilerplate`. It's the magic that makes it move. +Just getting started, you won't need to alter `Gruntfile.js` at all, but +as you get into more advanced application development, you will probably need to +add more tasks and change some steps around to make this build your own. +Hopefully, this readme and the documentation within `Gruntfile.js` (as well as +of course the documentation at gruntjs.com) will set you on the right path. + +## Bower + +[Bower](bower.io) is a package manager for the web. It's similar in many +respects to NPM, though it is significantly simpler and only contains code for +web projects, like Twitter Bootstrap and its AngularJS counterpart Angular +Bootstrap. Bower allows us to say that our app depends in some way on these +other libraries so that we can manage all of them in one simple place. + +`ngBoilerplate` comes with a `bower.json` file that looks something like this: + +```js +{ + "name": "ng-boilerplate", + "version": "0.2.0-SNAPSHOT", + "devDependencies": { + "angular": "~1.0.7", + "angular-mocks": "~1.0.7", + "bootstrap": "~2.3.2", + "angular-bootstrap": "~0.3.0", + "angular-ui-router": "~0.0.1", + "angular-ui-utils": "~0.0.3" + }, + "dependencies": {} +} +``` + +This file is fairly self-explanatory; it gives the package name and version +(duplicated from `package.json`, but this is unavoidable) as well as a list of +dependencies our application needs in order to work. If we simply call + +```sh +$ bower install +``` + +it will read these three dependencies and install them into the `vendor/` folder +(along with any dependencies they have) so that we can use them in our app. If +we want to add a new package like AngularUI's +[ngGrid](http://angular-ui.github.io/ng-grid/), then we can tell Bower to +install that from the web, place it into the `vendor/` folder for us to use, and +then add it as a dependency to `bower.json`: + +```js +$ bower install angular-grid --save-dev +``` + +Bower can also update all of our packages for us at a later date, though that +and its many other awesome features are beyond the scope of this simple +overview. + +One last thing to note is that packages installed with Bower are not +standardized, so we cannot automatically add them to the build process; anything +installed with Bower (or placed in the `vendor/` directory manually) *must* be +added to your `build.config.js` file manually; look for the Bower libs included +in `ngBoilerplate` by default in there to see what I mean. + +## Where to Go From Here + +That's it! Now that you have a basic understanding of the tools involved, read +through the [main README](README.md) to dive another level deeper and apply what +you've learned for great good. I promise it will all make sense it short order. + +Happy programming! +