├── .bowerrc ├── .gitignore ├── .jshintrc ├── Gruntfile.js ├── LICENSE ├── README.md ├── app ├── README.md ├── fonts │ ├── FontAwesome.otf │ ├── fontawesome-webfont.eot │ ├── fontawesome-webfont.svg │ ├── fontawesome-webfont.ttf │ ├── fontawesome-webfont.woff │ ├── fontawesome-webfont.woff2 │ ├── ionicons.eot │ ├── ionicons.svg │ ├── ionicons.ttf │ └── ionicons.woff ├── images │ ├── cards │ │ ├── ben.png │ │ ├── face-1.jpg │ │ ├── face-2.jpg │ │ ├── face-3.jpg │ │ ├── face-4.jpg │ │ ├── face-5.jpg │ │ ├── face-6.jpg │ │ ├── face-7.jpg │ │ ├── max.jpg │ │ └── perry.jpg │ └── ionic.png ├── index.html ├── scripts │ ├── app.js │ ├── common │ │ ├── common.module.js │ │ ├── directives │ │ │ └── gmaps │ │ │ │ └── gmaps.directive.js │ │ └── services │ │ │ ├── extenal-apps.service.js │ │ │ └── html-to-plain-text.service.js │ ├── config │ │ ├── internet-connectivity.js │ │ └── spinner.js │ ├── elements │ │ ├── checkbox.html │ │ ├── elements.controller.js │ │ ├── elements.html │ │ ├── elements.module.js │ │ ├── form-floating-labels.html │ │ ├── form-inline-labels.html │ │ ├── form-input-icons.html │ │ ├── form-inset-form.html │ │ ├── form-inset-inputs.html │ │ ├── form-placeholder-labels.html │ │ ├── form-stacked-labels.html │ │ ├── radiobuttons.html │ │ ├── range.html │ │ ├── select.html │ │ ├── tabs-icononly.html │ │ ├── tabs-lefticon.html │ │ ├── tabs-striped.html │ │ ├── tabs-topicon.html │ │ └── toggle.html │ ├── home │ │ ├── home-data.service.js │ │ ├── home.controller.js │ │ ├── home.html │ │ ├── home.module.js │ │ └── menu-items.service.js │ ├── map │ │ ├── map.controller.js │ │ ├── map.html │ │ ├── map.module.js │ │ └── map.service.js │ ├── menu │ │ ├── menu.controller.js │ │ ├── menu.html │ │ └── menu.module.js │ ├── native-scrolling │ │ ├── native-scrolling.controller.js │ │ ├── native-scrolling.html │ │ ├── native-scrolling.module.js │ │ └── native-scrolling.service.js │ ├── new-slide-box │ │ ├── new-slide-box.controller.js │ │ ├── new-slide-box.html │ │ └── new-slide-box.module.js │ ├── popover-menu │ │ ├── popover-menu.controller.js │ │ ├── popover-menu.html │ │ ├── popover-menu.module.js │ │ ├── popover-view.html │ │ └── popover-view.service.js │ └── wordpress │ │ ├── wordpress-article.controller.js │ │ ├── wordpress-article.html │ │ ├── wordpress-articles.controller.js │ │ ├── wordpress-articles.html │ │ ├── wordpress.module.js │ │ └── wordpress.service.js └── styles │ ├── common.scss │ ├── home.scss │ ├── main.scss │ └── map.scss ├── bower.json ├── changelog.md ├── config.xml ├── hooks ├── README.md ├── after_platform_add │ └── install_plugins.js ├── after_plugin_add │ └── register_plugins.js ├── after_plugin_rm │ └── deregister_plugins.js ├── after_prepare │ ├── icons_and_splashscreens.js │ └── update_platform_config.js └── before_platform_add │ └── init_directories.js ├── install.bat ├── install.sh ├── ionic.project ├── misc ├── faces.psd └── menu-items │ ├── item-01-1.jpg │ ├── item-01-thumb.jpg │ ├── item-02-1.jpg │ ├── item-02-thumb.jpg │ ├── item-03-1.jpg │ ├── item-03-thumb.jpg │ ├── item-04-1.jpg │ ├── item-04-thumb.jpg │ ├── item-05-1.jpg │ ├── item-05-thumb.jpg │ ├── item-06-1.jpg │ ├── item-06-thumb.jpg │ ├── item-07-1.jpg │ ├── item-07-thumb.jpg │ ├── item-08-1.jpg │ ├── item-08-thumb.jpg │ ├── item-09-1.jpg │ ├── item-09-thumb.jpg │ ├── item-10-1.jpg │ ├── item-10-thumb.jpg │ ├── item-11-1.jpg │ ├── item-11-thumb.jpg │ ├── item-12-1.jpg │ ├── item-12-thumb.jpg │ └── items.json ├── package.json ├── package.json.local ├── resources ├── android │ ├── drawable-hdpi │ │ ├── ic_action_next_item.png │ │ ├── ic_action_previous_item.png │ │ ├── ic_action_remove.png │ │ └── icon.png │ ├── drawable-land-hdpi │ │ └── screen.png │ ├── drawable-land-ldpi │ │ └── screen.png │ ├── drawable-land-mdpi │ │ └── screen.png │ ├── drawable-land-xhdpi │ │ └── screen.png │ ├── drawable-ldpi │ │ └── icon.png │ ├── drawable-mdpi │ │ ├── ic_action_next_item.png │ │ ├── ic_action_previous_item.png │ │ ├── ic_action_remove.png │ │ └── icon.png │ ├── drawable-port-hdpi │ │ └── screen.png │ ├── drawable-port-ldpi │ │ └── screen.png │ ├── drawable-port-mdpi │ │ └── screen.png │ ├── drawable-port-xhdpi │ │ └── screen.png │ ├── drawable-xhdpi │ │ ├── ic_action_next_item.png │ │ ├── ic_action_previous_item.png │ │ ├── ic_action_remove.png │ │ └── icon.png │ ├── drawable-xxhdpi │ │ ├── ic_action_next_item.png │ │ ├── ic_action_previous_item.png │ │ └── ic_action_remove.png │ └── drawable │ │ └── icon.png └── ios │ ├── icons │ ├── icon-40.png │ ├── icon-40@2x.png │ ├── icon-50.png │ ├── icon-50@2x.png │ ├── icon-60.png │ ├── icon-60@2x.png │ ├── icon-60@3x.png │ ├── icon-72.png │ ├── icon-72@2x.png │ ├── icon-76.png │ ├── icon-76@2x.png │ ├── icon-small.png │ ├── icon-small@2x.png │ ├── icon.png │ └── icon@2x.png │ └── splash │ ├── Default-568h@2x~iphone.png │ ├── Default-667h.png │ ├── Default-736h.png │ ├── Default-Landscape-736h.png │ ├── Default-Landscape@2x~ipad.png │ ├── Default-Landscape~ipad.png │ ├── Default-Portrait@2x~ipad.png │ ├── Default-Portrait~ipad.png │ ├── Default@2x~iphone.png │ └── Default~iphone.png ├── test └── .jshintrc └── typings └── angularjs └── angular.d.ts /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "app/bower_components" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | www 3 | .idea 4 | .temp 5 | .sass-cache 6 | app/bower_components 7 | coverage 8 | platforms 9 | plugins 10 | *.swp 11 | *.swo 12 | *.log 13 | *.DS_Store 14 | 15 | app/scripts/configuration.js 16 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "bitwise": true, 3 | "camelcase": true, 4 | "curly": true, 5 | "eqeqeq": true, 6 | "es3": false, 7 | "forin": true, 8 | "freeze": true, 9 | "immed": true, 10 | "indent": 4, 11 | "latedef": "nofunc", 12 | "newcap": true, 13 | "noarg": true, 14 | "noempty": true, 15 | "nonbsp": true, 16 | "nonew": true, 17 | "plusplus": false, 18 | "quotmark": "single", 19 | "undef": true, 20 | "unused": false, 21 | "strict": false, 22 | "maxparams": 10, 23 | "maxdepth": 5, 24 | "maxstatements": 40, 25 | "maxcomplexity": 8, 26 | "maxlen": 120, 27 | 28 | "asi": false, 29 | "boss": false, 30 | "debug": false, 31 | "eqnull": true, 32 | "esnext": false, 33 | "evil": false, 34 | "expr": false, 35 | "funcscope": false, 36 | "globalstrict": false, 37 | "iterator": false, 38 | "lastsemic": false, 39 | "laxbreak": false, 40 | "laxcomma": false, 41 | "loopfunc": true, 42 | "maxerr": false, 43 | "moz": false, 44 | "multistr": false, 45 | "notypeof": false, 46 | "proto": false, 47 | "scripturl": false, 48 | "shadow": false, 49 | "sub": true, 50 | "supernew": false, 51 | "validthis": false, 52 | "noyield": false, 53 | 54 | "browser": true, 55 | "node": true, 56 | 57 | "globals": { 58 | "alert": false, 59 | "angular": false, 60 | "cordova": false, 61 | "StatusBar": false, 62 | "ionic": false 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | // Generated on 2015-05-01 using generator-ionic 0.7.3 2 | 'use strict'; 3 | 4 | var _ = require('lodash'); 5 | var path = require('path'); 6 | var cordovaCli = require('cordova'); 7 | var spawn = process.platform === 'win32' ? require('win-spawn') : require('child_process').spawn; 8 | 9 | module.exports = function(grunt) { 10 | 11 | // Load grunt tasks automatically 12 | require('load-grunt-tasks')(grunt); 13 | 14 | // Time how long tasks take. Can help when optimizing build times 15 | require('time-grunt')(grunt); 16 | 17 | // Define the configuration for all the tasks 18 | grunt.initConfig({ 19 | 20 | // Project settings 21 | yeoman: { 22 | // configurable paths 23 | app: 'app', 24 | scripts: 'scripts', 25 | styles: 'styles', 26 | images: 'images', 27 | test: 'test', 28 | dist: 'www' 29 | }, 30 | 31 | // Includes all js files into index.html 32 | includeSource: { 33 | options: { 34 | basePath: 'app', 35 | baseUrl: '', 36 | }, 37 | server: { 38 | files: { 39 | '.temp/index.html': '<%= yeoman.app %>/index.html' 40 | } 41 | }, 42 | dist: { 43 | files: { 44 | '<%= yeoman.dist %>/index.html': '<%= yeoman.app %>/index.html' 45 | } 46 | } 47 | }, 48 | 49 | // Environment Variables for Angular App 50 | // This creates an Angular Module that can be injected via ENV 51 | // Add any desired constants to the ENV objects below. 52 | // https://github.com/diegonetto/generator-ionic/blob/master/docs/FAQ.md#how-do-i-add-constants 53 | ngconstant: { 54 | options: { 55 | space: ' ', 56 | wrap: '"use strict";\n\n {%= __ngModule %}', 57 | name: 'config', 58 | dest: '<%= yeoman.app %>/<%= yeoman.scripts %>/configuration.js' 59 | }, 60 | development: { 61 | constants: { 62 | ENV: { 63 | name: 'development', 64 | apiEndpoint: 'http://dev.yoursite.com:10000/', 65 | youtubeKey: 'AIzaSyDael5MmCQa1GKQNKQYypmBeB08GATgSEo', 66 | ionicPrivateKey: 'a9265eaf15a20cc8516c770e8748aeed4891b28f453ce755', //'c63b22cd7330a4a9d5e526bfcd74891a59fd5c23d1d81239', 67 | ionicPublicKey: 'e30d4d540b8c75d1f167bbf242423c3fb23fe10275d1c016', //'04dee953a91ef3857f1c8a7cf4748ecee375848681f7e833', 68 | ionicAppId: '241b6d37', //'2113c758', 69 | gcmId: '228071472080', 70 | // https://developer.vimeo.com/api/authentication#single-user 71 | vimeoAccessToken: 'd995ffff0228beba7c9716c3ee0d4add', 72 | // https://developers.facebook.com/apps/ 73 | facebookAppId: '785803021527033', //'927897987270774', 74 | // http://logicum.co/getting-a-facebook-page-permanent-access-token/ 75 | facebookPermanentAccessToken: 'CAANL6xXrSHYBANNHhMUDugVZBHXfVQBMeWG6FmpYROWcOEmC2xze1BNiraZB87NCAZC3w08L7KhCBnhJItZCUzWCgBNzBjt0BkoV6qMoXjIZBjkWRTUGgZBR39OZAiP3DF76jufQ4hJ7xsdQc0l68vFAZAePdZCZAjkjTwaOeEZC22xi8ZAQYBqvNvYRgIfOZBzf4zRURHgrLtNazxzln8ZBkd9FZC7', 76 | facebookPage: 'apple.inc', 77 | // https://instagram.com/developer/ 78 | instagramAppId: '2998ca20ed924ca3be22907c6ae77363', //'ab4ccebff87a46e789e231bed83685e4' 79 | firebaseUrl: 'barebone-ionic.firebaseio.com', //'https://barebone-chat.firebaseio.com/', 80 | iosUrl: 'com.titaniumtemplates.barebone-ionic', 81 | androidUrl: 'market://details?id=com.titaniumtemplates.barebone-ionic', 82 | usesUntilRatePrompt: 4, 83 | androidPublisherKey: 'ca-app-pub-3965039466794589/2790557649', 84 | //'ca-app-pub-5273644196186544/3459900111', 85 | iosPublisherKey: 'ca-app-pub-3965039466794589/2930158449', 86 | //'ca-app-pub-5273644196186544/3850179718' 87 | // http://excellencenodejsblog.com/cordova-ionic-google-oauth-login-for-your-mobile-app/ 88 | googleAppId: '400671186930-m07eu77bm43tgr30p90k6b9e1qgsva4p.apps.googleusercontent.com', 89 | // http://devdactic.com/twitter-rest-api-angularjs/ 90 | // Requesting a user’s email address requires your application to be whitelisted by Twitter 91 | // https://dev.twitter.com/rest/reference/get/account/verify_credentials 92 | twitterApiKey: 'wXRPbDKzyLXOy4etLq4fNqu8M', 93 | twitterApiSecret: '1Bi6DGM98yc9MToSLstGLFaB2tvHOLkBrBBYm8WWI2fTKl0gWX' 94 | } 95 | } 96 | }, 97 | production: { 98 | constants: { 99 | ENV: { 100 | name: 'production', 101 | apiEndpoint: 'http://api.yoursite.com/', 102 | youtubeKey: '' 103 | } 104 | } 105 | } 106 | }, 107 | 108 | // Watches files for changes and runs tasks based on the changed files 109 | watch: { 110 | bower: { 111 | files: ['bower.json'], 112 | tasks: ['wiredep', 'newer:copy:app'] 113 | }, 114 | html: { 115 | files: ['<%= yeoman.app %>/**/*.html'], 116 | tasks: ['newer:copy:app'] 117 | }, 118 | js: { 119 | files: ['<%= yeoman.app %>/<%= yeoman.scripts %>/**/*.js'], 120 | tasks: ['newer:copy:app', 'newer:jshint:all'] 121 | }, 122 | styles: { 123 | files: ['<%= yeoman.app %>/<%= yeoman.styles %>/**/*.css'], 124 | tasks: ['newer:copy:styles', 'autoprefixer', 'newer:copy:tmp'] 125 | }, 126 | gruntfile: { 127 | files: ['Gruntfile.js'], 128 | tasks: ['ngconstant:development', 'newer:copy:app'] 129 | }, 130 | includeSource: { 131 | files: ['<%= yeoman.app %>/index.html'], 132 | tasks: ['includeSource:server'] 133 | }, 134 | sass: { 135 | files: ['<%= yeoman.app %>/<%= yeoman.styles %>/**/*.scss'], 136 | tasks: ['sass:dist', 'newer:copy:styles', 'newer:copy:tmp'] 137 | } 138 | }, 139 | 140 | // The actual grunt server settings 141 | connect: { 142 | options: { 143 | port: 9000, 144 | // Change this to '0.0.0.0' to access the server from outside. 145 | hostname: 'localhost' 146 | }, 147 | dist: { 148 | options: { 149 | base: '<%= yeoman.dist %>' 150 | } 151 | }, 152 | coverage: { 153 | options: { 154 | port: 9002, 155 | open: true, 156 | base: ['coverage'] 157 | } 158 | } 159 | }, 160 | 161 | // Make sure code styles are up to par and there are no obvious mistakes 162 | jshint: { 163 | options: { 164 | jshintrc: '.jshintrc', 165 | reporter: require('jshint-stylish') 166 | }, 167 | all: [ 168 | 'Gruntfile.js', 169 | '<%= yeoman.app %>/<%= yeoman.scripts %>/**/*.js' 170 | ], 171 | test: { 172 | options: { 173 | jshintrc: 'test/.jshintrc' 174 | }, 175 | src: ['test/unit/**/*.js'] 176 | } 177 | }, 178 | 179 | // Empties folders to start fresh 180 | clean: { 181 | dist: { 182 | files: [{ 183 | dot: true, 184 | src: [ 185 | '.temp', 186 | '<%= yeoman.dist %>/*', 187 | '!<%= yeoman.dist %>/.git*' 188 | ] 189 | }] 190 | }, 191 | server: '.temp' 192 | }, 193 | 194 | autoprefixer: { 195 | options: { 196 | browsers: ['last 1 version'] 197 | }, 198 | dist: { 199 | files: [{ 200 | expand: true, 201 | cwd: '.temp/<%= yeoman.styles %>/', 202 | src: '{,*/}*.css', 203 | dest: '.temp/<%= yeoman.styles %>/' 204 | }] 205 | } 206 | }, 207 | 208 | // Automatically inject Bower components into the app 209 | wiredep: { 210 | app: { 211 | src: ['<%= yeoman.app %>/index.html'], 212 | ignorePath: /\.\.\//, 213 | exclude: ['app/bower_components/ionic/release/css/ionic.css', /jquery/, /bower_components\/bootstrap/] 214 | } 215 | }, 216 | sass: { // Task 217 | dist: { // Target 218 | options: { // Target options 219 | style: 'expanded' 220 | }, 221 | files: { // Dictionary of files 222 | '.temp/<%= yeoman.styles %>/main.css': '<%= yeoman.app %>/<%= yeoman.styles %>/main.scss', // 'destination': 'source' 223 | } 224 | } 225 | }, 226 | 227 | // Reads HTML for usemin blocks to enable smart builds that automatically 228 | // concat, minify and revision files. Creates configurations in memory so 229 | // additional tasks can operate on them 230 | useminPrepare: { 231 | html: '<%= yeoman.app %>/index.html', 232 | options: { 233 | dest: '<%= yeoman.dist %>', 234 | staging: '.temp', 235 | flow: { 236 | html: { 237 | steps: { 238 | js: ['concat', 'uglifyjs'], 239 | css: ['cssmin'] 240 | }, 241 | post: {} 242 | } 243 | } 244 | } 245 | }, 246 | 247 | // Performs rewrites based on the useminPrepare configuration 248 | usemin: { 249 | html: ['<%= yeoman.dist %>/**/*.html'], 250 | css: ['<%= yeoman.dist %>/<%= yeoman.styles %>/**/*.css'], 251 | options: { 252 | assetsDirs: ['<%= yeoman.dist %>'] 253 | } 254 | }, 255 | 256 | // The following *-min tasks produce minified files in the dist folder 257 | cssmin: { 258 | options: { 259 | //root: '<%= yeoman.app %>', 260 | noRebase: true 261 | } 262 | }, 263 | htmlmin: { 264 | dist: { 265 | options: { 266 | collapseWhitespace: true, 267 | collapseBooleanAttributes: true, 268 | removeCommentsFromCDATA: true, 269 | removeOptionalTags: true 270 | }, 271 | files: [{ 272 | expand: true, 273 | cwd: '<%= yeoman.dist %>', 274 | src: ['*.html', 'templates/**/*.html'], 275 | dest: '<%= yeoman.dist %>' 276 | }] 277 | } 278 | }, 279 | 280 | // Copies remaining files to places other tasks can use 281 | copy: { 282 | dist: { 283 | files: [{ 284 | expand: true, 285 | dot: true, 286 | cwd: '<%= yeoman.app %>', 287 | dest: '<%= yeoman.dist %>', 288 | src: [ 289 | '<%= yeoman.images %>/**/*.{png,jpg,jpeg,gif,webp,svg}', 290 | '*.html', 291 | 'templates/**/*.html', 292 | 'fonts/*' 293 | ] 294 | }, { 295 | expand: true, 296 | cwd: '.temp/<%= yeoman.images %>', 297 | dest: '<%= yeoman.dist %>/<%= yeoman.images %>', 298 | src: ['generated/*'] 299 | }] 300 | }, 301 | styles: { 302 | expand: true, 303 | cwd: '<%= yeoman.app %>/<%= yeoman.styles %>', 304 | dest: '.temp/<%= yeoman.styles %>/', 305 | src: '{,*/}*.css' 306 | }, 307 | fonts: { 308 | expand: true, 309 | cwd: 'app/bower_components/ionic/release/fonts/', 310 | dest: '<%= yeoman.app %>/fonts/', 311 | src: '*' 312 | }, 313 | vendor: { 314 | expand: true, 315 | cwd: '<%= yeoman.app %>/vendor', 316 | dest: '.temp/<%= yeoman.styles %>/', 317 | src: '{,*/}*.css' 318 | }, 319 | app: { 320 | expand: true, 321 | cwd: '<%= yeoman.app %>', 322 | dest: '<%= yeoman.dist %>/', 323 | src: [ 324 | '**/*', 325 | '!**/*.scss', 326 | ] 327 | }, 328 | tmp: { 329 | expand: true, 330 | cwd: '.temp', 331 | dest: '<%= yeoman.dist %>/', 332 | src: '**/*' 333 | }, 334 | misc: { 335 | expand: true, 336 | cwd: 'misc', 337 | dest: '<%= yeoman.dist %>/misc', 338 | src: ['**/*', '!assets/**', '!**/*.jpg', '!**/*.psd'] 339 | } 340 | }, 341 | 342 | concurrent: { 343 | ionic: { 344 | tasks: [], 345 | options: { 346 | logConcurrentOutput: true 347 | } 348 | }, 349 | server: [ 350 | 'sass:dist', 351 | 'copy:styles', 352 | 'copy:vendor', 353 | 'copy:fonts', 354 | ], 355 | test: [ 356 | 'sass:dist', 357 | 'copy:styles', 358 | 'copy:vendor', 359 | 'copy:fonts', 360 | ], 361 | dist: [ 362 | 'sass:dist', 363 | 'copy:styles', 364 | 'copy:vendor', 365 | 'copy:fonts', 366 | ] 367 | }, 368 | 369 | // By default, your `index.html`'s will take care of 370 | // minification. These next options are pre-configured if you do not wish 371 | // to use the Usemin blocks. 372 | // cssmin: { 373 | // dist: { 374 | // files: { 375 | // '<%= yeoman.dist %>/<%= yeoman.styles %>/main.css': [ 376 | // '.temp/<%= yeoman.styles %>/**/*.css', 377 | // '<%= yeoman.app %>/<%= yeoman.styles %>/**/*.css' 378 | // ] 379 | // } 380 | // } 381 | // }, 382 | // uglify: { 383 | // dist: { 384 | // files: { 385 | // '<%= yeoman.dist %>/<%= yeoman.scripts %>/scripts.js': [ 386 | // '<%= yeoman.dist %>/<%= yeoman.scripts %>/scripts.js' 387 | // ] 388 | // } 389 | // } 390 | // }, 391 | // concat: { 392 | // dist: {} 393 | // }, 394 | 395 | // Test settings 396 | // These will override any config options in karma.conf.js if you create it. 397 | karma: { 398 | options: { 399 | basePath: '', 400 | frameworks: ['mocha', 'chai'], 401 | files: [ 402 | '<%= yeoman.app %>/bower_components/angular/angular.js', 403 | '<%= yeoman.app %>/bower_components/angular-mocks/angular-mocks.js', 404 | '<%= yeoman.app %>/bower_components/angular-animate/angular-animate.js', 405 | '<%= yeoman.app %>/bower_components/angular-sanitize/angular-sanitize.js', 406 | '<%= yeoman.app %>/bower_components/angular-ui-router/release/angular-ui-router.js', 407 | '<%= yeoman.app %>/bower_components/ionic/release/js/ionic.js', 408 | '<%= yeoman.app %>/bower_components/ionic/release/js/ionic-angular.js', 409 | '<%= yeoman.app %>/<%= yeoman.scripts %>/**/*.js', 410 | '<%= yeoman.test %>/mock/**/*.js', 411 | '<%= yeoman.test %>/spec/**/*.js' 412 | ], 413 | autoWatch: false, 414 | reporters: ['dots', 'coverage'], 415 | port: 8080, 416 | singleRun: false, 417 | preprocessors: { 418 | // Update this if you change the yeoman config path 419 | '<%= yeoman.app %>/<%= yeoman.scripts %>/**/*.js': ['coverage'] 420 | }, 421 | coverageReporter: { 422 | reporters: [{ 423 | type: 'html', 424 | dir: 'coverage/' 425 | }, { 426 | type: 'text-summary' 427 | }] 428 | } 429 | }, 430 | unit: { 431 | // Change this to 'Chrome', 'Firefox', etc. Note that you will need 432 | // to install a karma launcher plugin for browsers other than Chrome. 433 | browsers: ['PhantomJS'], 434 | background: true 435 | }, 436 | continuous: { 437 | browsers: ['PhantomJS'], 438 | singleRun: true, 439 | } 440 | }, 441 | 442 | // ngAnnotate tries to make the code safe for minification automatically by 443 | // using the Angular long form for dependency injection. 444 | ngAnnotate: { 445 | dist: { 446 | files: [{ 447 | expand: true, 448 | cwd: '.temp/concat/<%= yeoman.scripts %>', 449 | src: '*.js', 450 | dest: '.temp/concat/<%= yeoman.scripts %>' 451 | }] 452 | } 453 | } 454 | 455 | }); 456 | 457 | // Register tasks for all Cordova commands 458 | _.functions(cordovaCli).forEach(function(name) { 459 | grunt.registerTask(name, function() { 460 | this.args.unshift(name.replace('cordova:', '')); 461 | // Handle URL's being split up by Grunt because of `:` characters 462 | if (_.contains(this.args, 'http') || _.contains(this.args, 'https')) { 463 | this.args = this.args.slice(0, -2).concat(_.last(this.args, 2).join(':')); 464 | } 465 | var done = this.async(); 466 | var exec = process.platform === 'win32' ? 'cordova.cmd' : 'cordova'; 467 | var cmd = path.resolve('./node_modules/cordova/bin', exec); 468 | var flags = process.argv.splice(3); 469 | var child = spawn(cmd, this.args.concat(flags)); 470 | child.stdout.on('data', function(data) { 471 | grunt.log.writeln(data); 472 | }); 473 | child.stderr.on('data', function(data) { 474 | grunt.log.error(data); 475 | }); 476 | child.on('close', function(code) { 477 | code = code ? false : true; 478 | done(code); 479 | }); 480 | }); 481 | }); 482 | 483 | // Since Apache Ripple serves assets directly out of their respective platform 484 | // directories, we watch all registered files and then copy all un-built assets 485 | // over to <%= yeoman.dist %>/. Last step is running cordova prepare so we can refresh the ripple 486 | // browser tab to see the changes. Technically ripple runs `cordova prepare` on browser 487 | // refreshes, but at this time you would need to re-run the emulator to see changes. 488 | grunt.registerTask('ripple', ['wiredep', 'newer:copy:app', 'ripple-emulator']); 489 | grunt.registerTask('ripple-emulator', function() { 490 | grunt.config.set('watch', { 491 | all: { 492 | files: _.flatten(_.pluck(grunt.config.get('watch'), 'files')), 493 | tasks: ['newer:copy:app', 'prepare'] 494 | } 495 | }); 496 | 497 | var cmd = path.resolve('./node_modules/ripple-emulator/bin', 'ripple'); 498 | var child = spawn(cmd, ['emulate']); 499 | child.stdout.on('data', function(data) { 500 | grunt.log.writeln(data); 501 | }); 502 | child.stderr.on('data', function(data) { 503 | grunt.log.error(data); 504 | }); 505 | process.on('exit', function(code) { 506 | child.kill('SIGINT'); 507 | process.exit(code); 508 | }); 509 | 510 | return grunt.task.run(['watch']); 511 | }); 512 | 513 | // Dynamically configure `karma` target of `watch` task so that 514 | // we don't have to run the karma test server as part of `grunt serve` 515 | grunt.registerTask('watch:karma', function() { 516 | var karma = { 517 | files: ['<%= yeoman.app %>/<%= yeoman.scripts %>/**/*.js', '<%= yeoman.test %>/spec/**/*.js'], 518 | tasks: ['newer:jshint:test', 'karma:unit:run'] 519 | }; 520 | grunt.config.set('watch', karma); 521 | return grunt.task.run(['watch']); 522 | }); 523 | 524 | // Wrap ionic-cli commands 525 | grunt.registerTask('ionic', function() { 526 | var done = this.async(); 527 | var script = path.resolve('./node_modules/ionic/bin/', 'ionic'); 528 | var flags = process.argv.splice(3); 529 | var child = spawn(script, this.args.concat(flags), { 530 | stdio: 'inherit' 531 | }); 532 | child.on('close', function(code) { 533 | code = code ? false : true; 534 | done(code); 535 | }); 536 | }); 537 | 538 | grunt.registerTask('test', [ 539 | 'wiredep', 540 | 'clean', 541 | 'concurrent:test', 542 | 'autoprefixer', 543 | 'karma:unit:start', 544 | 'watch:karma' 545 | ]); 546 | 547 | grunt.registerTask('serve', function(target) { 548 | if (target === 'compress') { 549 | return grunt.task.run(['compress', 'ionic:serve']); 550 | } 551 | 552 | grunt.config('concurrent.ionic.tasks', ['ionic:serve', 'watch']); 553 | grunt.task.run(['wiredep', 'init', 'concurrent:ionic']); 554 | }); 555 | grunt.registerTask('emulate', function() { 556 | grunt.config('concurrent.ionic.tasks', ['ionic:emulate:' + this.args.join(), 'watch']); 557 | return grunt.task.run(['init', 'concurrent:ionic']); 558 | }); 559 | grunt.registerTask('run', function() { 560 | grunt.config('concurrent.ionic.tasks', ['ionic:run:' + this.args.join(), 'watch']); 561 | return grunt.task.run(['init', 'concurrent:ionic']); 562 | }); 563 | grunt.registerTask('build', function() { 564 | return grunt.task.run(['init', 'ionic:build:' + this.args.join()]); 565 | }); 566 | 567 | grunt.registerTask('init', [ 568 | 'clean', 569 | 'includeSource:dist', 570 | 'ngconstant:development', 571 | 'wiredep', 572 | 'concurrent:server', 573 | 'autoprefixer', 574 | 'newer:copy:app', 575 | 'newer:copy:tmp', 576 | 'newer:copy:misc' 577 | ]); 578 | 579 | 580 | grunt.registerTask('compress', [ 581 | 'clean', 582 | 'ngconstant:production', 583 | 'wiredep', 584 | 'useminPrepare', 585 | 'concurrent:dist', 586 | 'autoprefixer', 587 | 'concat', 588 | 'ngAnnotate', 589 | 'copy:dist', 590 | 'cssmin', 591 | 'uglify', 592 | 'usemin', 593 | 'htmlmin' 594 | ]); 595 | 596 | grunt.registerTask('coverage', ['karma:continuous', 597 | 'connect:coverage:keepalive' 598 | ]); 599 | 600 | grunt.registerTask('default', [ 601 | 'wiredep', 602 | 'newer:jshint', 603 | 'karma:continuous', 604 | 'compress' 605 | ]); 606 | }; 607 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Stavros Kounis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Supermodular Ionic 3 | A super modular Ionic starter application. 4 | 5 | * Project's Home: https://github.com/skounis/supermodular 6 | 7 | > Are you interesting in **Ionic 2**? 8 | > * Check our [Supermodular 2](https://github.com/skounis/supermodular2) starter kit 9 | 10 | ## Dependecies, Run and Build 11 | 12 | ### Install NodeJS dependencies 13 | 14 | Run `npm install` to install all needed dependencies. 15 | 16 | ### Install Plugins and Javascript dependencies 17 | #### Linux/MacOX 18 | Run `./install.sh` to install all needed plugins and dependencies 19 | 20 | #### Windows Users 21 | Similarly, Windows users should run `install.bat`. 22 | 23 | ### Run the app 24 | Use `grunt serve -l` to run the app in browser and watch for changes in code 25 | 26 | or 27 | 28 | use `grunt serve` to just run the app for a browser preview 29 | 30 | or 31 | 32 | use `grunt serve --lab` to run the app in a browser on two platforms at the same time. 33 | 34 | ### Add a platform 35 | 36 | ```bash 37 | $ grunt platform:add: 38 | ``` 39 | 40 | Supported Cordova platforms: 41 | 42 | ```bash 43 | $ grunt platform:add:ios 44 | $ grunt platform:add:android 45 | ``` 46 | 47 | ### Build the app 48 | 49 | ```bash 50 | $ grunt build 51 | ``` 52 | 53 | ### Εmulate the app on simulator 54 | iOS: 55 | 56 | ```bash 57 | $ grunt emulate:ios 58 | ``` 59 | 60 | Android: 61 | 62 | ```bash 63 | $ grunt emulate:android 64 | ``` 65 | 66 | For more information, see [Ionic Framework Generator's instructions](https://github.com/diegonetto/generator-ionic). 67 | 68 | ### Plugins installation 69 | 70 | Use the following commands and install all the plugins required by the app: 71 | ```bash 72 | $ cordova plugin add {plugin id or url} 73 | ``` 74 | 75 | eg: 76 | 77 | ```bash 78 | cordova plugin add cordova-plugin-inappbrowser 79 | ``` 80 | 81 | #### Used Cordova plugins 82 | In case that the required Cordova plugins are not installed while installing NodeJS dependencies, Cordova's command mentioned previously can be used to install the following plugins: 83 | 84 | * **cordova-plugin-device** - This plugin defines a global device object, which describes the device's hardware and software. 85 | * **cordova-plugin-console** - This plugin is meant to ensure that console.log() is as useful as it can be. It adds additional function for iOS, Ubuntu, Windows Phone 8, and Windows. 86 | * **com.ionic.keyboard** - It provides functions to make interacting with the keyboard easier, and fires events to indicate that the keyboard will hide/show. 87 | * **cordova-plugin-inappbrowser** - Provides a web browser view. It could be used to open images, access web pages, and open PDF files. 88 | * **cordova-plugin-geolocation** - Grab the current location of the user, or grab continuous location changes 89 | * **nl.x-services.plugins.socialsharing** - Share images, text, messages via Facebook, Twitter, Email, SMS, WhatsApp, etc using this plugin (https://github.com/EddyVerbruggen/SocialSharing-PhoneGap-Plugin.git). 90 | * **de.appplant.cordova.plugin.email-composer** - The plugin provides access to the standard interface that manages the editing and sending an email message. 91 | * **cordova-plugin-network-information** - This plugin provides an implementation of an old version of the Network Information API. It provides information about the device's cellular and wifi connection, and whether the device has an internet connection. 92 | * **cordova-plugin-whitelist** - This plugin implements a whitelist policy for navigating the application webview on Cordova 4.0 93 | * **cordova-plugin-transport-security** - Cordova / PhoneGap Plugin to allow 'Arbitrary Loads' by adding a declaration to the Info.plist file to bypass the iOS 9 App Transport Security 94 | 95 | ## Branches naming convention 96 | Each branch is related to the Ionic framework version the source code is based on. Currently, there are the following branches: 97 | 1. `master`: Main development source code 98 | 2. `1.1-1.x`: Source code maintenance based on Ionic 1.1.x 99 | 100 | ## Credits 101 | 102 | * [Yeoman](http://yeoman.io/) 103 | * [Yeoman's Ionic Framework generator](https://github.com/diegonetto/generator-ionic) 104 | 105 | ## Third Party Licences 106 | * [Apache License](http://www.apache.org/licenses/) 107 | * [MIT License](https://opensource.org/licenses/MIT) 108 | -------------------------------------------------------------------------------- /app/README.md: -------------------------------------------------------------------------------- 1 | This is an addon starter template for the [Ionic Framework](http://ionicframework.com/). 2 | 3 | ## How to use this template 4 | 5 | *This template does not work on its own*. It is missing the Ionic library, and AngularJS. 6 | 7 | To use this, either create a new ionic project using the ionic node.js utility, or copy and paste this into an existing Cordova project and download a release of Ionic separately. 8 | 9 | ### With the Ionic tool: 10 | 11 | Take the name after `ionic-starter-`, and that is the name of the template to be used when using the `ionic start` command below: 12 | 13 | ```bash 14 | $ sudo npm install -g ionic cordova 15 | $ ionic start myApp sidemenu 16 | ``` 17 | 18 | Then, to run it, cd into `myApp` and run: 19 | 20 | ```bash 21 | $ ionic platform add ios 22 | $ ionic build ios 23 | $ ionic emulate ios 24 | ``` 25 | 26 | Substitute ios for android if not on a Mac, but if you can, the ios development toolchain is a lot easier to work with until you need to do anything custom to Android. 27 | 28 | ## Demo 29 | http://plnkr.co/edit/0RXSDB?p=preview 30 | 31 | ## Issues 32 | Issues have been disabled on this repo, if you do find an issue or have a question consider posting it on the [Ionic Forum](http://forum.ionicframework.com/). Or else if there is truly an error, follow our guidelines for [submitting an issue](http://ionicframework.com/contribute/#issues) to the main Ionic repository. On the other hand, pull requests are welcome here! 33 | -------------------------------------------------------------------------------- /app/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/app/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /app/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/app/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /app/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/app/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /app/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/app/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /app/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/app/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /app/fonts/ionicons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/app/fonts/ionicons.eot -------------------------------------------------------------------------------- /app/fonts/ionicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/app/fonts/ionicons.ttf -------------------------------------------------------------------------------- /app/fonts/ionicons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/app/fonts/ionicons.woff -------------------------------------------------------------------------------- /app/images/cards/ben.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/app/images/cards/ben.png -------------------------------------------------------------------------------- /app/images/cards/face-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/app/images/cards/face-1.jpg -------------------------------------------------------------------------------- /app/images/cards/face-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/app/images/cards/face-2.jpg -------------------------------------------------------------------------------- /app/images/cards/face-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/app/images/cards/face-3.jpg -------------------------------------------------------------------------------- /app/images/cards/face-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/app/images/cards/face-4.jpg -------------------------------------------------------------------------------- /app/images/cards/face-5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/app/images/cards/face-5.jpg -------------------------------------------------------------------------------- /app/images/cards/face-6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/app/images/cards/face-6.jpg -------------------------------------------------------------------------------- /app/images/cards/face-7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/app/images/cards/face-7.jpg -------------------------------------------------------------------------------- /app/images/cards/max.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/app/images/cards/max.jpg -------------------------------------------------------------------------------- /app/images/cards/perry.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/app/images/cards/perry.jpg -------------------------------------------------------------------------------- /app/images/ionic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/app/images/ionic.png -------------------------------------------------------------------------------- /app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /app/scripts/app.js: -------------------------------------------------------------------------------- 1 | // Ionic Starter App 2 | 3 | // angular.module is a global place for creating, registering and retrieving Angular modules 4 | // 'starter' is the name of this angular module example (also set in a attribute in index.html) 5 | // the 2nd parameter is an array of 'requires' 6 | // 'starter.controllers' is found in controllers.js 7 | angular.module('starter', [ 8 | 'ionic', 9 | 'ionic.service.core', 10 | 'config', 11 | 'ionic.service.core', 12 | 'ionic.service.push', 13 | 'supermodular.common', 14 | 'supermodular.home', 15 | 'supermodular.map', 16 | 'supermodular.wordpress', 17 | 'supermodular.menu', 18 | 'supermodular.elements', 19 | 'supermodular.popover-menu', 20 | 'supermodular.native-scrolling', 21 | 'supermodular.new-slide-box', 22 | 'gMaps', 23 | 'ngCordova' 24 | ]) 25 | 26 | .value('_', window._) 27 | 28 | .run(function($ionicPlatform) { 29 | $ionicPlatform.ready(function() { 30 | // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard 31 | // for form inputs) 32 | 33 | if (window.cordova && window.cordova.plugins.Keyboard) { 34 | window.cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true); 35 | } 36 | if (window.StatusBar) { 37 | // org.apache.cordova.statusbar required 38 | StatusBar.styleDefault(); 39 | } 40 | }); 41 | }) 42 | 43 | .config(function($urlRouterProvider, $compileProvider) { 44 | $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|file|blob|cdvfile|content):|data:image\//); 45 | // if none of the above states are matched, use this as the fallback 46 | $urlRouterProvider.otherwise('/app/home'); 47 | }); 48 | -------------------------------------------------------------------------------- /app/scripts/common/common.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.common', ['ionic']); 6 | })(); 7 | -------------------------------------------------------------------------------- /app/scripts/common/directives/gmaps/gmaps.directive.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | angular.module('gMaps', []) 3 | 4 | /** 5 | * Handle Google Maps API V3+ 6 | */ 7 | // - Documentation: https://developers.google.com/maps/documentation/ 8 | .directive('gmaps', function($window) { 9 | 10 | return { 11 | restrict: 'E', 12 | replace: true, 13 | template: '
', 14 | scope: { 15 | center: '=', // Center point on the map (e.g. { latitude: 10, longitude: 10 }). 16 | markers: '=', // Array of map markers (e.g. [{ lat: 10, lon: 10, name: 'hello' }]). 17 | width: '@', // Map width in pixels. 18 | height: '@', // Map height in pixels. 19 | zoom: '=', // Zoom level (one is totally zoomed out, 25 is very much zoomed in). 20 | mapTypeId: '@', // Type of tile to show on the map (roadmap, satellite, hybrid, terrain). 21 | panControl: '@', // Whether to show a pan control on the map. 22 | zoomControl: '@', // Whether to show a zoom control on the map. 23 | scaleControl: '@' // Whether to show scale control on the map. 24 | }, 25 | link: function(scope, element, attrs) { 26 | var toResize, toCenter; 27 | var map; 28 | var infowindow; 29 | var currentMarkers; 30 | var callbackName = 'InitMapCb'; 31 | var google; 32 | 33 | // callback when google maps is loaded 34 | $window[callbackName] = function() { 35 | google = window.google; 36 | console.log('map: init callback'); 37 | createMap(); 38 | updateMarkers(); 39 | }; 40 | 41 | if (!$window.google || !$window.google.maps) { 42 | console.log('map: not available - load now gmap js'); 43 | loadGMaps(); 44 | } else { 45 | console.log('map: IS available - create only map now'); 46 | google = window.google; 47 | createMap(); 48 | } 49 | 50 | function loadGMaps() { 51 | console.log('map: start loading js gmaps'); 52 | var script = $window.document.createElement('script'); 53 | script.type = 'text/javascript'; 54 | script.src = 'http://maps.googleapis.com/maps/api/js?v=3.exp&sensor=true&callback=InitMapCb'; 55 | $window.document.body.appendChild(script); 56 | } 57 | 58 | function createMap() { 59 | console.log('map: create map start'); 60 | var c = scope.center; 61 | var mapOptions = { 62 | zoom: scope.zoom || 10, 63 | center: new google.maps.LatLng(c.lat, c.lon), 64 | mapTypeId: google.maps.MapTypeId.ROADMAP, 65 | panControl: true, 66 | zoomControl: true, 67 | mapTypeControl: true, 68 | scaleControl: false, 69 | streetViewControl: false, 70 | navigationControl: true, 71 | disableDefaultUI: true, 72 | overviewMapControl: true 73 | }; 74 | if (!(map instanceof google.maps.Map)) { 75 | console.log('map: create map now as not already available '); 76 | map = new google.maps.Map(element[0], mapOptions); 77 | // EDIT Added this and it works on android now 78 | // Stop the side bar from dragging when mousedown/tapdown on the map 79 | google.maps.event.addDomListener(element[0], 'mousedown', function(e) { 80 | e.preventDefault(); 81 | return false; 82 | }); 83 | infowindow = new google.maps.InfoWindow({ 84 | disableAutoPan: true 85 | }); 86 | } 87 | } 88 | 89 | scope.$watch('markers', function() { 90 | updateMarkers(); 91 | }); 92 | 93 | // Info window trigger function 94 | function onItemClick(pin, label) { 95 | // Create content 96 | var contentString = label; 97 | // Replace our Info Window's content and position 98 | infowindow.setContent(contentString); 99 | infowindow.setPosition(pin.position); 100 | infowindow.open(map); 101 | google.maps.event.addListener(infowindow, 'closeclick', function() { 102 | //console.log('map: info windows close listener triggered '); 103 | infowindow.close(); 104 | }); 105 | } 106 | 107 | function markerCb(marker, member, location) { 108 | return function() { 109 | //console.log('map: marker listener for ' + member.name); 110 | // var href = 'http://maps.apple.com/?q=' + member.lat + ',' + member.lon; 111 | // map.setCenter(location); 112 | onItemClick(marker, member.name); 113 | }; 114 | } 115 | 116 | // update map markers to match scope marker collection 117 | function updateMarkers() { 118 | if (map && scope.markers) { 119 | // create new markers 120 | //console.log('map: make markers '); 121 | currentMarkers = []; 122 | var markers = scope.markers; 123 | if (angular.isString(markers)) { 124 | markers = scope.$eval(scope.markers); 125 | } 126 | for (var i = 0; i < markers.length; i++) { 127 | var m = markers[i]; 128 | var loc = new google.maps.LatLng(m.lat, m.lon); 129 | var mm = new google.maps.Marker({ 130 | position: loc, 131 | map: map, 132 | title: m.name 133 | }); 134 | //console.log('map: make marker for ' + m.name); 135 | google.maps.event.addListener(mm, 'click', markerCb(mm, m, loc)); 136 | currentMarkers.push(mm); 137 | } 138 | } 139 | } 140 | 141 | // convert current location to Google maps location 142 | function getLocation(loc) { 143 | if (loc == null) { 144 | return new google.maps.LatLng(40, -73); 145 | } 146 | if (angular.isString(loc)) { 147 | loc = scope.$eval(loc); 148 | } 149 | return new google.maps.LatLng(loc.lat, loc.lon); 150 | } 151 | 152 | } // end of link: 153 | }; // end of return 154 | }); 155 | -------------------------------------------------------------------------------- /app/scripts/common/services/extenal-apps.service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.common') 6 | .factory('externalAppsService', externalAppsService); 7 | 8 | externalAppsService.$inject = ['$window']; 9 | 10 | /* @ngInject */ 11 | function externalAppsService($window) { 12 | var service = { 13 | openMapsApp: openMapsApp, 14 | openExternalUrl: openExternalUrl 15 | }; 16 | return service; 17 | 18 | // ****************************************************** 19 | 20 | function openMapsApp(coords) { 21 | var q; 22 | if (ionic.Platform.isAndroid()) { 23 | q = 'geo:' + coords; 24 | } else { 25 | q = 'maps://maps.apple.com/?q=' + coords; 26 | } 27 | $window.location.href = q; 28 | } 29 | 30 | function openExternalUrl(url) { 31 | $window.open(url, '_system', 'location=yes'); 32 | return false; 33 | } 34 | } 35 | })(); 36 | -------------------------------------------------------------------------------- /app/scripts/common/services/html-to-plain-text.service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.common') 6 | .factory('htmlToPlainText', htmlToPlainText); 7 | 8 | htmlToPlainText.$inject = []; 9 | 10 | /* @ngInject */ 11 | function htmlToPlainText() { 12 | return function(text) { 13 | return String(text).replace(/<[^>]+>/gm, ''); 14 | }; 15 | } 16 | })(); 17 | -------------------------------------------------------------------------------- /app/scripts/config/internet-connectivity.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('starter') 6 | .config(function($httpProvider) { 7 | $httpProvider.interceptors.push(function($cordovaNetwork, $q, $rootScope, $injector) { 8 | return { 9 | request: function(config) { 10 | if (!ionic.Platform.isReady) { 11 | return config; 12 | } 13 | 14 | if (config.url.indexOf('http') !== 0) { 15 | return config; 16 | } 17 | 18 | var isOnline = getNetworkStatus(); 19 | 20 | if (isOnline) { 21 | return config; 22 | } 23 | 24 | var $ionicPopup = $injector.get('$ionicPopup'); 25 | var alertPopup = $ionicPopup.alert({ 26 | title: 'Alert', 27 | template: 'There is no internet connection' 28 | }); 29 | 30 | return $q.reject('No internet connection'); 31 | }, 32 | response: function(response) { 33 | return response; 34 | } 35 | }; 36 | 37 | function getNetworkStatus() { 38 | 39 | // On Android and when only the 3G interface is on 40 | // the return connection type is `unknown` even the device is online. 41 | // To work around this we will assume that only Connection.NONE 42 | // is declaring an offline device. Which is returned when data are 43 | // disabled. 44 | 45 | var isPluginAvailable = !!navigator.connection; 46 | 47 | if (isPluginAvailable) { 48 | var networkState = JSON.stringify(navigator.connection); //.type 49 | console.log('Internet connectivity chech. NetworkState: ' + networkState); 50 | 51 | // HACK: this is a temporary hack due to Android 3G related issue 52 | // described above. 53 | if (navigator.connection.type.toLowerCase() == 'unknown'){ 54 | return true; 55 | }else { 56 | return $cordovaNetwork.isOnline(); 57 | } 58 | } 59 | 60 | return navigator.onLine; 61 | } 62 | }); 63 | }); 64 | })(); 65 | -------------------------------------------------------------------------------- /app/scripts/config/spinner.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('starter') 6 | .config(function($httpProvider) { 7 | $httpProvider.interceptors.push(function($rootScope, $q) { 8 | return { 9 | request: function(config) { 10 | $rootScope.$broadcast('loading:show'); 11 | return config; 12 | }, 13 | response: function(response) { 14 | $rootScope.$broadcast('loading:hide'); 15 | return response; 16 | }, 17 | requestError: function(rejectReason) { 18 | $rootScope.$broadcast('loading:hide'); 19 | return $q.reject(rejectReason); 20 | }, 21 | responseError: function(rejectReason) { 22 | $rootScope.$broadcast('loading:hide'); 23 | return $q.reject(rejectReason); 24 | } 25 | }; 26 | }); 27 | }) 28 | .run(function($rootScope, $ionicLoading) { 29 | $rootScope.$on('loading:show', function() { 30 | $ionicLoading.show({}); 31 | }); 32 | 33 | $rootScope.$on('loading:hide', function() { 34 | $ionicLoading.hide(); 35 | }); 36 | }); 37 | })(); -------------------------------------------------------------------------------- /app/scripts/elements/checkbox.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
    5 |
  • 6 | 9 | Flux Capacitor 10 |
  • 11 |
  • 12 | 15 | 1.21 Gigawatts 16 |
  • 17 |
  • 18 | 21 | Delorean 22 |
  • 23 |
  • 24 | 27 | 88 MPH 28 |
  • 29 |
  • 30 | 33 | Plutonium Resupply 34 |
  • 35 |
36 | 37 |
38 |
39 | -------------------------------------------------------------------------------- /app/scripts/elements/elements.controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.elements') 6 | .controller('ElementsController', ElementsController); 7 | 8 | ElementsController.$inject = ['menuItems']; 9 | 10 | /* @ngInject */ 11 | function ElementsController(menuItems) { 12 | var vm = angular.extend(this, { 13 | //TODO: add methods and properties to this controller 14 | }); 15 | 16 | } 17 | })(); 18 | -------------------------------------------------------------------------------- /app/scripts/elements/elements.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /app/scripts/elements/elements.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.elements', [ 6 | 'ionic', 7 | 'ngCordova' 8 | ]) 9 | .config(function($stateProvider) { 10 | $stateProvider 11 | .state('app.elements', { 12 | url: '/elements', 13 | views: { 14 | 'menuContent': { 15 | templateUrl: 'scripts/elements/elements.html', 16 | controller: 'ElementsController as vm' 17 | } 18 | } 19 | }) 20 | .state('app.elements-form-placeholder-labels', { 21 | url: '/elements-form-placeholder-labels', 22 | views: { 23 | 'menuContent': { 24 | templateUrl: 'scripts/elements/form-placeholder-labels.html' 25 | } 26 | } 27 | }) 28 | .state('app.elements-form-inline-labels', { 29 | url: '/elements-form-inline-labels', 30 | views: { 31 | 'menuContent': { 32 | templateUrl: 'scripts/elements/form-inline-labels.html' 33 | } 34 | } 35 | }) 36 | .state('app.elements-form-stacked-labels', { 37 | url: '/elements-form-stacked-labels', 38 | views: { 39 | 'menuContent': { 40 | templateUrl: 'scripts/elements/form-stacked-labels.html' 41 | } 42 | } 43 | }) 44 | .state('app.elements-form-floating-labels', { 45 | url: '/elements-form-floating-labels', 46 | views: { 47 | 'menuContent': { 48 | templateUrl: 'scripts/elements/form-floating-labels.html' 49 | } 50 | } 51 | }) 52 | .state('app.elements-form-inset-form', { 53 | url: '/elements-form-inset-form', 54 | views: { 55 | 'menuContent': { 56 | templateUrl: 'scripts/elements/form-inset-form.html' 57 | } 58 | } 59 | }) 60 | .state('app.elements-form-inset-inputs', { 61 | url: '/elements-form-inset-inputs', 62 | views: { 63 | 'menuContent': { 64 | templateUrl: 'scripts/elements/form-inset-inputs.html' 65 | } 66 | } 67 | }) 68 | .state('app.elements-form-input-icons', { 69 | url: '/elements-form-input-icons', 70 | views: { 71 | 'menuContent': { 72 | templateUrl: 'scripts/elements/form-input-icons.html' 73 | } 74 | } 75 | }) 76 | .state('app.elements-toggle', { 77 | url: '/elements-toggle', 78 | views: { 79 | 'menuContent': { 80 | templateUrl: 'scripts/elements/toggle.html' 81 | } 82 | } 83 | }) 84 | .state('app.elements-checkbox', { 85 | url: '/elements-checkbox', 86 | views: { 87 | 'menuContent': { 88 | templateUrl: 'scripts/elements/checkbox.html' 89 | } 90 | } 91 | }) 92 | .state('app.elements-radiobuttons', { 93 | url: '/elements-radiobuttons', 94 | views: { 95 | 'menuContent': { 96 | templateUrl: 'scripts/elements/radiobuttons.html' 97 | } 98 | } 99 | }) 100 | .state('app.elements-range', { 101 | url: '/elements-range', 102 | views: { 103 | 'menuContent': { 104 | templateUrl: 'scripts/elements/range.html' 105 | } 106 | } 107 | }) 108 | .state('app.elements-select', { 109 | url: '/elements-select', 110 | views: { 111 | 'menuContent': { 112 | templateUrl: 'scripts/elements/select.html' 113 | } 114 | } 115 | }) 116 | .state('app.elements-tabs-icononly', { 117 | url: '/elements-tabs-icononly', 118 | views: { 119 | 'menuContent': { 120 | templateUrl: 'scripts/elements/tabs-icononly.html' 121 | } 122 | } 123 | }) 124 | .state('app.elements-tabs-topicon', { 125 | url: '/elements-tabs-topicon', 126 | views: { 127 | 'menuContent': { 128 | templateUrl: 'scripts/elements/tabs-topicon.html' 129 | } 130 | } 131 | }) 132 | .state('app.elements-tabs-lefticon', { 133 | url: '/elements-tabs-lefticon', 134 | views: { 135 | 'menuContent': { 136 | templateUrl: 'scripts/elements/tabs-lefticon.html' 137 | } 138 | } 139 | }) 140 | .state('app.elements-tabs-striped', { 141 | url: '/elements-tabs-striped', 142 | views: { 143 | 'menuContent': { 144 | templateUrl: 'scripts/elements/tabs-striped.html' 145 | } 146 | } 147 | }); 148 | }); 149 | })(); 150 | -------------------------------------------------------------------------------- /app/scripts/elements/form-floating-labels.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 8 | 12 | 16 |
17 |
18 | 19 |
20 |
21 |
22 | -------------------------------------------------------------------------------- /app/scripts/elements/form-inline-labels.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 8 | 12 |
13 |
14 | 15 |
16 |
17 |
18 | -------------------------------------------------------------------------------- /app/scripts/elements/form-input-icons.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 8 |
9 |
10 |
11 | -------------------------------------------------------------------------------- /app/scripts/elements/form-inset-form.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 7 | 10 |
11 |
12 | 13 |
14 |
15 |
16 | -------------------------------------------------------------------------------- /app/scripts/elements/form-inset-inputs.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 | 6 |
7 | 10 | 13 |
14 | 15 |
16 | 17 |
18 |
19 | -------------------------------------------------------------------------------- /app/scripts/elements/form-placeholder-labels.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 7 | 10 | 13 |
14 |
15 | 16 |
17 |
18 |
19 | -------------------------------------------------------------------------------- /app/scripts/elements/form-stacked-labels.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 8 | 12 | 16 |
17 |
18 | 19 |
20 |
21 |
22 | -------------------------------------------------------------------------------- /app/scripts/elements/radiobuttons.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 | 6 | 13 | 14 | 21 | 22 | 29 | 30 | 37 | 38 | 45 | 46 | 53 | 54 |
55 | 56 |
57 |
58 | -------------------------------------------------------------------------------- /app/scripts/elements/range.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 | 6 | 7 | 8 |
9 | 10 |
11 |
12 | Ranges In A List 13 |
14 |
15 | 16 | 17 | 18 |
19 |
20 | 21 | 22 | 23 |
24 |
25 | 26 | 27 | 28 |
29 |
30 | 31 | 32 | 33 |
34 |
35 | 36 | 37 | 38 |
39 |
40 | 41 | 42 | 43 |
44 |
45 | 46 | 47 | 48 |
49 |
50 | 51 |
52 |
53 | -------------------------------------------------------------------------------- /app/scripts/elements/select.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 | 6 |
7 |
8 | Lightsaber 9 |
10 | 15 |
16 | 17 |
18 |
19 | Fighter 20 |
21 | 30 |
31 | 32 |
33 |
34 | Droid 35 |
36 | 44 |
45 | 46 |
47 |
48 | Planet 49 |
50 | 63 |
64 | 65 |
66 | 67 |
68 |
69 | -------------------------------------------------------------------------------- /app/scripts/elements/tabs-icononly.html: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | -------------------------------------------------------------------------------- /app/scripts/elements/tabs-lefticon.html: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | -------------------------------------------------------------------------------- /app/scripts/elements/tabs-striped.html: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 35 | 36 | -------------------------------------------------------------------------------- /app/scripts/elements/tabs-topicon.html: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | -------------------------------------------------------------------------------- /app/scripts/elements/toggle.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
    5 |
  • 6 | HTML5 7 | 13 |
  • 14 |
  • 15 | CSS3 16 | 22 |
  • 23 |
  • 24 | Flashplayer 25 | 31 |
  • 32 |
  • 33 | Java Applets 34 | 40 |
  • 41 |
  • 42 | JavaScript 43 | 49 |
  • 50 |
  • 51 | Silverlight 52 | 58 |
  • 59 |
  • 60 | Web Components 61 | 67 |
  • 68 |
69 | 70 |
71 |
72 | -------------------------------------------------------------------------------- /app/scripts/home/home-data.service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.home') 6 | .factory('homeDataService', homeDataService); 7 | 8 | homeDataService.$inject = []; 9 | 10 | /* @ngInject */ 11 | function homeDataService() { 12 | return { 13 | phoneNumber: '+306973216110', 14 | email: 'skounis@gmail.com', 15 | officeLocation: '37.7736854,-122.421034', 16 | facebookPage: 'https://www.facebook.com/ionicframework' 17 | }; 18 | } 19 | })(); 20 | -------------------------------------------------------------------------------- /app/scripts/home/home.controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.home') 6 | .controller('HomeController', HomeController); 7 | 8 | HomeController.$inject = ['menuItems', 'homeDataService', 'externalAppsService', '$cordovaEmailComposer']; 9 | 10 | /* @ngInject */ 11 | function HomeController(menuItems, homeDataService, externalAppsService, $cordovaEmailComposer) { 12 | var vm = angular.extend(this, { 13 | entries: menuItems, 14 | phoneNumber: homeDataService.phoneNumber, 15 | getDirections: getDirections, 16 | sendEmail: sendEmail, 17 | openFacebookPage: openFacebookPage 18 | }); 19 | 20 | function getDirections() { 21 | externalAppsService.openMapsApp(homeDataService.officeLocation); 22 | } 23 | 24 | function sendEmail() { 25 | $cordovaEmailComposer.isAvailable().then(function() { 26 | var email = { 27 | to: homeDataService.email, 28 | subject: 'Cordova Icons', 29 | body: 'How are you? Nice greetings from Leipzig' 30 | }; 31 | 32 | $cordovaEmailComposer.open(email); 33 | }); 34 | } 35 | 36 | function openFacebookPage() { 37 | externalAppsService.openExternalUrl(homeDataService.facebookPage); 38 | } 39 | 40 | } 41 | })(); 42 | -------------------------------------------------------------------------------- /app/scripts/home/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
6 |

ABC Corp Inc.

7 | 50 Market Street, San Francisco, California 94103, United States 8 |
9 |
10 | 11 | 15 | 32 | 33 | 54 | 55 |
56 |
57 | -------------------------------------------------------------------------------- /app/scripts/home/home.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.home', [ 6 | 'ionic', 7 | 'ngCordova', 8 | 'supermodular.common' 9 | ]) 10 | .config(function($stateProvider) { 11 | $stateProvider 12 | .state('app.home', { 13 | url: '/home', 14 | views: { 15 | 'menuContent': { 16 | templateUrl: 'scripts/home/home.html', 17 | controller: 'HomeController as vm' 18 | } 19 | } 20 | }); 21 | }); 22 | })(); 23 | -------------------------------------------------------------------------------- /app/scripts/home/menu-items.service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.home') 6 | .factory('menuItems', menuItems); 7 | 8 | menuItems.$inject = []; 9 | 10 | /* @ngInject */ 11 | function menuItems() { 12 | var data = [{ 13 | title: 'PopOver menu', 14 | path: 'popover-menu', 15 | icon: 'ion-ios-arrow-down' 16 | }, { 17 | title: 'Wordpress', 18 | path: 'wordpress-articles', 19 | icon: 'ion-social-wordpress' 20 | }, { 21 | title: 'Elements', 22 | path: 'elements', 23 | icon: 'ion-android-checkbox-outline' 24 | }, { 25 | title: 'Map', 26 | path: 'map', 27 | icon: 'ion-map' 28 | }]; 29 | 30 | return data; 31 | } 32 | })(); 33 | -------------------------------------------------------------------------------- /app/scripts/map/map.controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.map') 6 | .controller('MapController', MapController); 7 | 8 | MapController.$inject = ['$scope', 'mapService']; 9 | 10 | /* @ngInject */ 11 | function MapController($scope, mapService) { 12 | var vm = angular.extend(this, { 13 | origin: { 14 | lat: mapService.origin.latitude, 15 | lon: mapService.origin.longitude 16 | }, 17 | zoom: mapService.zoomLevel, 18 | markers: [] 19 | }); 20 | 21 | var markers = []; 22 | for (var i = 0; i < mapService.annotations.length; i++) { 23 | var annotation = mapService.annotations[i]; 24 | markers.push({ 25 | name: annotation.title, 26 | lat: annotation.latitude, 27 | lon: annotation.longitude 28 | }); 29 | } 30 | vm.markers = markers; 31 | } 32 | })(); 33 | -------------------------------------------------------------------------------- /app/scripts/map/map.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/scripts/map/map.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.map', [ 6 | 'ionic' 7 | ]) 8 | .config(function($stateProvider) { 9 | $stateProvider 10 | 11 | .state('app.map', { 12 | url: '/map', 13 | views: { 14 | 'menuContent': { 15 | templateUrl: 'scripts/map/map.html', 16 | controller: 'MapController as vm' 17 | } 18 | } 19 | }); 20 | }); 21 | })(); 22 | -------------------------------------------------------------------------------- /app/scripts/map/map.service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.map') 6 | .factory('mapService', mapService); 7 | 8 | mapService.$inject = []; 9 | 10 | /* @ngInject */ 11 | function mapService() { 12 | var data = { 13 | origin: { 14 | latitude : 37.407, 15 | longitude : -122.1 16 | }, 17 | zoomLevel: 15, 18 | annotations : [{ 19 | title : 'Molestie et wisi.', 20 | latitude : 37.407, 21 | longitude : -122.1 22 | }, { 23 | title : 'Ullamcorper eros.', 24 | latitude : 37.41, 25 | longitude : -122.1 26 | }] 27 | }; 28 | return data; 29 | } 30 | })(); 31 | -------------------------------------------------------------------------------- /app/scripts/menu/menu.controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.menu') 6 | .controller('MenuController', MenuController); 7 | 8 | MenuController.$inject = []; 9 | 10 | /* @ngInject */ 11 | function MenuController() { 12 | 13 | } 14 | })(); 15 | -------------------------------------------------------------------------------- /app/scripts/menu/menu.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |

Left

19 |
20 | 21 | 22 | 23 | 24 | Home 25 | 26 | 27 | 28 | PopOver menu 29 | 30 | 31 | 32 | Wordpress 33 | 34 | 35 | 36 | Elements 37 | 38 | 39 | 40 | Native scrolling 41 | 42 | 43 | 44 | New slide box 45 | 46 | 47 | 48 | Map 49 | 50 | 51 | 52 |
53 |
54 | -------------------------------------------------------------------------------- /app/scripts/menu/menu.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.menu', [ 6 | 'ionic' 7 | ]) 8 | .config(function($stateProvider) { 9 | $stateProvider 10 | .state('app', { 11 | url: '/app', 12 | abstract: true, 13 | templateUrl: 'scripts/menu/menu.html', 14 | controller: 'MenuController as vm' 15 | }); 16 | }); 17 | })(); 18 | -------------------------------------------------------------------------------- /app/scripts/native-scrolling/native-scrolling.controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.native-scrolling') 6 | .controller('NativeScrollingController', NativeScrollingController); 7 | 8 | NativeScrollingController.$inject = ['nativeScrollingService']; 9 | 10 | /* @ngInject */ 11 | function NativeScrollingController(nativeScrollingService) { 12 | var vm = angular.extend(this, { 13 | items: [] 14 | }); 15 | 16 | (function activate() { 17 | getItems(); 18 | })(); 19 | 20 | // ******************************************************************** 21 | 22 | function getItems() { 23 | nativeScrollingService.getItems(200) 24 | .then(function(items) { 25 | vm.items = items; 26 | }); 27 | } 28 | } 29 | })(); 30 | -------------------------------------------------------------------------------- /app/scripts/native-scrolling/native-scrolling.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{item}} 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/scripts/native-scrolling/native-scrolling.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.native-scrolling', [ 6 | 'ionic', 7 | 'supermodular.common' 8 | ]) 9 | .config(function($stateProvider) { 10 | $stateProvider 11 | .state('app.native-scrolling', { 12 | url: '/native-scrolling', 13 | views: { 14 | 'menuContent': { 15 | templateUrl: 'scripts/native-scrolling/native-scrolling.html', 16 | controller: 'NativeScrollingController as vm' 17 | } 18 | } 19 | }); 20 | }); 21 | })(); 22 | -------------------------------------------------------------------------------- /app/scripts/native-scrolling/native-scrolling.service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.native-scrolling') 6 | .factory('nativeScrollingService', nativeScrollingService); 7 | 8 | nativeScrollingService.$inject = ['$q']; 9 | 10 | /* @ngInject */ 11 | function nativeScrollingService($q) { 12 | var service = { 13 | getItems: getItems 14 | }; 15 | return service; 16 | 17 | // ************************************************************************* 18 | 19 | function getItems(numberOfItems) { 20 | var items = []; 21 | for (var i = 0;i < numberOfItems;i++) { 22 | items.push('Item #' + (i + 1)); 23 | } 24 | return $q.when(items); 25 | } 26 | } 27 | })(); 28 | -------------------------------------------------------------------------------- /app/scripts/new-slide-box/new-slide-box.controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.new-slide-box') 6 | .controller('NewSlideBoxController', NewSlideBoxController); 7 | 8 | NewSlideBoxController.$inject = []; 9 | 10 | /* @ngInject */ 11 | function NewSlideBoxController() { 12 | var vm = angular.extend(this, { 13 | items: getItems(), 14 | options: { 15 | loop: true 16 | } 17 | }); 18 | 19 | // ******************************************************************** 20 | 21 | function getItems() { 22 | var items = []; 23 | for (var i = 1;i <= 7;i++) { 24 | // 25 | // Local stored images 26 | // 27 | // items.push({ 28 | // image: 'images/cards/face-' + i + '.jpg' 29 | // }); 30 | // 31 | // Online images 32 | // 33 | items.push({ 34 | image: 'http://lorempixel.com/786/1024/nightlife/' + i + '/' 35 | }); 36 | } 37 | return items; 38 | } 39 | } 40 | })(); 41 | -------------------------------------------------------------------------------- /app/scripts/new-slide-box/new-slide-box.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/scripts/new-slide-box/new-slide-box.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.new-slide-box', [ 6 | 'ionic', 7 | 'supermodular.common' 8 | ]) 9 | .config(function($stateProvider) { 10 | $stateProvider 11 | .state('app.new-slide-box', { 12 | url: '/new-slide-box', 13 | views: { 14 | 'menuContent': { 15 | templateUrl: 'scripts/new-slide-box/new-slide-box.html', 16 | controller: 'NewSlideBoxController as vm' 17 | } 18 | } 19 | }); 20 | }); 21 | })(); 22 | -------------------------------------------------------------------------------- /app/scripts/popover-menu/popover-menu.controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.popover-menu') 6 | .controller('PopoverMenuController', PopoverMenuController); 7 | 8 | PopoverMenuController.$inject = ['popoverViewService']; 9 | 10 | /* @ngInject */ 11 | function PopoverMenuController(popoverViewService) { 12 | var vm = angular.extend(this, { 13 | showPopover: showPopover 14 | }); 15 | 16 | (function activate() { 17 | })(); 18 | 19 | // ******************************************************************** 20 | 21 | function showPopover(event) { 22 | popoverViewService.show(event).then(function(option) { 23 | alert('You have selected option \'' + option + '\''); 24 | }); 25 | } 26 | } 27 | })(); 28 | -------------------------------------------------------------------------------- /app/scripts/popover-menu/popover-menu.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iusto molestias libero beatae aliquam hic illo minus, vel quo fugiat rem, fugit eaque officia pariatur deleniti temporibus accusantium a dolorum quidem.

9 |
10 |
11 | -------------------------------------------------------------------------------- /app/scripts/popover-menu/popover-menu.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.popover-menu', [ 6 | 'ionic' 7 | ]) 8 | .config(function($stateProvider) { 9 | $stateProvider 10 | .state('app.popover-menu', { 11 | url: '/popover-menu', 12 | views: { 13 | 'menuContent': { 14 | templateUrl: 'scripts/popover-menu/popover-menu.html', 15 | controller: 'PopoverMenuController as vm' 16 | } 17 | } 18 | }); 19 | }); 20 | })(); 21 | -------------------------------------------------------------------------------- /app/scripts/popover-menu/popover-view.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Select an option

4 |
5 | 6 | 7 | 8 |

{{option}}

9 |
10 |
11 |
12 |
-------------------------------------------------------------------------------- /app/scripts/popover-menu/popover-view.service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.popover-menu') 6 | .factory('popoverViewService', popoverViewService); 7 | 8 | popoverViewService.$inject = ['$rootScope', '$ionicPopover', '$q']; 9 | 10 | /* @ngInject */ 11 | function popoverViewService($rootScope, $ionicPopover, $q) { 12 | var scope = createPopover(); 13 | var service = { 14 | show: show 15 | }; 16 | return service; 17 | 18 | // *************************************************** 19 | 20 | function show(event) { 21 | var defer = $q.defer(); 22 | 23 | scope.select = function(option) { 24 | defer.resolve(option); 25 | scope.popover.hide(); 26 | } 27 | 28 | scope.popover.show(event); 29 | return defer.promise; 30 | } 31 | 32 | function createPopover() { 33 | var scope = $rootScope.$new(); 34 | scope.options = ['Red', 'Green', 'Blue', 'White']; 35 | 36 | $ionicPopover.fromTemplateUrl('scripts/popover-menu/popover-view.html', { 37 | scope: scope 38 | }).then(function(popover) { 39 | scope.popover = popover; 40 | }); 41 | 42 | return scope; 43 | } 44 | } 45 | })(); 46 | -------------------------------------------------------------------------------- /app/scripts/wordpress/wordpress-article.controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.wordpress') 6 | .controller('WordpressArticleController', WordpressArticleController); 7 | 8 | WordpressArticleController.$inject = [ 9 | '$stateParams', '$ionicActionSheet', '$cordovaSocialSharing', 'wordpressService']; 10 | 11 | /* @ngInject */ 12 | function WordpressArticleController($stateParams, $ionicActionSheet, $cordovaSocialSharing, wordpressService) { 13 | var articleId = parseInt($stateParams.articleId, 10); 14 | 15 | var vm = angular.extend(this, { 16 | article: null, 17 | share: share 18 | }); 19 | 20 | function activate() { 21 | loadArticle(); 22 | } 23 | activate(); 24 | 25 | // ******************************************************************** 26 | 27 | function share() { 28 | $ionicActionSheet.show({ 29 | buttons: [ 30 | { text: 'Facebook' }, 31 | { text: 'Twitter' }, 32 | { text: 'Email' }, 33 | { text: 'Share' } 34 | ], 35 | titleText: 'Share', 36 | cancelText: 'Cancel', 37 | buttonClicked: function(index) { 38 | switch(index) { 39 | case 0: 40 | shareToFacebook(); 41 | break; 42 | case 1: 43 | shareToTwitter(); 44 | break; 45 | case 2: 46 | shareViaEmail(); 47 | break; 48 | case 3: 49 | shareNative(); 50 | break; 51 | } 52 | return true; 53 | } 54 | }); 55 | } 56 | 57 | function shareNative() { 58 | var message = vm.article.title; 59 | var subject = vm.article.title; 60 | 61 | $cordovaSocialSharing 62 | .share(message, subject, null, vm.article.url); 63 | } 64 | 65 | function shareToFacebook() { 66 | var message = vm.article.title; 67 | var image = vm.article.image; 68 | var link = vm.article.url; 69 | 70 | $cordovaSocialSharing 71 | .shareViaFacebook(message, image, link); 72 | } 73 | 74 | function shareToTwitter() { 75 | var message = vm.article.title + ' ' + vm.article.url; 76 | var image = vm.article.image; 77 | var link = vm.article.url; 78 | 79 | $cordovaSocialSharing 80 | .shareViaTwitter(message, image, link); 81 | } 82 | 83 | function shareViaEmail() { 84 | var message = 'Read more about "' + vm.article.title + '" ' + vm.article.url; 85 | var subject = vm.article.title; 86 | 87 | $cordovaSocialSharing 88 | .shareViaEmail(message, subject, [], [], [], null); 89 | } 90 | 91 | function loadArticle() { 92 | wordpressService.getArticle(articleId) 93 | .then(function(article) { 94 | vm.article = article; 95 | }); 96 | } 97 | } 98 | })(); 99 | -------------------------------------------------------------------------------- /app/scripts/wordpress/wordpress-article.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 |

{{vm.article.title}}

10 |
11 |

{{vm.article.author}} - {{vm.article.date}}

12 |

[{{vm.article.tags.join(", ")}}]

13 |
14 |
15 |
16 | -------------------------------------------------------------------------------- /app/scripts/wordpress/wordpress-articles.controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.wordpress') 6 | .controller('WordpressArticlesController', WordpressArticlesController); 7 | 8 | WordpressArticlesController.$inject = ['$state', 'wordpressService']; 9 | 10 | /* @ngInject */ 11 | function WordpressArticlesController($state, wordpressService) { 12 | var vm = angular.extend(this, { 13 | articles: [], 14 | navigate: navigate 15 | }); 16 | 17 | function activate() { 18 | getArticles(); 19 | } 20 | activate(); 21 | 22 | // ******************************************************************** 23 | 24 | function getArticles() { 25 | wordpressService.getArticles() 26 | .then(function(articles) { 27 | vm.articles = articles; 28 | }); 29 | } 30 | 31 | function navigate(articleId) { 32 | $state.go('app.wordpress-article', { articleId: articleId }); 33 | } 34 | } 35 | })(); 36 | -------------------------------------------------------------------------------- /app/scripts/wordpress/wordpress-articles.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 | 7 |

{{article.title}}

8 |

{{article.brief | limitTo: 120 }}{{article.brief.length > 120 ? '...' : ''}}

9 |
10 |
11 |
12 | 13 |
14 |
15 | -------------------------------------------------------------------------------- /app/scripts/wordpress/wordpress.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.wordpress', [ 6 | 'ionic', 7 | 'supermodular.common' 8 | ]) 9 | .config(function($stateProvider) { 10 | $stateProvider 11 | .state('app.wordpress-articles', { 12 | url: '/wordpress-articles', 13 | views: { 14 | 'menuContent': { 15 | templateUrl: 'scripts/wordpress/wordpress-articles.html', 16 | controller: 'WordpressArticlesController as vm' 17 | } 18 | } 19 | }) 20 | .state('app.wordpress-article', { 21 | url: '/wordpress-articles/:articleId', 22 | views: { 23 | 'menuContent': { 24 | templateUrl: 'scripts/wordpress/wordpress-article.html', 25 | controller: 'WordpressArticleController as vm' 26 | } 27 | } 28 | }); 29 | }); 30 | })(); 31 | -------------------------------------------------------------------------------- /app/scripts/wordpress/wordpress.service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('supermodular.wordpress') 6 | .factory('wordpressService', wordpressService); 7 | 8 | wordpressService.$inject = ['$http', '$q', '_', 'htmlToPlainText']; 9 | 10 | /* @ngInject */ 11 | function wordpressService($http, $q, _, htmlToPlainText) { 12 | var url = 'http://demo.titaniumtemplates.com/wordpress/?json=1'; 13 | var articles = []; 14 | 15 | var service = { 16 | getArticles: getArticles, 17 | getArticle: getArticle 18 | }; 19 | return service; 20 | 21 | //////////////// 22 | 23 | function getArticles() { 24 | return $http.get(url) 25 | .then(function(response) { 26 | articles = []; 27 | _.each(response.data.posts, function(item) { 28 | var imageUrl = item.attachments.length > 0 ? item.attachments[0].images.full.url : null; 29 | var tags = []; 30 | _.each(item.tags, function(tag) { 31 | tags.push(tag.title); 32 | }); 33 | 34 | var contentIndex = item.content.indexOf('

') + 4; 35 | var content = contentIndex === -1 ? item.content : item.content.substring(contentIndex); 36 | 37 | articles.push({ 38 | id: item.id, 39 | title: item.title, 40 | brief: htmlToPlainText(item.excerpt), 41 | image: imageUrl, 42 | date: item.date, 43 | content: content, 44 | author: item.author.name, 45 | tags: tags, 46 | url: url 47 | }); 48 | }); 49 | return articles; 50 | }); 51 | } 52 | 53 | function getArticle(articleId) { 54 | if (articles.length) { 55 | return $q.when(_.find(articles, 'id', articleId)); 56 | } else { 57 | var deferred = $q.defer(); 58 | 59 | getArticles() 60 | .then(function() { 61 | deferred.resolve(_.find(articles, 'id', articleId)); 62 | }); 63 | 64 | return deferred.promise; 65 | } 66 | } 67 | } 68 | })(); 69 | -------------------------------------------------------------------------------- /app/styles/common.scss: -------------------------------------------------------------------------------- 1 | /* Empty. Add your own CSS if you like */ 2 | img {max-width: 100%;} 3 | 4 | .content-inner{padding: 16px;} 5 | 6 | .card.col{padding: 0;} 7 | 8 | /* 9 | * Android. Action sheet 10 | */ 11 | .platform-android .action-sheet .button { 12 | padding-left: 16px; 13 | } 14 | 15 | .has-extended-footer { 16 | bottom: $extended-footer-height; 17 | } 18 | 19 | .extended-footer { 20 | height: $extended-footer-height; 21 | .subtitle { 22 | text-align: center; 23 | width: 100%; 24 | position: absolute; 25 | bottom: 10px; 26 | left: -5px; 27 | } 28 | } 29 | 30 | .item-icon-left-extended { 31 | padding-left: 80px; 32 | .icon { 33 | left: 20px; 34 | font-size: 50px; 35 | } 36 | } 37 | 38 | .error-message { 39 | color: orangered !important; 40 | } -------------------------------------------------------------------------------- /app/styles/home.scss: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Home 4 | */ 5 | .home-hello{ 6 | position:relative; 7 | } 8 | 9 | .home img{ 10 | display: inherit; 11 | } 12 | 13 | .home-hello .item{ 14 | position: absolute; 15 | left: 0; 16 | right: 0; 17 | bottom: 0; 18 | margin: 0; 19 | border: 0; 20 | background: rgba(255,255,255, 0.6); 21 | } 22 | 23 | .card.col.home h1{text-align: center;} 24 | .card.col.home h2{text-align: center;} 25 | -------------------------------------------------------------------------------- /app/styles/main.scss: -------------------------------------------------------------------------------- 1 | /* 2 | To customize the look and feel of Ionic, you can override the variables 3 | in ionic's _variables.scss file. 4 | 5 | For example, you might change some of the default colors: 6 | 7 | $light: #fff !default; 8 | $stable: #f8f8f8 !default; 9 | $positive: #387ef5 !default; 10 | $calm: #11c1f3 !default; 11 | $balanced: #33cd5f !default; 12 | $energized: #ffc900 !default; 13 | $assertive: #ef473a !default; 14 | $royal: #886aea !default; 15 | $dark: #444 !default; 16 | */ 17 | 18 | // The path for our ionicons font files, relative to the built CSS in www/css 19 | $ionicons-font-path: "../fonts" !default; 20 | 21 | $extended-footer-height: 70px; 22 | 23 | // Include all of Ionic 24 | @import "../bower_components/ionic/scss/ionic"; 25 | 26 | @import "common"; 27 | @import "home"; 28 | @import "map"; 29 | -------------------------------------------------------------------------------- /app/styles/map.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Map 3 | */ 4 | 5 | #map-view .scroll { 6 | height: 100%; 7 | } 8 | 9 | .gmaps { 10 | height: 100%; 11 | } 12 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Supermodular", 3 | "version": "1.1.0", 4 | "dependencies": { 5 | "ionic": "~1.2.1", 6 | "angular-websocket": "~1.0.9", 7 | "ngCordova": "~0.1.18-alpha", 8 | "lodash": "~3.8.0", 9 | "angular-base64": "~2.0.4", 10 | "ionic-service-core": "~0.1.3", 11 | "ionic-service-push": "~0.1.3", 12 | "angular-moment": "~0.10.1", 13 | "angularfire": "~1.1.1", 14 | "angular-bootstrap-calendar": "~0.11.3", 15 | "components-font-awesome": "~4.3.0", 16 | "ng-cordova-oauth": "~0.1.4" 17 | }, 18 | "devDependencies": { 19 | "angular-mocks": "~1.3.6", 20 | "angular-scenario": "~1.3.6" 21 | }, 22 | "resolutions": { 23 | "angular": ">= 1.4.3" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | ``` 3 | 2.0 - December 31, 2015 4 | - Ionic update to v1.2.1 5 | - Demonstration examples of Native Scrolling as it is now Ionic's default and Ionic's Slide Box based on Swiper widget (http://blog.ionic.io/announcing-ionic-1-2/) 6 | 7 | 1.2 - December 22, 2015 8 | - Downgrade Cordova iOS to 3.9.2 so there is no conflict with the plugins used 9 | - Improved installation process 10 | - Copy of package.json for the replacement of the original one when needed 11 | 12 | 1.1 - December 17, 2015 13 | - Fix on ConnectionType always returning Connection.UNKNOWN (Android) 14 | - Ionic update to v1.1.1 15 | - Cordova CLI update to v5.4.1 16 | - Ionic CLI update to v1.7.12 17 | - ngCordova update to v0.1.23-alpha 18 | - Support of android versions back to 4.0 19 | - Cordova iOS engine update to 4.0.0 20 | - Plugins update 21 | - Improved installation process for Win/Linux/MacOS 22 | - README.md update with improved instructions on how to install, run, build the app. 23 | 24 | 1.0 - Nov 23, 2015 25 | - Initial release 26 | ``` 27 | -------------------------------------------------------------------------------- /config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Supermodular 4 | 5 | Supermodular Ionic. The boostrap you need in order to build your next Ionic application. 6 | 7 | 8 | Stavros Kounis 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /hooks/README.md: -------------------------------------------------------------------------------- 1 | 21 | # Cordova Hooks 22 | 23 | Cordova Hooks represent special scripts which could be added by application and plugin developers or even by your own build system to customize cordova commands. Hook scripts could be defined by adding them to the special predefined folder (`/hooks`) or via configuration files (`config.xml` and `plugin.xml`) and run serially in the following order: 24 | * Application hooks from `/hooks`; 25 | * Application hooks from `config.xml`; 26 | * Plugin hooks from `plugins/.../plugin.xml`. 27 | 28 | __Remember__: Make your scripts executable. 29 | 30 | __Note__: `.cordova/hooks` directory is also supported for backward compatibility, but we don't recommend using it as it is deprecated. 31 | 32 | ## Supported hook types 33 | The following hook types are supported: 34 | 35 | after_build/ 36 | after_compile/ 37 | after_docs/ 38 | after_emulate/ 39 | after_platform_add/ 40 | after_platform_rm/ 41 | after_platform_ls/ 42 | after_plugin_add/ 43 | after_plugin_ls/ 44 | after_plugin_rm/ 45 | after_plugin_search/ 46 | after_plugin_install/ <-- Plugin hooks defined in plugin.xml are executed exclusively for a plugin being installed 47 | after_prepare/ 48 | after_run/ 49 | after_serve/ 50 | before_build/ 51 | before_compile/ 52 | before_docs/ 53 | before_emulate/ 54 | before_platform_add/ 55 | before_platform_rm/ 56 | before_platform_ls/ 57 | before_plugin_add/ 58 | before_plugin_ls/ 59 | before_plugin_rm/ 60 | before_plugin_search/ 61 | before_plugin_install/ <-- Plugin hooks defined in plugin.xml are executed exclusively for a plugin being installed 62 | before_plugin_uninstall/ <-- Plugin hooks defined in plugin.xml are executed exclusively for a plugin being uninstalled 63 | before_prepare/ 64 | before_run/ 65 | before_serve/ 66 | pre_package/ <-- Windows 8 and Windows Phone only. 67 | 68 | ## Ways to define hooks 69 | ### Via '/hooks' directory 70 | To execute custom action when corresponding hook type is fired, use hook type as a name for a subfolder inside 'hooks' directory and place you script file here, for example: 71 | 72 | # script file will be automatically executed after each build 73 | hooks/after_build/after_build_custom_action.js 74 | 75 | 76 | ### Config.xml 77 | 78 | Hooks can be defined in project's `config.xml` using `` elements, for example: 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | ... 89 | 90 | 91 | 92 | 93 | 94 | 95 | ... 96 | 97 | 98 | ### Plugin hooks (plugin.xml) 99 | 100 | As a plugin developer you can define hook scripts using `` elements in a `plugin.xml` like that: 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | ... 109 | 110 | 111 | `before_plugin_install`, `after_plugin_install`, `before_plugin_uninstall` plugin hooks will be fired exclusively for the plugin being installed/uninstalled. 112 | 113 | ## Script Interface 114 | 115 | ### Javascript 116 | 117 | If you are writing hooks in Javascript you should use the following module definition: 118 | ```javascript 119 | module.exports = function(context) { 120 | ... 121 | } 122 | ``` 123 | 124 | You can make your scipts async using Q: 125 | ```javascript 126 | module.exports = function(context) { 127 | var Q = context.requireCordovaModule('q'); 128 | var deferral = new Q.defer(); 129 | 130 | setTimeout(function(){ 131 | console.log('hook.js>> end'); 132 | deferral.resolve(); 133 | }, 1000); 134 | 135 | return deferral.promise; 136 | } 137 | ``` 138 | 139 | `context` object contains hook type, executed script full path, hook options, command-line arguments passed to Cordova and top-level "cordova" object: 140 | ```json 141 | { 142 | "hook": "before_plugin_install", 143 | "scriptLocation": "c:\\script\\full\\path\\appBeforePluginInstall.js", 144 | "cmdLine": "The\\exact\\command\\cordova\\run\\with arguments", 145 | "opts": { 146 | "projectRoot":"C:\\path\\to\\the\\project", 147 | "cordova": { 148 | "platforms": ["wp8"], 149 | "plugins": ["com.plugin.withhooks"], 150 | "version": "0.21.7-dev" 151 | }, 152 | "plugin": { 153 | "id": "com.plugin.withhooks", 154 | "pluginInfo": { 155 | ... 156 | }, 157 | "platform": "wp8", 158 | "dir": "C:\\path\\to\\the\\project\\plugins\\com.plugin.withhooks" 159 | } 160 | }, 161 | "cordova": {...} 162 | } 163 | 164 | ``` 165 | `context.opts.plugin` object will only be passed to plugin hooks scripts. 166 | 167 | You can also require additional Cordova modules in your script using `context.requireCordovaModule` in the following way: 168 | ```javascript 169 | var Q = context.requireCordovaModule('q'); 170 | ``` 171 | 172 | __Note__: new module loader script interface is used for the `.js` files defined via `config.xml` or `plugin.xml` only. 173 | For compatibility reasons hook files specified via `/hooks` folders are run via Node child_process spawn, see 'Non-javascript' section below. 174 | 175 | ### Non-javascript 176 | 177 | Non-javascript scripts are run via Node child_process spawn from the project's root directory and have the root directory passes as the first argument. All other options are passed to the script using environment variables: 178 | 179 | * CORDOVA_VERSION - The version of the Cordova-CLI. 180 | * CORDOVA_PLATFORMS - Comma separated list of platforms that the command applies to (e.g.: android, ios). 181 | * CORDOVA_PLUGINS - Comma separated list of plugin IDs that the command applies to (e.g.: org.apache.cordova.file, org.apache.cordova.file-transfer) 182 | * CORDOVA_HOOK - Path to the hook that is being executed. 183 | * CORDOVA_CMDLINE - The exact command-line arguments passed to cordova (e.g.: cordova run ios --emulate) 184 | 185 | If a script returns a non-zero exit code, then the parent cordova command will be aborted. 186 | 187 | ## Writing hooks 188 | 189 | We highly recommend writing your hooks using Node.js so that they are 190 | cross-platform. Some good examples are shown here: 191 | 192 | [http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/](http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/) 193 | 194 | Also, note that even if you are working on Windows, and in case your hook scripts aren't bat files (which is recommended, if you want your scripts to work in non-Windows operating systems) Cordova CLI will expect a shebang line as the first line for it to know the interpreter it needs to use to launch the script. The shebang line should match the following example: 195 | 196 | #!/usr/bin/env [name_of_interpreter_executable] 197 | -------------------------------------------------------------------------------- /hooks/after_platform_add/install_plugins.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Install all plugins listed in package.json 5 | */ 6 | var exec = require('child_process').exec; 7 | var path = require('path'); 8 | var sys = require('sys'); 9 | 10 | var packageJSON = require('../../package.json'); 11 | var cmd = process.platform === 'win32' ? 'cordova.cmd' : 'cordova'; 12 | var script = path.resolve(__dirname, '../../node_modules/cordova/bin', cmd); 13 | 14 | packageJSON.cordovaPlugins = packageJSON.cordovaPlugins || []; 15 | packageJSON.cordovaPlugins.forEach(function (plugin) { 16 | exec(script + ' plugin add ' + plugin, function (error, stdout, stderr) { 17 | sys.puts(stdout); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /hooks/after_plugin_add/register_plugins.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Push plugins to cordovaPlugins array after_plugin_add 5 | */ 6 | var fs = require('fs'); 7 | var packageJSON = require('../../package.json'); 8 | 9 | packageJSON.cordovaPlugins = packageJSON.cordovaPlugins || []; 10 | 11 | var fromEnv = process.env.CORDOVA_PLUGINS.split(','); 12 | for (var i = 0; i < fromEnv.length; i++) { 13 | var plugin = fromEnv[i]; 14 | 15 | if (packageJSON.cordovaPlugins.indexOf(plugin) !== -1) { 16 | packageJSON.cordovaPlugins.push(plugin); 17 | } 18 | } 19 | 20 | fs.writeFileSync('package.json', JSON.stringify(packageJSON, null, 2)); 21 | -------------------------------------------------------------------------------- /hooks/after_plugin_rm/deregister_plugins.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Remove plugins from cordovaPlugins array after_plugin_rm 5 | */ 6 | var fs = require('fs'); 7 | var _ = require('lodash'); 8 | var packageJSON = require('../../package.json'); 9 | 10 | packageJSON.cordovaPlugins = packageJSON.cordovaPlugins || []; 11 | _.each(process.env.CORDOVA_PLUGINS.split(','), function (plugin) { 12 | _.remove(packageJSON.cordovaPlugins, function (p) { return p === plugin; }); 13 | }); 14 | 15 | fs.writeFile('package.json', JSON.stringify(packageJSON, null, 2)); 16 | -------------------------------------------------------------------------------- /hooks/after_prepare/icons_and_splashscreens.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /** 3 | * Algorithm 4 | * [1] Look at all installed platforms 5 | * [2] Copy (non-destructive) icons and splash screens from platform to local RESOURCE_DIR 6 | * [3] Copy (destructive) matching icons and splash screens from RESOURCE_DIR to platform 7 | * 8 | * This ensures that local RESOURCE_DIR will be pre-scaffolded with icons and splash 9 | * screens generated by Cordova as placeholder ONLY for installed platforms and that 10 | * any modifications to local assets are reflected in the CORRECT Cordova platform 11 | * locations, without having to hardcode file paths. 12 | */ 13 | var fs = require('fs'); 14 | var path = require('path'); 15 | var _ = require('lodash'); 16 | var ncp = require('ncp'); 17 | var mkdirp = require('mkdirp'); 18 | var glob = require('glob'); 19 | var Orchestrator = require('orchestrator'); 20 | 21 | var BASES = { 22 | android: 'res', 23 | ios: 'Supermodular/Resources' 24 | }; 25 | var RESOURCE_DIR = 'resources'; 26 | 27 | // Helper function for file copying that ensures directory existence. 28 | function copyFile (src, dest, ncpOpts, callback) { 29 | var orchestrator = new Orchestrator(); 30 | var parts = dest.split(path.sep); 31 | var fileName = parts.pop(); 32 | var destDir = parts.join(path.sep); 33 | var destFile = path.resolve(destDir, fileName); 34 | orchestrator.add('ensureDir', function (done) { 35 | mkdirp(destDir, function (err) { 36 | done(err); 37 | }); 38 | }); 39 | orchestrator.add('copyFile', ['ensureDir'], function (done) { 40 | ncp(src, destFile, ncpOpts, function (err) { 41 | done(err); 42 | }); 43 | }); 44 | orchestrator.start('copyFile', function (err) { 45 | callback(err); 46 | }); 47 | } 48 | 49 | // Main 50 | var platforms = _.filter(fs.readdirSync('platforms'), function (file) { 51 | return fs.statSync(path.resolve('platforms', file)).isDirectory(); 52 | }); 53 | _.each(platforms, function (platform) { 54 | var base = path.resolve('platforms', platform, BASES[platform]); 55 | glob(base + '/**/*.png', function (err, files) { 56 | _.each(files, function (cordovaFile) { 57 | var orchestrator = new Orchestrator(); 58 | var parts = cordovaFile.split('/'); 59 | var fileName = parts.pop(); 60 | var localDir = path.resolve(RESOURCE_DIR, platform, _.last(parts)); 61 | var localFile = path.resolve(localDir, fileName); 62 | 63 | orchestrator.add('copyFromCordova', function (done) { 64 | copyFile(cordovaFile, localFile, { clobber: false }, function (err) { 65 | done(err); 66 | }); 67 | }); 68 | orchestrator.add('copyToCordova', ['copyFromCordova'], function (done) { 69 | copyFile(localFile, cordovaFile, { clobber: true }, function (err) { 70 | done(err); 71 | }); 72 | }); 73 | orchestrator.start('copyToCordova', function (err) { 74 | if (err) { console.error(err); } 75 | }); 76 | }); 77 | }); 78 | }); 79 | -------------------------------------------------------------------------------- /hooks/after_prepare/update_platform_config.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** This hook updates platform configuration files based on preferences and config-file data defined in config.xml. 4 | Currently only the AndroidManifest.xml and IOS *-Info.plist file are supported. 5 | 6 | Preferences: 7 | 1. Preferences defined outside of the platform element will apply to all platforms 8 | 2. Preferences defined inside a platform element will apply only to the specified platform 9 | 3. Platform preferences take precedence over common preferences 10 | 4. The preferenceMappingData object contains all of the possible custom preferences to date including the 11 | target file they belong to, parent element, and destination element or attribute 12 | 13 | Config Files 14 | 1. config-file elements MUST be defined inside a platform element, otherwise they will be ignored. 15 | 2. config-file target attributes specify the target file to update. (AndroidManifest.xml or *-Info.plist) 16 | 3. config-file parent attributes specify the parent element (AndroidManifest.xml) or parent key (*-Info.plist) 17 | that the child data will replace or be appended to. 18 | 4. config-file elements are uniquely indexed by target AND parent for each platform. 19 | 5. If there are multiple config-file's defined with the same target AND parent, the last config-file will be used 20 | 6. Elements defined WITHIN a config-file will replace or be appended to the same elements relative to the parent element 21 | 7. If a unique config-file contains multiples of the same elements (other than uses-permssion elements which are 22 | selected by by the uses-permission name attribute), the last defined element will be retrieved. 23 | 24 | Examples: 25 | 26 | AndroidManifest.xml 27 | NOTE: For possible manifest values see http://developer.android.com/guide/topics/manifest/manifest-intro.html 28 | 29 | 30 | //These preferences are actually available in Cordova by default although not currently documented 31 | 32 | 33 | 34 | 35 | //custom preferences examples 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | *-Info.plist 56 | 57 | 58 | 59 | 60 | UIInterfaceOrientationLandscapeOmg 61 | 62 | 63 | 64 | 65 | someValue 66 | 67 | 68 | 69 | NOTE: Currently, items aren't removed from the platform config files if you remove them from config.xml. 70 | For example, if you add a custom permission, build the remove it, it will still be in the manifest. 71 | If you make a mistake, for example adding an element to the wrong parent, you may need to remove and add your platform, 72 | or revert to your previous manifest/plist file. 73 | 74 | TODO: We may need to capture all default manifest/plist elements/keys created by Cordova along with any plugin elements/keys to compare against custom elements to remove. 75 | */ 76 | 77 | // global vars 78 | var fs = require('fs'); 79 | var path = require('path'); 80 | var _ = require('lodash'); 81 | var et = require('elementtree'); 82 | var plist = require('plist'); 83 | 84 | var rootdir = path.resolve(__dirname, '../../'); 85 | 86 | var platformConfig = (function(){ 87 | /* Global object that defines the available custom preferences for each platform. 88 | Maps a config.xml preference to a specific target file, parent element, and destination attribute or element 89 | */ 90 | var preferenceMappingData = { 91 | 'android': { 92 | 'android-manifest-hardwareAccelerated': {target: 'AndroidManifest.xml', parent: './', destination: 'android:hardwareAccelerated'}, 93 | 'android-installLocation': {target: 'AndroidManifest.xml', parent: './', destination: 'android:installLocation'}, 94 | 'android-activity-hardwareAccelerated': {target: 'AndroidManifest.xml', parent: 'application', destination: 'android:hardwareAccelerated'}, 95 | 'android-configChanges': {target: 'AndroidManifest.xml', parent: 'application/activity[@android:name=\'CordovaApp\']', destination: 'android:configChanges'}, 96 | 'android-launchMode': {target: 'AndroidManifest.xml', parent: 'application/activity[@android:name=\'CordovaApp\']', destination: 'android:launchMode'}, 97 | 'android-theme': {target: 'AndroidManifest.xml', parent: 'application/activity[@android:name=\'CordovaApp\']', destination: 'android:theme'}, 98 | 'android-windowSoftInputMode': {target: 'AndroidManifest.xml', parent: 'application/activity[@android:name=\'CordovaApp\']', destination: 'android:windowSoftInputMode'} 99 | }, 100 | 'ios': {} 101 | }; 102 | var configXmlData, preferencesData; 103 | 104 | return { 105 | // Parses a given file into an elementtree object 106 | parseElementtreeSync: function (filename) { 107 | var contents = fs.readFileSync(filename, 'utf-8'); 108 | if(contents) { 109 | //Windows is the BOM. Skip the Byte Order Mark. 110 | contents = contents.substring(contents.indexOf('<')); 111 | } 112 | return new et.ElementTree(et.XML(contents)); 113 | }, 114 | 115 | // Converts an elementtree object to an xml string. Since this is used for plist values, we don't care about attributes 116 | eltreeToXmlString: function (data) { 117 | var tag = data.tag; 118 | var el = '<' + tag + '>'; 119 | 120 | if(data.text && data.text.trim()) { 121 | el += data.text.trim(); 122 | } else { 123 | _.each(data.getchildren(), function (child) { 124 | el += platformConfig.eltreeToXmlString(child); 125 | }); 126 | } 127 | 128 | el += ''; 129 | return el; 130 | }, 131 | 132 | // Parses the config.xml into an elementtree object and stores in the config object 133 | getConfigXml: function () { 134 | if(!configXmlData) { 135 | configXmlData = this.parseElementtreeSync(path.join(rootdir, 'config.xml')); 136 | } 137 | 138 | return configXmlData; 139 | }, 140 | 141 | /* Retrieves all from config.xml and returns a map of preferences with platform as the key. 142 | If a platform is supplied, common prefs + platform prefs will be returned, otherwise just common prefs are returned. 143 | */ 144 | getPreferences: function (platform) { 145 | var configXml = this.getConfigXml(); 146 | 147 | //init common config.xml prefs if we haven't already 148 | if(!preferencesData) { 149 | preferencesData = { 150 | common: configXml.findall('preference') 151 | }; 152 | } 153 | 154 | var prefs = preferencesData.common || []; 155 | if(platform) { 156 | if(!preferencesData[platform]) { 157 | preferencesData[platform] = configXml.findall('platform[@name=\'' + platform + '\']/preference'); 158 | } 159 | prefs = prefs.concat(preferencesData[platform]); 160 | } 161 | 162 | return prefs; 163 | }, 164 | 165 | /* Retrieves all configured xml for a specific platform/target/parent element nested inside a platforms config-file 166 | element within the config.xml. The config-file elements are then indexed by target|parent so if there are 167 | any config-file elements per platform that have the same target and parent, the last config-file element is used. 168 | */ 169 | getConfigFilesByTargetAndParent: function (platform) { 170 | var configFileData = this.getConfigXml().findall('platform[@name=\'' + platform + '\']/config-file'); 171 | 172 | return _.indexBy(configFileData, function(item) { 173 | var parent = item.attrib.parent; 174 | //if parent attribute is undefined /* or */, set parent to top level elementree selector 175 | if(!parent || parent === '/*' || parent === '*/') { 176 | parent = './'; 177 | } 178 | return item.attrib.target + '|' + parent; 179 | }); 180 | }, 181 | 182 | // Parses the config.xml's preferences and config-file elements for a given platform 183 | parseConfigXml: function (platform) { 184 | var configData = {}; 185 | this.parsePreferences(configData, platform); 186 | this.parseConfigFiles(configData, platform); 187 | 188 | return configData; 189 | }, 190 | 191 | // Retrieves the config.xml's pereferences for a given platform and parses them into JSON data 192 | parsePreferences: function (configData, platform) { 193 | var preferences = this.getPreferences(platform), 194 | type = 'preference'; 195 | 196 | _.each(preferences, function (preference) { 197 | var prefMappingData = preferenceMappingData[platform][preference.attrib.name], 198 | target, 199 | prefData; 200 | 201 | if (prefMappingData) { 202 | prefData = { 203 | parent: prefMappingData.parent, 204 | type: type, 205 | destination: prefMappingData.destination, 206 | data: preference 207 | }; 208 | 209 | target = prefMappingData.target; 210 | if(!configData[target]) { 211 | configData[target] = []; 212 | } 213 | configData[target].push(prefData); 214 | } 215 | }); 216 | }, 217 | 218 | // Retrieves the config.xml's config-file elements for a given platform and parses them into JSON data 219 | parseConfigFiles: function (configData, platform) { 220 | var configFiles = this.getConfigFilesByTargetAndParent(platform), 221 | type = 'configFile'; 222 | 223 | _.each(configFiles, function (configFile, key) { 224 | var keyParts = key.split('|'); 225 | var target = keyParts[0]; 226 | var parent = keyParts[1]; 227 | var items = configData[target] || []; 228 | 229 | _.each(configFile.getchildren(), function (element) { 230 | items.push({ 231 | parent: parent, 232 | type: type, 233 | destination: element.tag, 234 | data: element 235 | }); 236 | }); 237 | 238 | configData[target] = items; 239 | }); 240 | }, 241 | 242 | // Parses config.xml data, and update each target file for a specified platform 243 | updatePlatformConfig: function (platform) { 244 | var configData = this.parseConfigXml(platform), 245 | platformPath = path.join(rootdir, 'platforms', platform); 246 | 247 | _.each(configData, function (configItems, targetFileName) { 248 | var projectName, targetFile; 249 | 250 | if (platform === 'ios' && targetFileName.indexOf("Info.plist") > -1) { 251 | projectName = platformConfig.getConfigXml().findtext('name'); 252 | targetFile = path.join(platformPath, projectName, projectName + '-Info.plist'); 253 | platformConfig.updateIosPlist(targetFile, configItems); 254 | } else if (platform === 'android' && targetFileName === 'AndroidManifest.xml') { 255 | targetFile = path.join(platformPath, targetFileName); 256 | platformConfig.updateAndroidManifest(targetFile, configItems); 257 | } 258 | }); 259 | }, 260 | 261 | // Updates the AndroidManifest.xml target file with data from config.xml 262 | updateAndroidManifest: function (targetFile, configItems) { 263 | var tempManifest = platformConfig.parseElementtreeSync(targetFile), 264 | root = tempManifest.getroot(); 265 | 266 | _.each(configItems, function (item) { 267 | // if parent is not found on the root, child/grandchild nodes are searched 268 | var parentEl = root.find(item.parent) || root.find('*/' + item.parent), 269 | data = item.data, 270 | childSelector = item.destination, 271 | childEl; 272 | 273 | if(!parentEl) { 274 | return; 275 | } 276 | 277 | if(item.type === 'preference') { 278 | parentEl.attrib[childSelector] = data.attrib['value']; 279 | } else { 280 | // since there can be multiple uses-permission elements, we need to select them by unique name 281 | if(childSelector === 'uses-permission') { 282 | childSelector += '[@android:name=\'' + data.attrib['android:name'] + '\']'; 283 | } 284 | 285 | childEl = parentEl.find(childSelector); 286 | // if child element doesnt exist, create new element 287 | if(!childEl) { 288 | childEl = new et.Element(item.destination); 289 | parentEl.append(childEl); 290 | } 291 | 292 | // copy all config.xml data except for the generated _id property 293 | _.each(data, function (prop, propName) { 294 | if(propName !== '_id') { 295 | childEl[propName] = prop; 296 | } 297 | }); 298 | } 299 | }); 300 | 301 | fs.writeFileSync(targetFile, tempManifest.write({indent: 4}), 'utf-8'); 302 | }, 303 | 304 | /* Updates the *-Info.plist file with data from config.xml by parsing to an xml string, then using the plist 305 | module to convert the data to a map. The config.xml data is then replaced or appended to the original plist file 306 | */ 307 | updateIosPlist: function (targetFile, configItems) { 308 | var infoPlist = plist.parse(fs.readFileSync(targetFile, 'utf-8')), 309 | tempInfoPlist; 310 | 311 | _.each(configItems, function (item) { 312 | var key = item.parent; 313 | var plistXml = '' + key + ''; 314 | plistXml += platformConfig.eltreeToXmlString(item.data) + ''; 315 | 316 | var configPlistObj = plist.parse(plistXml); 317 | infoPlist[key] = configPlistObj[key]; 318 | }); 319 | 320 | tempInfoPlist = plist.build(infoPlist); 321 | tempInfoPlist = tempInfoPlist.replace(/[\s\r\n]*<\/string>/g,''); 322 | fs.writeFileSync(targetFile, tempInfoPlist, 'utf-8'); 323 | } 324 | }; 325 | })(); 326 | 327 | // Main 328 | (function () { 329 | if (rootdir) { 330 | // go through each of the platform directories that have been prepared 331 | var platforms = _.filter(fs.readdirSync('platforms'), function (file) { 332 | return fs.statSync(path.resolve('platforms', file)).isDirectory(); 333 | }); 334 | 335 | _.each(platforms, function (platform) { 336 | try { 337 | platform = platform.trim().toLowerCase(); 338 | platformConfig.updatePlatformConfig(platform); 339 | } catch (e) { 340 | process.stdout.write(e); 341 | } 342 | }); 343 | } 344 | })(); -------------------------------------------------------------------------------- /hooks/before_platform_add/init_directories.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * On a fresh clone, the local platforms/ and plugins/ directories will be 5 | * missing, so ensure they get created before the first platform is added. 6 | */ 7 | var mkdirp = require('mkdirp'); 8 | var path = require('path'); 9 | 10 | var platformsDir = path.resolve(__dirname, '../../platforms'); 11 | var pluginsDir = path.resolve(__dirname, '../../plugins'); 12 | 13 | mkdirp(platformsDir, function (err) { 14 | if (err) { console.error(err); } 15 | }); 16 | 17 | mkdirp(pluginsDir, function (err) { 18 | if (err) { console.error(err); } 19 | }); 20 | -------------------------------------------------------------------------------- /install.bat: -------------------------------------------------------------------------------- 1 | :: 2 | :: Create output (Cordova) directory 3 | :: 4 | mkdir www 5 | 6 | :: 7 | :: Install client libraries 8 | :: 9 | bower install 10 | 11 | :: 12 | :: Install cordova plugins 13 | :: The quickest option is to ask from Ionic 14 | :: to restore the state of the app. 15 | :: https://github.com/driftyco/ionic-cli::ionic-state-restore 16 | :: If this process fails comment this line and uncomment the 17 | :: "cordova plugin add ..." lines that follow. 18 | :: 19 | ionic state restore 20 | :: 21 | :: cordova plugin add cordova-plugin-device 22 | :: cordova plugin add cordova-plugin-console 23 | :: cordova plugin add com.ionic.keyboard 24 | :: cordova plugin add cordova-plugin-inappbrowser 25 | :: cordova plugin add cordova-plugin-geolocation 26 | :: cordova plugin add https://github.com/EddyVerbruggen/SocialSharing-PhoneGap-Plugin.git 27 | :: cordova plugin add de.appplant.cordova.plugin.email-composer 28 | :: cordova plugin add cordova-plugin-network-information 29 | :: cordova plugin add cordova-plugin-whitelist 30 | :: cordova plugin add cordova-plugin-transport-security 31 | 32 | :: 33 | :: Add target platform 34 | :: 35 | :: Comment out the platform(s) your system supports 36 | :: 37 | grunt platform:add:ios 38 | :: grunt platform:add:android 39 | 40 | :: 41 | :: Build the project and generate the cordova directory (www) 42 | :: 43 | grunt build 44 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | # 2 | # Create output (Cordova) directory 3 | # 4 | mkdir www 5 | 6 | # 7 | # Install client libraries 8 | # 9 | bower install 10 | 11 | # 12 | # Install cordova plugins 13 | # The quickest option is to ask from Ionic 14 | # to restore the state of the app. 15 | # https://github.com/driftyco/ionic-cli#ionic-state-restore 16 | # If this process fails comment this line and uncomment the 17 | # "cordova plugin add ..." lines that follow. 18 | # 19 | ionic state restore 20 | # 21 | # cordova plugin add cordova-plugin-device 22 | # cordova plugin add cordova-plugin-console 23 | # cordova plugin add com.ionic.keyboard 24 | # cordova plugin add cordova-plugin-inappbrowser 25 | # cordova plugin add cordova-plugin-geolocation 26 | # cordova plugin add https://github.com/EddyVerbruggen/SocialSharing-PhoneGap-Plugin.git 27 | # cordova plugin add de.appplant.cordova.plugin.email-composer 28 | # cordova plugin add cordova-plugin-network-information 29 | # cordova plugin add cordova-plugin-whitelist 30 | # cordova plugin add cordova-plugin-transport-security 31 | 32 | # 33 | # Add target platform 34 | # 35 | # Comment out the platform(s) your system supports 36 | # 37 | grunt platform:add:ios 38 | # grunt platform:add:android 39 | 40 | # 41 | # Build the project and generate the cordova directory (www) 42 | # 43 | grunt build 44 | -------------------------------------------------------------------------------- /ionic.project: -------------------------------------------------------------------------------- 1 | { 2 | "name": "supermodular-ionic", 3 | "app_id": "d25614ca" 4 | } 5 | -------------------------------------------------------------------------------- /misc/faces.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/faces.psd -------------------------------------------------------------------------------- /misc/menu-items/item-01-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-01-1.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-01-thumb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-01-thumb.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-02-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-02-1.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-02-thumb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-02-thumb.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-03-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-03-1.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-03-thumb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-03-thumb.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-04-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-04-1.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-04-thumb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-04-thumb.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-05-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-05-1.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-05-thumb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-05-thumb.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-06-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-06-1.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-06-thumb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-06-thumb.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-07-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-07-1.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-07-thumb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-07-thumb.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-08-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-08-1.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-08-thumb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-08-thumb.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-09-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-09-1.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-09-thumb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-09-thumb.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-10-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-10-1.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-10-thumb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-10-thumb.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-11-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-11-1.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-11-thumb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-11-thumb.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-12-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-12-1.jpg -------------------------------------------------------------------------------- /misc/menu-items/item-12-thumb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/misc/menu-items/item-12-thumb.jpg -------------------------------------------------------------------------------- /misc/menu-items/items.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 1, 3 | "jsonrpc": "2.0", 4 | "total": 6, 5 | "result": [ 6 | { 7 | "id": 1, 8 | "guid": "1d4aa3b2-c059-4fa7-a751-9bca735e4ebb", 9 | "thumb": "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-01-thumb.jpg", 10 | "title": "Mozzarella sticks", 11 | "body": "Extra delicious Mozzarella cheese sticks, mixed with zucchini and potatoes coated with flavorful herbs. Served with a side of marinara sauce for dipping.", 12 | "tags": ["mozzarella", "sticks"], 13 | "url" : "http://demo.morethanthemes.com/retailplus/commerce-default/node/9", 14 | "currency": "£", 15 | "price" : "11.00", 16 | "pictures": [ 17 | "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-01-1.jpg" 18 | ] 19 | }, { 20 | "id": 2, 21 | "guid": "6630fb89-94d6-4fec-a1c3-c48d80b88895", 22 | "thumb": "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-02-thumb.jpg", 23 | "title": "Cheesy Rosemary Monkey Bread Rolls", 24 | "body": "Rosemary, garlic and cheese make these monkey bread rolls perfect with any meal.", 25 | "tags": ["bread", "rosemary"], 26 | "url" : "http://demo.morethanthemes.com/retailplus/commerce-default/node/10", 27 | "currency": "£", 28 | "price" : "11.00", 29 | "pictures": [ 30 | "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-02-1.jpg" 31 | ] 32 | }, { 33 | "id": 3, 34 | "guid": "861d3f45-28ce-4b10-80e5-e98fafee4d4f", 35 | "thumb": "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-03-thumb.jpg", 36 | "title": "Sticks variety", 37 | "body": "A variety of vegetable and beef sticks will keep the balance for a healthy yet tasteful starter.", 38 | "tags": ["sticks", "beef", "vegetables"], 39 | "url" : "http://demo.morethanthemes.com/retailplus/commerce-default/node/11", 40 | "currency": "£", 41 | "price" : "18.00", 42 | "pictures": [ 43 | "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-03-1.jpg" 44 | ] 45 | }, { 46 | "id": 4, 47 | "guid": "205f2dd0-35e8-450c-9577-bb71be487fe7", 48 | "thumb": "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-04-thumb.jpg", 49 | "title": "Espresso coffee", 50 | "body": "Classic italian espresso made with blends of 80% arabica and 20% robusta. Served with cinnamon cookies.", 51 | "tags": ["coffee", "espresso"], 52 | "url" : "http://demo.morethanthemes.com/retailplus/commerce-default/node/12", 53 | "currency": "£", 54 | "price" : "7.00", 55 | "pictures": [ 56 | "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-04-1.jpg" 57 | ] 58 | }, { 59 | "id": 5, 60 | "guid": "4e0d6228-1ffc-46d4-ba68-22454728dd37", 61 | "thumb": "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-05-thumb.jpg", 62 | "title": "Plum layered dessert", 63 | "body": "A delicious dessert which is low in both fat and sugar.", 64 | "tags": ["plum"], 65 | "url" : "http://demo.morethanthemes.com/retailplus/commerce-default/node/13", 66 | "currency": "£", 67 | "price" : "9.00", 68 | "pictures": [ 69 | "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-05-1.jpg" 70 | ] 71 | }, { 72 | "id": 6, 73 | "guid": "b3119483-5125-4f6c-89a3-849ebc732447", 74 | "thumb": "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-06-thumb.jpg", 75 | "title": "Chocolate, raspberry and vanilla cake", 76 | "body": "Cake with almond sponge, raspberry coulis and raspberry sorbet.", 77 | "tags": ["cake", "raspberry", "Chocolate"], 78 | "url" : "http://demo.morethanthemes.com/retailplus/commerce-default/node/14", 79 | "currency": "£", 80 | "price" : "7.00", 81 | "pictures": [ 82 | "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-06-1.jpg" 83 | ] 84 | }, { 85 | "id": 7, 86 | "guid": "b3119483-5125-4f6c-89a3-849ebc732447", 87 | "thumb": "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-07-thumb.jpg", 88 | "title": "Strawberry heaven", 89 | "body": "Crispy base smothered with a layer of light mousse is then perfectly complemented by a layer of dreamy strawberry puree.", 90 | "tags": ["strawberry", "layered"], 91 | "url" : "http://demo.morethanthemes.com/retailplus/commerce-default/node/14", 92 | "currency": "£", 93 | "price" : "9.00", 94 | "pictures": [ 95 | "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-07-1.jpg" 96 | ] 97 | }, { 98 | "id": 8, 99 | "guid": "b3119483-5125-4f6c-89a3-849ebc732447", 100 | "thumb": "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-08-thumb.jpg", 101 | "title": "Mix of meat", 102 | "body": "Filets and sausages served with herb roasted potatoes and roasted vegetables seasoned with rosemary and thyme.", 103 | "tags": ["filet", "sausage", "red meat"], 104 | "url" : "http://demo.morethanthemes.com/retailplus/commerce-default/node/14", 105 | "currency": "£", 106 | "price" : "21.00", 107 | "pictures": [ 108 | "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-08-1.jpg" 109 | ] 110 | }, { 111 | "id": 9, 112 | "guid": "b3119483-5125-4f6c-89a3-849ebc732447", 113 | "thumb": "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-09-thumb.jpg", 114 | "title": "Handmade burgers", 115 | "body": "The beef we source for our burgers is sourced from Aberdeenshire a we just love the distinctive flavour and quality.", 116 | "tags": ["burger", "beef", "handmade"], 117 | "url" : "http://demo.morethanthemes.com/retailplus/commerce-default/node/14", 118 | "currency": "£", 119 | "price" : "16.00", 120 | "pictures": [ 121 | "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-09-1.jpg" 122 | ] 123 | }, { 124 | "id": 10, 125 | "guid": "b3119483-5125-4f6c-89a3-849ebc732447", 126 | "thumb": "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-10-thumb.jpg", 127 | "title": "Supreme Pizza", 128 | "body": "Beef, ham, pepperoni, Italian sausage, onion, mushroom, pineapple, capsicum & peppers.", 129 | "tags": ["pizza"], 130 | "url" : "http://demo.morethanthemes.com/retailplus/commerce-default/node/14", 131 | "currency": "£", 132 | "price" : "17.00", 133 | "pictures": [ 134 | "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-10-1.jpg" 135 | ] 136 | }, { 137 | "id": 11, 138 | "guid": "b3119483-5125-4f6c-89a3-849ebc732447", 139 | "thumb": "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-11-thumb.jpg", 140 | "title": "Mixed Vegetable Salad with Lime Dressing", 141 | "body": "This raw mixed vegetable salad takes the green leaves out of the mix and focuses more on the topping vegetables.", 142 | "tags": ["raw", "vegetables"], 143 | "url" : "http://demo.morethanthemes.com/retailplus/commerce-default/node/14", 144 | "currency": "£", 145 | "price" : "11.00", 146 | "pictures": [ 147 | "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-11-1.jpg" 148 | ] 149 | }, { 150 | "id": 12, 151 | "guid": "b3119483-5125-4f6c-89a3-849ebc732447", 152 | "thumb": "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-12-thumb.jpg", 153 | "title": "Lettuce Salad with Garlic Croutons", 154 | "body": "This salad has a fresh crunch due to different kinds of lettuce, garlic croutons and nuts.", 155 | "tags": ["lettuce", "croutons", "nuts"], 156 | "url" : "http://demo.morethanthemes.com/retailplus/commerce-default/node/14", 157 | "currency": "£", 158 | "price" : "11.00", 159 | "pictures": [ 160 | "http://skounis.s3.amazonaws.com/mobile-apps/barebone-ionic/item-12-1.jpg" 161 | ] 162 | } 163 | ] 164 | } 165 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Supermodular", 3 | "version": "1.1.0", 4 | "private": true, 5 | "dependencies": {}, 6 | "devDependencies": { 7 | "cordova": "^5.4.1", 8 | "elementtree": "0.1.6", 9 | "glob": "~4.3.5", 10 | "grunt": "~0.4.5", 11 | "grunt-autoprefixer": "~2.2.0", 12 | "grunt-concurrent": "1.0.0", 13 | "grunt-contrib-clean": "~0.6.0", 14 | "grunt-contrib-concat": "~0.5.0", 15 | "grunt-contrib-connect": "~0.9.0", 16 | "grunt-contrib-copy": "~0.7.0", 17 | "grunt-contrib-cssmin": "~0.11.0", 18 | "grunt-contrib-htmlmin": "~0.3.0", 19 | "grunt-contrib-jshint": "~0.11.0", 20 | "grunt-contrib-sass": "^0.9.2", 21 | "grunt-contrib-uglify": "~0.7.0", 22 | "grunt-contrib-watch": "~0.6.1", 23 | "grunt-include-source": "^0.5.1", 24 | "grunt-karma": "~0.12.1", 25 | "grunt-newer": "~1.1.0", 26 | "grunt-ng-annotate": "~0.9.2", 27 | "grunt-ng-constant": "^1.0.0", 28 | "grunt-usemin": "~3.0.0", 29 | "grunt-wiredep": "^2.0.0", 30 | "ionic": "^1.7.12", 31 | "jshint-stylish": "~1.0.0", 32 | "karma": "~0.13.15", 33 | "karma-chai": "~0.1.0", 34 | "karma-chrome-launcher": "~0.2.2", 35 | "karma-coverage": "~0.5.3", 36 | "karma-mocha": "~0.2.1", 37 | "karma-phantomjs-launcher": "~0.2.1", 38 | "load-grunt-tasks": "~3.1.0", 39 | "lodash": "~3.10.1", 40 | "mkdirp": "~0.5.0", 41 | "ncp": "~1.0.1", 42 | "orchestrator": "~0.3.7", 43 | "plist": "^1.2.0", 44 | "ripple-emulator": "~0.9.24", 45 | "time-grunt": "~1.0.0", 46 | "win-spawn": "^2.0.0" 47 | }, 48 | "engines": { 49 | "node": ">=0.10.0" 50 | }, 51 | "scripts": { 52 | "test": "grunt test", 53 | "//": "Post installation.", 54 | "//": "Uncomment the next line to enable post install script.", 55 | "//": "There is always the option to run it manually.", 56 | "//": { "postinstall": "./install.sh" }, 57 | "//": { "postinstall": "./install.bat" } 58 | }, 59 | "cordovaPlatforms": [], 60 | "cordovaPlugins": [ 61 | "cordova-plugin-device", 62 | "cordova-plugin-console", 63 | "com.ionic.keyboard", 64 | "cordova-plugin-inappbrowser", 65 | "cordova-plugin-geolocation", 66 | { 67 | "locator": "https://github.com/EddyVerbruggen/SocialSharing-PhoneGap-Plugin.git", 68 | "id": "nl.x-services.plugins.socialsharing" 69 | }, 70 | { 71 | "locator": "https://github.com/katzer/cordova-plugin-email-composer.git", 72 | "id": "de.appplant.cordova.plugin.email-composer" 73 | }, 74 | "cordova-plugin-network-information", 75 | "cordova-plugin-whitelist", 76 | "cordova-plugin-transport-security" 77 | ] 78 | } 79 | -------------------------------------------------------------------------------- /package.json.local: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Supermodular", 3 | "version": "1.1.0", 4 | "private": true, 5 | "dependencies": {}, 6 | "devDependencies": { 7 | "cordova": "^5.4.1", 8 | "elementtree": "0.1.6", 9 | "glob": "~4.3.5", 10 | "grunt": "~0.4.5", 11 | "grunt-autoprefixer": "~2.2.0", 12 | "grunt-concurrent": "1.0.0", 13 | "grunt-contrib-clean": "~0.6.0", 14 | "grunt-contrib-concat": "~0.5.0", 15 | "grunt-contrib-connect": "~0.9.0", 16 | "grunt-contrib-copy": "~0.7.0", 17 | "grunt-contrib-cssmin": "~0.11.0", 18 | "grunt-contrib-htmlmin": "~0.3.0", 19 | "grunt-contrib-jshint": "~0.11.0", 20 | "grunt-contrib-sass": "^0.9.2", 21 | "grunt-contrib-uglify": "~0.7.0", 22 | "grunt-contrib-watch": "~0.6.1", 23 | "grunt-include-source": "^0.5.1", 24 | "grunt-karma": "~0.12.1", 25 | "grunt-newer": "~1.1.0", 26 | "grunt-ng-annotate": "~0.9.2", 27 | "grunt-ng-constant": "^1.0.0", 28 | "grunt-usemin": "~3.0.0", 29 | "grunt-wiredep": "^2.0.0", 30 | "ionic": "^1.7.12", 31 | "jshint-stylish": "~1.0.0", 32 | "karma": "~0.13.15", 33 | "karma-chai": "~0.1.0", 34 | "karma-chrome-launcher": "~0.2.2", 35 | "karma-coverage": "~0.5.3", 36 | "karma-mocha": "~0.2.1", 37 | "karma-phantomjs-launcher": "~0.2.1", 38 | "load-grunt-tasks": "~3.1.0", 39 | "lodash": "~3.10.1", 40 | "mkdirp": "~0.5.0", 41 | "ncp": "~1.0.1", 42 | "orchestrator": "~0.3.7", 43 | "plist": "^1.2.0", 44 | "ripple-emulator": "~0.9.24", 45 | "time-grunt": "~1.0.0", 46 | "win-spawn": "^2.0.0" 47 | }, 48 | "engines": { 49 | "node": ">=0.10.0" 50 | }, 51 | "scripts": { 52 | "test": "grunt test", 53 | "//": "Post installation.", 54 | "//": "Uncomment the next line to enable post install script.", 55 | "//": "There is always the option to run it manually.", 56 | "//": { "postinstall": "./install.sh" }, 57 | "//": { "postinstall": "./install.bat" } 58 | }, 59 | "cordovaPlatforms": [], 60 | "cordovaPlugins": [ 61 | "cordova-plugin-device", 62 | "cordova-plugin-console", 63 | "com.ionic.keyboard", 64 | "cordova-plugin-inappbrowser", 65 | "cordova-plugin-geolocation", 66 | { 67 | "locator": "https://github.com/EddyVerbruggen/SocialSharing-PhoneGap-Plugin.git", 68 | "id": "nl.x-services.plugins.socialsharing" 69 | }, 70 | { 71 | "locator": "https://github.com/katzer/cordova-plugin-email-composer.git", 72 | "id": "de.appplant.cordova.plugin.email-composer" 73 | }, 74 | "cordova-plugin-network-information", 75 | "cordova-plugin-whitelist", 76 | "cordova-plugin-transport-security" 77 | ] 78 | } 79 | -------------------------------------------------------------------------------- /resources/android/drawable-hdpi/ic_action_next_item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-hdpi/ic_action_next_item.png -------------------------------------------------------------------------------- /resources/android/drawable-hdpi/ic_action_previous_item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-hdpi/ic_action_previous_item.png -------------------------------------------------------------------------------- /resources/android/drawable-hdpi/ic_action_remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-hdpi/ic_action_remove.png -------------------------------------------------------------------------------- /resources/android/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /resources/android/drawable-land-hdpi/screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-land-hdpi/screen.png -------------------------------------------------------------------------------- /resources/android/drawable-land-ldpi/screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-land-ldpi/screen.png -------------------------------------------------------------------------------- /resources/android/drawable-land-mdpi/screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-land-mdpi/screen.png -------------------------------------------------------------------------------- /resources/android/drawable-land-xhdpi/screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-land-xhdpi/screen.png -------------------------------------------------------------------------------- /resources/android/drawable-ldpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-ldpi/icon.png -------------------------------------------------------------------------------- /resources/android/drawable-mdpi/ic_action_next_item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-mdpi/ic_action_next_item.png -------------------------------------------------------------------------------- /resources/android/drawable-mdpi/ic_action_previous_item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-mdpi/ic_action_previous_item.png -------------------------------------------------------------------------------- /resources/android/drawable-mdpi/ic_action_remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-mdpi/ic_action_remove.png -------------------------------------------------------------------------------- /resources/android/drawable-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-mdpi/icon.png -------------------------------------------------------------------------------- /resources/android/drawable-port-hdpi/screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-port-hdpi/screen.png -------------------------------------------------------------------------------- /resources/android/drawable-port-ldpi/screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-port-ldpi/screen.png -------------------------------------------------------------------------------- /resources/android/drawable-port-mdpi/screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-port-mdpi/screen.png -------------------------------------------------------------------------------- /resources/android/drawable-port-xhdpi/screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-port-xhdpi/screen.png -------------------------------------------------------------------------------- /resources/android/drawable-xhdpi/ic_action_next_item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-xhdpi/ic_action_next_item.png -------------------------------------------------------------------------------- /resources/android/drawable-xhdpi/ic_action_previous_item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-xhdpi/ic_action_previous_item.png -------------------------------------------------------------------------------- /resources/android/drawable-xhdpi/ic_action_remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-xhdpi/ic_action_remove.png -------------------------------------------------------------------------------- /resources/android/drawable-xhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-xhdpi/icon.png -------------------------------------------------------------------------------- /resources/android/drawable-xxhdpi/ic_action_next_item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-xxhdpi/ic_action_next_item.png -------------------------------------------------------------------------------- /resources/android/drawable-xxhdpi/ic_action_previous_item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-xxhdpi/ic_action_previous_item.png -------------------------------------------------------------------------------- /resources/android/drawable-xxhdpi/ic_action_remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable-xxhdpi/ic_action_remove.png -------------------------------------------------------------------------------- /resources/android/drawable/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/android/drawable/icon.png -------------------------------------------------------------------------------- /resources/ios/icons/icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/icons/icon-40.png -------------------------------------------------------------------------------- /resources/ios/icons/icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/icons/icon-40@2x.png -------------------------------------------------------------------------------- /resources/ios/icons/icon-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/icons/icon-50.png -------------------------------------------------------------------------------- /resources/ios/icons/icon-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/icons/icon-50@2x.png -------------------------------------------------------------------------------- /resources/ios/icons/icon-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/icons/icon-60.png -------------------------------------------------------------------------------- /resources/ios/icons/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/icons/icon-60@2x.png -------------------------------------------------------------------------------- /resources/ios/icons/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/icons/icon-60@3x.png -------------------------------------------------------------------------------- /resources/ios/icons/icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/icons/icon-72.png -------------------------------------------------------------------------------- /resources/ios/icons/icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/icons/icon-72@2x.png -------------------------------------------------------------------------------- /resources/ios/icons/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/icons/icon-76.png -------------------------------------------------------------------------------- /resources/ios/icons/icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/icons/icon-76@2x.png -------------------------------------------------------------------------------- /resources/ios/icons/icon-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/icons/icon-small.png -------------------------------------------------------------------------------- /resources/ios/icons/icon-small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/icons/icon-small@2x.png -------------------------------------------------------------------------------- /resources/ios/icons/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/icons/icon.png -------------------------------------------------------------------------------- /resources/ios/icons/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/icons/icon@2x.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-568h@2x~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/splash/Default-568h@2x~iphone.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-667h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/splash/Default-667h.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-736h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/splash/Default-736h.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Landscape-736h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/splash/Default-Landscape-736h.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Landscape@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/splash/Default-Landscape@2x~ipad.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Landscape~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/splash/Default-Landscape~ipad.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Portrait@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/splash/Default-Portrait@2x~ipad.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Portrait~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/splash/Default-Portrait~ipad.png -------------------------------------------------------------------------------- /resources/ios/splash/Default@2x~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/splash/Default@2x~iphone.png -------------------------------------------------------------------------------- /resources/ios/splash/Default~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appseed-io/supermodular/1c165275bf7efc7be0c91ea7e08f8c56a69197f0/resources/ios/splash/Default~iphone.png -------------------------------------------------------------------------------- /test/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": true, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "immed": true, 10 | "indent": 2, 11 | "latedef": true, 12 | "newcap": true, 13 | "noarg": true, 14 | "quotmark": "single", 15 | "regexp": true, 16 | "undef": true, 17 | "unused": true, 18 | "strict": true, 19 | "trailing": true, 20 | "smarttabs": true, 21 | "globals": { 22 | "after": false, 23 | "afterEach": false, 24 | "angular": false, 25 | "before": false, 26 | "beforeEach": false, 27 | "browser": false, 28 | "describe": false, 29 | "expect": false, 30 | "inject": false, 31 | "it": false, 32 | "jasmine": false, 33 | "spyOn": false 34 | } 35 | } 36 | --------------------------------------------------------------------------------