<commit_before>/*
	The MIT License (MIT)

	Copyright (c) 2014 Julian Xhokaxhiu

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
	SOFTWARE.
*/
module.exports = function(grunt) {

	// Load Tasks
    require('load-grunt-tasks')(grunt);

    // Configure the tasks
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        app: grunt.file.readJSON('app.json'),
        cssMin: 'css/<%= pkg.name %>.min.<%= getCurrentDate() %>.css',
        cssPrintMin: 'css/<%= pkg.name %>.min.<%= getCurrentDate() %>.print.css',
        jsMin: 'js/<%= pkg.name %>.min.<%= getCurrentDate() %>.js',
        getCurrentDate: function() {
            var date = new Date();
            return date.getDate() + '-' + ( date.getMonth() + 1 ) + '-' + date.getFullYear();
        },
        clean: {
            options: {
                force: true
            },
            output: [
                '<%= app.config.output.path %>/*',
                'tpl/scss/_<%= pkg.name %>-icons.scss'
            ],
            cssFiles: [
                'tpl/css/99_<%= pkg.name %>.css',
                'tpl/css-print/99_<%= pkg.name %>.css'
            ],
            mapFiles: [
            	'tpl/css/*.map',
                'tpl/css/*.map',
            ],
            webfonts: [
            	'webfonts/'
            ],
            webicons: [
            	'webicons/'
            ]
        },
        tasty_swig: {
        	build: {
        		options: {
            		context: {
            			app: {
			                name: '<%= pkg.name %>',
			                liveReloadHost: '<%= app.config.livereload.host %>:<%= app.config.livereload.port %>',
			                cssFiles: {
			                    'screen': grunt.file.expand({
			                        filter: 'isFile',
			                        cwd: 'tpl/'
			                    }, 'css/**/*.css'),
			                    'print': grunt.file.expand({
			                        filter: 'isFile',
			                        cwd: 'tpl/'
			                    }, 'css-print/**/*.css')
			                },
			                jsFiles: [ '<%= jsMin %>' ],
			                data: '<%= app.data %>'
			            }
            		}
            	},
				src: [ 'tpl/*.swig' ],
				dest: '<%= app.config.output.path %>/'
			},
			deploy: {
				options: {
            		context: {
            			app: {
			                name: '<%= pkg.name %>',
			                liveReloadHost: false,
			                cssFiles: {
			                    'screen': [ '<%= cssMin %>' ],
								'print': [ '<%= cssPrintMin %>' ]
			                },
			                jsFiles: [ '<%= jsMin %>' ],
			                data: '<%= app.data %>'
			            }
            		}
            	},
				src: [ 'tpl/*.swig' ],
				dest: '<%= app.config.output.path %>/'
			}
        },
		sass: {
            options: {
                style: 'compressed'
            },
			build: {
				files: {
					'tpl/css/99_<%= pkg.name %>.css' : [ 'tpl/scss/screen.scss' ],
					'tpl/css-print/99_<%= pkg.name %>.css' : [ 'tpl/scss/print.scss' ]
				}
			}
		},
		fontgen: {
			build: {
				options: {
					path_prefix: '../fonts/'
				},
				files: {
					'webfonts/' : [
		            	'fonts/*.otf',
						'fonts/*.ttf'
		            ]
				}
			}
		},
		webfont: {
			icons: {
				src: 'icons/*.svg',
				dest: 'webicons/',
                destCss: 'tpl/scss/',
				options: {
					template: 'tpl/icons.css',
                    relativeFontPath: '../fonts/',
					font: '<%= pkg.name %>-icons',
                    stylesheet: 'scss',
                    htmlDemo: false,
                    templateOptions: {
                        baseClass: '<%= pkg.name %>-icon',
                        classPrefix: '<%= pkg.name %>-icon-',
                        mixinPrefix: '<%= pkg.name %>-icon-'
                    }
				}
			}
		},
        concat: {
        	webfonts: {
        		files: {
        			'tpl/css/98_webfonts.css' : [ 'webfonts/*.css' ],
        			'tpl/css-print/98_webfonts.css' : [ 'webfonts/*.css' ]
        		}
        	},
            css: {
                filter: 'isFile',
                src: 'tpl/css/**/*.css',
                dest: '<%= app.config.output.path %>/<%= cssMin %>'
            },
            cssPrint: {
                filter: 'isFile',
                src: 'tpl/css-print/**/*.css',
                dest: '<%= app.config.output.path %>/<%= cssPrintMin %>'
            },
            js: {
            	files: {
            		'<%= app.config.output.path %>/<%= jsMin %>' : '<%= app.assets.js %>'
            	}
            }
        },
        autoprefixer: {
            options: {
                browsers: [
                    "Android 2.3",
                    "Android >= 4",
                    "Chrome >= 20",
                    "Firefox >= 24",
                    "Explorer >= 8",
                    "iOS >= 6",
                    "Opera >= 12",
                    "Safari >= 6"
                ]
            },
            build: {
            	options: {
            		map: true
            	},
                src: '<%= app.config.output.path %>/css/*.css'
            },
            deploy: {
            	options: {
            		map: false
            	},
            	src: '<%= app.config.output.path %>/css/*.css'
            }
        },
        cssmin: {
            build: {
                files: {
                	'<%= app.config.output.path %>/<%= cssMin %>' : [ '<%= app.config.output.path %>/<%= cssMin %>' ],
                	'<%= app.config.output.path %>/<%= cssPrintMin %>' : [ '<%= app.config.output.path %>/<%= cssPrintMin %>' ]
                }
            }
        },
        closurecompiler: {
            build: {
            	files: {
            		'<%= app.config.output.path %>/<%= jsMin %>': '<%= app.assets.js %>'
            	},
            	options: {
	                // Any options supported by Closure Compiler, for example:
	                "compilation_level": "SIMPLE_OPTIMIZATIONS",

	                // Plus a simultaneous processes limit
	                "max_processes": 5,
	            }
            }
        },
        copy: {
            build: {
                files: [
                    // The project CSS and JS files
                    {
                        expand: true,
                        cwd: 'tpl/',
                        src: [
                            'css/**/*.css',
                            'css-print/**/*.css',
                            'css/**/*.map',
                            'css-print/**/*.map',
                            'js/**/*.js'
                        ],
                        dest: '<%= app.config.output.path %>/'
                    }
                ]
            },
            deploy: {
                files: [
                	// External Packages Fonts
                	{
                		expand: true,
                		flatten: true,
                		src: '<%= app.assets.fonts %>',
                		dest: '<%= app.config.output.path %>/fonts/'
                	},
                	// The project Webfonts
                	{
                		expand: true,
                		flatten: true,
                		cwd: 'webfonts/',
                		src: ['**/*.{ttf,woff,eot,svg,otf}'],
                		dest: '<%= app.config.output.path %>/fonts/'
                	},
                	// The project Webicons
                	{
                		expand: true,
                		flatten: true,
                		cwd: 'webicons/',
                		src: ['**/*.{ttf,woff,eot,svg,otf}'],
                		dest: '<%= app.config.output.path %>/fonts/'
                	},
                	// Webicons sass generated file
                	{
                        expand: true,
                        cwd: 'webicons/',
                        src: [
                            '*.scss'
                        ],
                        dest: 'tpl/scss/'
                    },
                	// The project resource files
                    {
                        expand: true,
                        cwd: 'rsc/',
                        src: ['**'],
                        dest: '<%= app.config.output.path %>/'
                    }
                ]
            },
            typo3: {
            	files: [
            		// Icons
            		{
            			expand: true,
              		flatten: true,
              		cwd: 'icons/',
              		src: [ '*.svg' ],
              		dest: '<%= app.config.typo3.path %>/<%= pkg.name %><%= app.config.typo3.suffix %>/Resources/Private/Icons/'
            		},
                // Icons CSS template
                {
                  expand: true,
                  flatten: true,
                  cwd: 'tpl/',
                  src: [ 'icons.css' ],
                  dest: '<%= app.config.typo3.path %>/<%= pkg.name %><%= app.config.typo3.suffix %>/Resources/Private/'
                },
              	// Fonts
              	{
              		expand: true,
              		flatten: true,
              		cwd: 'fonts/',
              		src: [ '*' ],
              		dest: '<%= app.config.typo3.path %>/<%= pkg.name %><%= app.config.typo3.suffix %>/Resources/Private/Fonts/'
              	},
              	// Images
              	{
                  expand: true,
                  cwd: 'rsc/img',
                  src: [ '**/*' ],
                  dest: '<%= app.config.typo3.path %>/<%= pkg.name %><%= app.config.typo3.suffix %>/Resources/Private/Images/'
                },
              	// HTML
                {
                  expand: true,
                  flatten: true,
                  cwd: '<%= app.config.output.path %>/',
                  src: ['*.html'],
                  dest: '<%= app.config.typo3.path %>/<%= pkg.name %><%= app.config.typo3.suffix %>/Resources/Private/Templates/Html/'
                },
                // SCSS
                {
                  expand: true,
                  flatten: true,
                  cwd: 'tpl/scss/',
                  src: ['*.scss'],
                  dest: '<%= app.config.typo3.path %>/<%= pkg.name %><%= app.config.typo3.suffix %>/Resources/Private/Scss/'
                },
                // Javascript
                {
                	expand: true,
                  flatten: true,
                  cwd: 'tpl/js/',
                  src: ['*.js'],
                  dest: '<%= app.config.typo3.path %>/<%= pkg.name %><%= app.config.typo3.suffix %>/Resources/Private/JavaScript/'
                },
                // Bower + App configuration
                {
                  expand: true,
                  flatten: true,
                	src: [ 'app.json', 'bower.json', 'package.json' ],
                	dest: '<%= app.config.typo3.path %>/<%= pkg.name %><%= app.config.typo3.suffix %>/'
                },
                /// Typo3 related stuff
                {
                  expand: true,
                  flatten: true,
                  dot: true,
                  cwd: '_typo3/',
                  src: [ '*' ],
                  dest: '<%= app.config.typo3.path %>/<%= pkg.name %><%= app.config.typo3.suffix %>/'
                }
              ]
            }
        },
        watch: {
        	options: {
        		livereload: '<%= app.config.livereload.port %>'
        	},
            html: {
                files: [
                    'tpl/**/*.swig',
                    'app.json'
                ],
                tasks: [
                	'rebuild:html'
                ]
            },
            css: {
                files: [
                    'tpl/**/*.scss',
                ],
                tasks: [
                    'rebuild:css'
                ]
            },
            js: {
                files: [
                    'tpl/**/*.js'
                ],
                tasks: [
                    'rebuild:js'
                ]
            }
        },
        rsync: {
            options: {
                recursive: true,
                deleteAll: true
            },
            deploy: {
                options: {
                    src: '<%= app.config.output.path %>/',
                    dest: '<%= app.config.deploy.path %>',
                    host: '<%= app.config.deploy.host %>'
                }
            }
        },
        connect: {
			build: {
				options: {
					port: '<%= app.config.server.port %>',
					hostname: '*',
					base: '<%= app.config.output.path %>/'
				}
			}
		},
        exec: {
            npm_update: {
                cmd: 'npm update'
            },
            bower_update: {
                cmd: 'bower update'
            },
            npm_install: {
                cmd: 'npm install'
            },
            bower_install: {
                cmd: 'bower install'
            }
        },
        periodic: {
            update: {
                when: 'daily',
                tasks: [
                    'exec:npm_update',
                    'exec:bower_update'
                ]
            },
            npm_install: {
                when: 'newer',
                tasks: [
                    'exec:npm_install',
                    'exec:npm_update'
                ],
                files: [{
                    src: [ 'package.json' ]
                }]
            },
            bower_install: {
                when: 'newer',
                tasks: [
                    'exec:bower_install',
                    'exec:bower_update'
                ],
                files: [{
                    src: [ 'bower.json' ]
                }]
            }
        }
    });

    grunt.registerTask('default', 'Gruntfile for Mockups', function() {
        grunt.warn('No task name specified.\n\nAvailable tasks: build, deploy, server, typo3"\n\n');
    });

    grunt.registerTask('server', 'Serve an already built mockup', [
    	'connect:build:keepalive'
    ]);

    grunt.registerTask('build', 'Build a mockup and watch for file modifications', [
		'rebuild',
		'watch'
    ]);

    grunt.registerTask('rebuild', 'Build a mockup without watching for file modifications', function ( watchTask ) {
        var tasks = [];

        if ( watchTask === undefined ) watchTask = 'all';

        if ( watchTask == 'all' ) {
            tasks = tasks.concat([
                'periodic',
                'clean',
                'fontgen',
                'webfont',
                'concat:webfonts',
                'sass',
                'concat:js',
                'tasty_swig:build',
                'copy:deploy',
                'copy:build',
                'autoprefixer:build',
                'clean:mapFiles',
                'clean:webfonts',
                'clean:webicons'
            ]);
            if ( grunt.config.get('app').config.server.port > -1 )
                tasks = tasks.concat([
                	'connect:build'
                ]);
        } else if ( watchTask == 'html' ) {
            tasks = tasks.concat([
                'tasty_swig:build',
                'copy:deploy',
                'copy:build'
            ]);
        } else if ( watchTask == 'css' ) {
            tasks = tasks.concat([
                'clean:cssFiles',
                'sass',
                'copy:deploy',
                'copy:build',
                'autoprefixer:build'
            ]);
        } else if ( watchTask == 'js' ) {
            tasks = tasks.concat([
                'concat:js',
                'copy:deploy',
                'copy:build'
            ]);
        }
        grunt.task.run(tasks);
    });

    grunt.registerTask('build_deploy', 'Build a mockup ready for deployment sync', [
    	'clean',
        'fontgen',
        'webfont',
        'concat:webfonts',
        'sass',
        'concat:css',
        'concat:cssPrint',
        'cssmin',
        'closurecompiler',
        'tasty_swig:deploy',
        'copy:deploy',
        'autoprefixer:deploy',
        'clean:mapFiles',
        'clean:webfonts',
        'clean:webicons'
    ]);

    grunt.registerTask('deploy', 'Deploy a mockup to the Mockups Server', [
		'build_deploy',
		'rsync:deploy'
    ]);

    grunt.registerTask('typo3', 'Create a TYPO3 extension based on the current output of the mockup', [
    	'build_deploy',
    	'copy:typo3'
    ])
};
<commit_msg>Allow SASS paths to be typed as "relative to current project directory"<commit_after>/*
	The MIT License (MIT)

	Copyright (c) 2014 Julian Xhokaxhiu

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
	SOFTWARE.
*/
module.exports = function(grunt) {

	// Load Tasks
    require('load-grunt-tasks')(grunt);

    // Configure the tasks
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        app: grunt.file.readJSON('app.json'),
        cssMin: 'css/<%= pkg.name %>.min.<%= getCurrentDate() %>.css',
        cssPrintMin: 'css/<%= pkg.name %>.min.<%= getCurrentDate() %>.print.css',
        jsMin: 'js/<%= pkg.name %>.min.<%= getCurrentDate() %>.js',
        getCurrentDate: function() {
            var date = new Date();
            return date.getDate() + '-' + ( date.getMonth() + 1 ) + '-' + date.getFullYear();
        },
        clean: {
            options: {
                force: true
            },
            output: [
                '<%= app.config.output.path %>/*',
                'tpl/scss/_<%= pkg.name %>-icons.scss'
            ],
            cssFiles: [
                'tpl/css/99_<%= pkg.name %>.css',
                'tpl/css-print/99_<%= pkg.name %>.css'
            ],
            mapFiles: [
            	'tpl/css/*.map',
                'tpl/css/*.map',
            ],
            webfonts: [
            	'webfonts/'
            ],
            webicons: [
            	'webicons/'
            ]
        },
        tasty_swig: {
        	build: {
        		options: {
            		context: {
            			app: {
			                name: '<%= pkg.name %>',
			                liveReloadHost: '<%= app.config.livereload.host %>:<%= app.config.livereload.port %>',
			                cssFiles: {
			                    'screen': grunt.file.expand({
			                        filter: 'isFile',
			                        cwd: 'tpl/'
			                    }, 'css/**/*.css'),
			                    'print': grunt.file.expand({
			                        filter: 'isFile',
			                        cwd: 'tpl/'
			                    }, 'css-print/**/*.css')
			                },
			                jsFiles: [ '<%= jsMin %>' ],
			                data: '<%= app.data %>'
			            }
            		}
            	},
				src: [ 'tpl/*.swig' ],
				dest: '<%= app.config.output.path %>/'
			},
			deploy: {
				options: {
            		context: {
            			app: {
			                name: '<%= pkg.name %>',
			                liveReloadHost: false,
			                cssFiles: {
			                    'screen': [ '<%= cssMin %>' ],
								'print': [ '<%= cssPrintMin %>' ]
			                },
			                jsFiles: [ '<%= jsMin %>' ],
			                data: '<%= app.data %>'
			            }
            		}
            	},
				src: [ 'tpl/*.swig' ],
				dest: '<%= app.config.output.path %>/'
			}
        },
		sass: {
            options: {
                style: 'compressed',
                loadPath: '.'
            },
			build: {
				files: {
					'tpl/css/99_<%= pkg.name %>.css' : [ 'tpl/scss/screen.scss' ],
					'tpl/css-print/99_<%= pkg.name %>.css' : [ 'tpl/scss/print.scss' ]
				}
			}
		},
		fontgen: {
			build: {
				options: {
					path_prefix: '../fonts/'
				},
				files: {
					'webfonts/' : [
		            	'fonts/*.otf',
						'fonts/*.ttf'
		            ]
				}
			}
		},
		webfont: {
			icons: {
				src: 'icons/*.svg',
				dest: 'webicons/',
                destCss: 'tpl/scss/',
				options: {
					template: 'tpl/icons.css',
                    relativeFontPath: '../fonts/',
					font: '<%= pkg.name %>-icons',
                    stylesheet: 'scss',
                    htmlDemo: false,
                    templateOptions: {
                        baseClass: '<%= pkg.name %>-icon',
                        classPrefix: '<%= pkg.name %>-icon-',
                        mixinPrefix: '<%= pkg.name %>-icon-'
                    }
				}
			}
		},
        concat: {
        	webfonts: {
        		files: {
        			'tpl/css/98_webfonts.css' : [ 'webfonts/*.css' ],
        			'tpl/css-print/98_webfonts.css' : [ 'webfonts/*.css' ]
        		}
        	},
            css: {
                filter: 'isFile',
                src: 'tpl/css/**/*.css',
                dest: '<%= app.config.output.path %>/<%= cssMin %>'
            },
            cssPrint: {
                filter: 'isFile',
                src: 'tpl/css-print/**/*.css',
                dest: '<%= app.config.output.path %>/<%= cssPrintMin %>'
            },
            js: {
            	files: {
            		'<%= app.config.output.path %>/<%= jsMin %>' : '<%= app.assets.js %>'
            	}
            }
        },
        autoprefixer: {
            options: {
                browsers: [
                    "Android 2.3",
                    "Android >= 4",
                    "Chrome >= 20",
                    "Firefox >= 24",
                    "Explorer >= 8",
                    "iOS >= 6",
                    "Opera >= 12",
                    "Safari >= 6"
                ]
            },
            build: {
            	options: {
            		map: true
            	},
                src: '<%= app.config.output.path %>/css/*.css'
            },
            deploy: {
            	options: {
            		map: false
            	},
            	src: '<%= app.config.output.path %>/css/*.css'
            }
        },
        cssmin: {
            build: {
                files: {
                	'<%= app.config.output.path %>/<%= cssMin %>' : [ '<%= app.config.output.path %>/<%= cssMin %>' ],
                	'<%= app.config.output.path %>/<%= cssPrintMin %>' : [ '<%= app.config.output.path %>/<%= cssPrintMin %>' ]
                }
            }
        },
        closurecompiler: {
            build: {
            	files: {
            		'<%= app.config.output.path %>/<%= jsMin %>': '<%= app.assets.js %>'
            	},
            	options: {
	                // Any options supported by Closure Compiler, for example:
	                "compilation_level": "SIMPLE_OPTIMIZATIONS",

	                // Plus a simultaneous processes limit
	                "max_processes": 5,
	            }
            }
        },
        copy: {
            build: {
                files: [
                    // The project CSS and JS files
                    {
                        expand: true,
                        cwd: 'tpl/',
                        src: [
                            'css/**/*.css',
                            'css-print/**/*.css',
                            'css/**/*.map',
                            'css-print/**/*.map',
                            'js/**/*.js'
                        ],
                        dest: '<%= app.config.output.path %>/'
                    }
                ]
            },
            deploy: {
                files: [
                	// External Packages Fonts
                	{
                		expand: true,
                		flatten: true,
                		src: '<%= app.assets.fonts %>',
                		dest: '<%= app.config.output.path %>/fonts/'
                	},
                	// The project Webfonts
                	{
                		expand: true,
                		flatten: true,
                		cwd: 'webfonts/',
                		src: ['**/*.{ttf,woff,eot,svg,otf}'],
                		dest: '<%= app.config.output.path %>/fonts/'
                	},
                	// The project Webicons
                	{
                		expand: true,
                		flatten: true,
                		cwd: 'webicons/',
                		src: ['**/*.{ttf,woff,eot,svg,otf}'],
                		dest: '<%= app.config.output.path %>/fonts/'
                	},
                	// Webicons sass generated file
                	{
                        expand: true,
                        cwd: 'webicons/',
                        src: [
                            '*.scss'
                        ],
                        dest: 'tpl/scss/'
                    },
                	// The project resource files
                    {
                        expand: true,
                        cwd: 'rsc/',
                        src: ['**'],
                        dest: '<%= app.config.output.path %>/'
                    }
                ]
            },
            typo3: {
            	files: [
            		// Icons
            		{
            			expand: true,
              		flatten: true,
              		cwd: 'icons/',
              		src: [ '*.svg' ],
              		dest: '<%= app.config.typo3.path %>/<%= pkg.name %><%= app.config.typo3.suffix %>/Resources/Private/Icons/'
            		},
                // Icons CSS template
                {
                  expand: true,
                  flatten: true,
                  cwd: 'tpl/',
                  src: [ 'icons.css' ],
                  dest: '<%= app.config.typo3.path %>/<%= pkg.name %><%= app.config.typo3.suffix %>/Resources/Private/'
                },
              	// Fonts
              	{
              		expand: true,
              		flatten: true,
              		cwd: 'fonts/',
              		src: [ '*' ],
              		dest: '<%= app.config.typo3.path %>/<%= pkg.name %><%= app.config.typo3.suffix %>/Resources/Private/Fonts/'
              	},
              	// Images
              	{
                  expand: true,
                  cwd: 'rsc/img',
                  src: [ '**/*' ],
                  dest: '<%= app.config.typo3.path %>/<%= pkg.name %><%= app.config.typo3.suffix %>/Resources/Private/Images/'
                },
              	// HTML
                {
                  expand: true,
                  flatten: true,
                  cwd: '<%= app.config.output.path %>/',
                  src: ['*.html'],
                  dest: '<%= app.config.typo3.path %>/<%= pkg.name %><%= app.config.typo3.suffix %>/Resources/Private/Templates/Html/'
                },
                // SCSS
                {
                  expand: true,
                  flatten: true,
                  cwd: 'tpl/scss/',
                  src: ['*.scss'],
                  dest: '<%= app.config.typo3.path %>/<%= pkg.name %><%= app.config.typo3.suffix %>/Resources/Private/Scss/'
                },
                // Javascript
                {
                	expand: true,
                  flatten: true,
                  cwd: 'tpl/js/',
                  src: ['*.js'],
                  dest: '<%= app.config.typo3.path %>/<%= pkg.name %><%= app.config.typo3.suffix %>/Resources/Private/JavaScript/'
                },
                // Bower + App configuration
                {
                  expand: true,
                  flatten: true,
                	src: [ 'app.json', 'bower.json', 'package.json' ],
                	dest: '<%= app.config.typo3.path %>/<%= pkg.name %><%= app.config.typo3.suffix %>/'
                },
                /// Typo3 related stuff
                {
                  expand: true,
                  flatten: true,
                  dot: true,
                  cwd: '_typo3/',
                  src: [ '*' ],
                  dest: '<%= app.config.typo3.path %>/<%= pkg.name %><%= app.config.typo3.suffix %>/'
                }
              ]
            }
        },
        watch: {
        	options: {
        		livereload: '<%= app.config.livereload.port %>'
        	},
            html: {
                files: [
                    'tpl/**/*.swig',
                    'app.json'
                ],
                tasks: [
                	'rebuild:html'
                ]
            },
            css: {
                files: [
                    'tpl/**/*.scss',
                ],
                tasks: [
                    'rebuild:css'
                ]
            },
            js: {
                files: [
                    'tpl/**/*.js'
                ],
                tasks: [
                    'rebuild:js'
                ]
            }
        },
        rsync: {
            options: {
                recursive: true,
                deleteAll: true
            },
            deploy: {
                options: {
                    src: '<%= app.config.output.path %>/',
                    dest: '<%= app.config.deploy.path %>',
                    host: '<%= app.config.deploy.host %>'
                }
            }
        },
        connect: {
			build: {
				options: {
					port: '<%= app.config.server.port %>',
					hostname: '*',
					base: '<%= app.config.output.path %>/'
				}
			}
		},
        exec: {
            npm_update: {
                cmd: 'npm update'
            },
            bower_update: {
                cmd: 'bower update'
            },
            npm_install: {
                cmd: 'npm install'
            },
            bower_install: {
                cmd: 'bower install'
            }
        },
        periodic: {
            update: {
                when: 'daily',
                tasks: [
                    'exec:npm_update',
                    'exec:bower_update'
                ]
            },
            npm_install: {
                when: 'newer',
                tasks: [
                    'exec:npm_install',
                    'exec:npm_update'
                ],
                files: [{
                    src: [ 'package.json' ]
                }]
            },
            bower_install: {
                when: 'newer',
                tasks: [
                    'exec:bower_install',
                    'exec:bower_update'
                ],
                files: [{
                    src: [ 'bower.json' ]
                }]
            }
        }
    });

    grunt.registerTask('default', 'Gruntfile for Mockups', function() {
        grunt.warn('No task name specified.\n\nAvailable tasks: build, deploy, server, typo3"\n\n');
    });

    grunt.registerTask('server', 'Serve an already built mockup', [
    	'connect:build:keepalive'
    ]);

    grunt.registerTask('build', 'Build a mockup and watch for file modifications', [
		'rebuild',
		'watch'
    ]);

    grunt.registerTask('rebuild', 'Build a mockup without watching for file modifications', function ( watchTask ) {
        var tasks = [];

        if ( watchTask === undefined ) watchTask = 'all';

        if ( watchTask == 'all' ) {
            tasks = tasks.concat([
                'periodic',
                'clean',
                'fontgen',
                'webfont',
                'concat:webfonts',
                'sass',
                'concat:js',
                'tasty_swig:build',
                'copy:deploy',
                'copy:build',
                'autoprefixer:build',
                'clean:mapFiles',
                'clean:webfonts',
                'clean:webicons'
            ]);
            if ( grunt.config.get('app').config.server.port > -1 )
                tasks = tasks.concat([
                	'connect:build'
                ]);
        } else if ( watchTask == 'html' ) {
            tasks = tasks.concat([
                'tasty_swig:build',
                'copy:deploy',
                'copy:build'
            ]);
        } else if ( watchTask == 'css' ) {
            tasks = tasks.concat([
                'clean:cssFiles',
                'sass',
                'copy:deploy',
                'copy:build',
                'autoprefixer:build'
            ]);
        } else if ( watchTask == 'js' ) {
            tasks = tasks.concat([
                'concat:js',
                'copy:deploy',
                'copy:build'
            ]);
        }
        grunt.task.run(tasks);
    });

    grunt.registerTask('build_deploy', 'Build a mockup ready for deployment sync', [
    	'clean',
        'fontgen',
        'webfont',
        'concat:webfonts',
        'sass',
        'concat:css',
        'concat:cssPrint',
        'cssmin',
        'closurecompiler',
        'tasty_swig:deploy',
        'copy:deploy',
        'autoprefixer:deploy',
        'clean:mapFiles',
        'clean:webfonts',
        'clean:webicons'
    ]);

    grunt.registerTask('deploy', 'Deploy a mockup to the Mockups Server', [
		'build_deploy',
		'rsync:deploy'
    ]);

    grunt.registerTask('typo3', 'Create a TYPO3 extension based on the current output of the mockup', [
    	'build_deploy',
    	'copy:typo3'
    ])
};
<|endoftext|>


<commit_before>const UserProfile = require("../lib/Structures/UserProfile");
module.exports = {
    exec: async function (msg, args) {
        let [action, ...rest] = args.split(" ");
        let a = rest.join(" ");
        if (!action) return cmds["help"].exec(msg, "profile");
        async function remove() {
            if (!msg.userProfile) return msg.channel.createMessage(msg.t("PROFILE_NONEXISTENT"));
            else {
                await db.table("profile").get(msg.author.id).delete();
                msg.channel.createMessage(msg.t("PROFILE_DELETED"));
            }
        }

        async function setup() {
            if (msg.userProfile) return;
            let data = {
                id: msg.author.id,
                profileFields: [],
                color: null,
                timezone: "UTC",
                locale: "en"
            };
            let color = a;
            let num;
            if (color.startsWith("#")) color = color.slice(1);
            if (color) num = new Number(`0x${color.substring(0, 6)}`);
            if (num && isNaN(num)) return msg.channel.createMessage(msg.t("INVALID_COLOR"));
            data.color = num ? num.toString() : "";
            await db.table("profile").insert(UserProfile.create(data));
            await msg.channel.createMessage(msg.t("PROFILE_CREATED"));
        }
        async function show() {
            let query = a;
            let user;
            try {
                user = await userQuery(query || msg.author.id, msg, true);
            } catch (e) {
                return;
            }
            if (user.bot) return msg.channel.createMessage(msg.t("BOT_PROFILE"));
            let profileData = await db.table("profile").get(user.id);
            if (!profileData) return msg.channel.createMessage(msg.t("PROFILE_SPECIFIC_NONEXISTENT", bot.getTag(user)));
            let profile = new UserProfile(profileData);
            return msg.channel.createMessage({
                embed: {
                    author: {
                        name: msg.t("USER_PROFILE", bot.getTag(user)),
                        icon_url: user.user.staticAvatarURL
                    },
                    fields: (profile.profileFields && profile.profileFields.length > 0) ? profile.profileFields : [{
                        name: "<:xmark:314349398824058880>",
                        value: msg.t("NO_PROFILE_FIELDS"),
                        inline: true
                    }],
                    color: parseInt(profile.color)
                }
            });
        }

        async function color() {
            if (!msg.userProfile) return msg.channel.createMessage(msg.t("PROFILE_NONEXISTENT"));
            let color = a;
            if (color.startsWith("#")) color = color.slice(1);
            if (!color) return msg.channel.createMessage(msg.t("ARGS_MISSING"));
            let n;

            if (color) n = new Number(`0x${color.substring(0, 6)}`);
            if (n && isNaN(n)) return msg.channel.createMessage(msg.t("INVALID_COLOR"));
            msg.userProfile.color = n.toString();
            await db.table("profile").get(msg.author.id).update(msg.userProfile.toEncryptedObject());
            msg.channel.createMessage({
                content: ":ok_hand:",
                embed: {
                    color: msg.userProfile.color,
                    author: {
                        name: `${bot.getTag(msg.author)}`,
                        icon_url: msg.author.staticAvatarURL
                    },
                    description: "Lorum ispum dolor sit amet..."
                }
            });

        }

        async function fields() {
            if (!msg.userProfile) return msg.channel.createMessage(msg.t("PROFILE_NONEXISTENT"));
            const p = msg.userProfile;
            let arg = a;
            if (!arg) return msg.channel.createMessage(msg.t("ARGS_MISSING"));
            let [act, ...stuff] = arg.split(" ");
            let fieldsargs = stuff.join(" ").split("|");
            let fieldname = fieldsargs[0];
            let fielddata = fieldsargs.slice(1).join("|");
            switch (act) {
            default: {
                msg.channel.createMessage(":question: fields <add|del> <<name><|data, not required for del>>");
                break;
            }
            case "del": {
                if (p.profileFields.length == 0) return;
                let f = p.profileFields.find(f => f.name == fieldname);
                if (f) p.profileFields.splice(p.profileFields.indexOf(f), 1);
                else return msg.channel.createMessage(msg.t("FIELD_NONEXISTENT"));
                await db.table("profile").get(msg.author.id).update(p.toEncryptedObject());
                msg.channel.createMessage(msg.t("FIELD_DELETED", fieldname));
                break;
            }
            case "add": {
                if (p.profileFields && p.profileFields.length > 10) return;
                if (p.profileFields && p.profileFields.find(f => f.name.toLowerCase() == fieldname.toLowerCase())) return;
                p.profileFields.push({
                    name: fieldname,
                    value: fielddata,
                    inline: true
                });
                await db.table("profile").get(msg.author.id).update(p.toEncryptedObject());
                msg.channel.createMessage(msg.t("FIELD_CREATED", fieldname));
                break;
            }
            }
        }

        async function timezone() {
            if (!msg.userProfile) return msg.channel.createMessage(msg.t("PROFILE_NONEXISTENT"));
            let tzValue = a;
            if (!momentTz.tz.zone(tzValue)) return msg.channel.createMessage(msg.t("INVALID_TIMEZONE"));
            msg.userProfile.timezone = tzValue;
            await db.table("profile").get(msg.author.id).update(msg.userProfile.toEncryptedObject());
            msg.channel.createMessage(":ok_hand:");
        }

        async function locale() {
            if (!msg.userProfile) return msg.channel.createMessage(msg.t("PROFILE_NONEXISTENT"));
            if (!a) {
                const status = await calculateLocaleStatus();
                return msg.channel.createMessage(msg.t("PROFILE_LOCALE_LIST", msg.userProfile.locale, Object.keys(status).map(l => `${l} - ${status[l]}%`).join("\n")));
            }
            let lang = a;
            if (!bot.i18n.languages[lang]) return msg.channel.createMessage(msg.t("INVALID_LOCALE", lang));
            msg.userProfile.locale = lang;
            await db.table("profile").get(msg.author.id).update(msg.userProfile.toEncryptedObject());
            msg.channel.createMessage(msg.t("LOCALE_SET", `${lang} (${msg.t("NATIVE_LOCALE_NAME")}/${msg.t("ENGLISH_LOCALE_NAME")})`));
        }

        async function calculateLocaleStatus() {
            let s = {};
            for (const [l, k] of Object.entries(bot.i18n.languages)) {
                if (!bot.i18n.languages.hasOwnProperty(l)) continue;
                if (l === "en") {
                    s["en"] = (100).toFixed(2);
                    continue;
                }
                const terms = Object.keys(bot.i18n.languages.en);
                const termsInForeignLang = terms.filter(l => k.hasOwnProperty(l)).length; // Removes stuff that don't exist
                s[l] = ((termsInForeignLang / terms.length) * 100).toFixed(2);
            }
            return s;
        }
        switch (action) {
        case "remove": {
            await remove();
            break;
        }
        case "setup": {
            await setup();
            break;
        }
        case "show": {
            await show();
            break;
        }
        case "color": {
            await color();
            break;
        }
        case "fields": {
            await fields();
            break;
        }
        case "timezone": {
            await timezone();
            break;
        }
        case "locale": {
            await locale();
            break;
        }
        }
    },
    isCmd: true,
    display: true,
    category: 1,
    description: "Manages the information we know about you.\nYou can see what locales we support [here](https://github.com/tt-bot-dev/languages)",
    args: "<show [user]|setup [color]|fields <del|add> <<name><|data, not required for del>>|remove|color <color>|locale [locale]>"
};<commit_msg>Remove old profile<commit_after><|endoftext|>


<commit_before>import React, {PropTypes} from 'react';
import AutoRefresh from 'shared/components/AutoRefresh';
import LineGraph from 'shared/components/LineGraph';
import ReactGridLayout from 'react-grid-layout';
import _ from 'lodash';

const RefreshingLineGraph = AutoRefresh(LineGraph);

export const LayoutRenderer = React.createClass({
  propTypes: {
    timeRange: PropTypes.string.isRequired,
    cells: PropTypes.arrayOf(
      PropTypes.shape({
        queries: PropTypes.arrayOf(
          PropTypes.shape({
            rp: PropTypes.string.isRequired,
            text: PropTypes.string.isRequired,
            database: PropTypes.string.isRequired,
            groupbys: PropTypes.arrayOf(PropTypes.string),
            wheres: PropTypes.arrayOf(PropTypes.string),
          }).isRequired
        ).isRequired,
        x: PropTypes.number.isRequired,
        y: PropTypes.number.isRequired,
        w: PropTypes.number.isRequired,
        h: PropTypes.number.isRequired,
        i: PropTypes.string.isRequired,
        name: PropTypes.string.isRequired,
      }).isRequired
    ),
    autoRefreshMs: PropTypes.number.isRequired,
    host: PropTypes.string.isRequired,
    source: PropTypes.string,
  },

  getInitialState() {
    return ({
      layout: _.without(this.props.cells, ['queries']),
    });
  },

  generateGraphs() {
    const {timeRange, host, autoRefreshMs, source} = this.props;

    return this.props.cells.map((cell) => {
      const qs = cell.queries.map((q) => {
        let text = q.text;
        text += ` where \"host\" = '${host}' and time > ${timeRange}`;
        if (q.wheres && q.wheres.length > 0) {
          text += ` and ${q.wheres.join(' and ')}`;
        }
        if (q.groupbys && q.groupbys.length > 0) {
          text += ` group by ${q.groupbys.join(',')}`;
        }
        return {
          host: source,
          text,
        };
      });
      return (

{cell.name}

            <RefreshingLineGraph
              queries={qs}
              autoRefresh={autoRefreshMs}
            />

      );
    });
  },

  render() {
    return (
      <ReactGridLayout layout={this.state.layout} isDraggable={false} isResizable={false} cols={12} rowHeight={90} width={1200}>
        {this.generateGraphs()}
      </ReactGridLayout>
    );
  },
});

export default LayoutRenderer;
<commit_msg>Send along the db and rp to AutoRefresh<commit_after>import React, {PropTypes} from 'react';
import AutoRefresh from 'shared/components/AutoRefresh';
import LineGraph from 'shared/components/LineGraph';
import ReactGridLayout from 'react-grid-layout';
import _ from 'lodash';

const RefreshingLineGraph = AutoRefresh(LineGraph);

export const LayoutRenderer = React.createClass({
  propTypes: {
    timeRange: PropTypes.string.isRequired,
    cells: PropTypes.arrayOf(
      PropTypes.shape({
        queries: PropTypes.arrayOf(
          PropTypes.shape({
            rp: PropTypes.string.isRequired,
            text: PropTypes.string.isRequired,
            database: PropTypes.string.isRequired,
            groupbys: PropTypes.arrayOf(PropTypes.string),
            wheres: PropTypes.arrayOf(PropTypes.string),
          }).isRequired
        ).isRequired,
        x: PropTypes.number.isRequired,
        y: PropTypes.number.isRequired,
        w: PropTypes.number.isRequired,
        h: PropTypes.number.isRequired,
        i: PropTypes.string.isRequired,
        name: PropTypes.string.isRequired,
      }).isRequired
    ),
    autoRefreshMs: PropTypes.number.isRequired,
    host: PropTypes.string.isRequired,
    source: PropTypes.string,
  },

  getInitialState() {
    return ({
      layout: _.without(this.props.cells, ['queries']),
    });
  },

  generateGraphs() {
    const {timeRange, host, autoRefreshMs, source} = this.props;

    return this.props.cells.map((cell) => {
      const qs = cell.queries.map((q) => {
        let text = q.text;
        text += ` where \"host\" = '${host}' and time > ${timeRange}`;
        if (q.wheres && q.wheres.length > 0) {
          text += ` and ${q.wheres.join(' and ')}`;
        }
        if (q.groupbys && q.groupbys.length > 0) {
          text += ` group by ${q.groupbys.join(',')}`;
        }

        return Object.assign({}, q, {
          host: source,
          text,
        });
      });
      return (

{cell.name}

            <RefreshingLineGraph
              queries={qs}
              autoRefresh={autoRefreshMs}
            />

      );
    });
  },

  render() {
    return (
      <ReactGridLayout layout={this.state.layout} isDraggable={false} isResizable={false} cols={12} rowHeight={90} width={1200}>
        {this.generateGraphs()}
      </ReactGridLayout>
    );
  },
});

export default LayoutRenderer;
<|endoftext|>


<commit_before>/**
 * This library allows component wrapping in "card" elements.
 * (right now these are just divs of class "ceci-card").
 */
define(["ceci"], function(Ceci) {
  "use strict";

  var cardClass = "ceci-card";
  var cards = [];
  Ceci.currentCard = null;

  function showCard(card) {
    Ceci.showCardCallback(card);
    cards.forEach(function(c) {
      if (c === card) {
        c.style.display = "block";
      } else {
        c.style.display = "none";
      }
    });
    Ceci.currentCard = card;
  }

  function extend(element, card) {
    card.elements.push(element);
    element.card = card;
    element.showCard = function() {
      showCard(card);
    };
  }

  function revert(element, card) {
    card.elements.splice(card.elements.indexOf(element),1);
    if(element.card === card) {
      delete element.card;
      delete element.showCard;
    }
  }

  function observe(container, card) {
    var observer = new MutationObserver(function(mutations) {
      mutations.forEach(function(mutation) {
        if (mutation.type !== "childList")
          return;
        if (mutation.addedNodes) {
          Array.prototype.slice.call(mutation.addedNodes).forEach(function(child) {
            extend(child, card);
          });
        }
        else if(mutation.removedNodes) {
          Array.prototype.slice.call(mutation.addedNodes).forEach(function(child) {
            revert(child, card);
          });
        }
      });
    });
    observer.observe(container, { childList: true });

    // also process any already existing cards
    if(container.children.length > 0) {
      var children = Array.prototype.slice.call(container.children);
      children.forEach(function(child) {
        extend(child, card);
      });
    }
  }

  function processCard(card) {
    card.elements = [];
    if(card.children) {
      Array.prototype.slice.call(card.children).forEach(function(child) {
        extend(child, card);
      });
    }
    card.id = card.id || cardClass + "-" + (cards.length+1);
    ["fixed-top", "phone-canvas", "fixed-bottom"].forEach(function(segment) {
      var div = document.createElement("div");
      div.className = segment + " drophere";
      card.appendChild(div);
      observe(div, card);
    });
    card.showCard = function() {
      showCard(card);
    };
    card.describe = function() {
      return {
        id: card.id,
        elements: card.elements.map(function(e) {
          return e.describe();
        })
      };
    };
    cards.push(card);
  }

  // extend rehydration function for card rehydrating
  (function() {
    var oldFn = Ceci.rehydrate;
    Ceci.rehydrate = function(description) {
      console.log(description.elements);
      var elements = description.elements.map(function(desc) {
        return oldFn(desc);
      });
      var card = document.createElement("div");
      card.setAttribute("class", cardClass);
      card.id = description.id;
      elements.forEach(function(e) {
        card.appendChild(e);
      });
      return card;
    };
  }());

  var createCard = Ceci.createCard = function() {
    var card = document.createElement("div");
    card.setAttribute("class", cardClass);
    processCard(card);
    return card;
  };

  function convertCards() {
    var cardlist = document.querySelectorAll("div." + cardClass);
    if (cardlist.length > 0) {
      cardlist = Array.prototype.slice.call(cardlist);
      cardlist.forEach(function(card) {
        if(!card.showCard) {
          processCard(card);
        }
      });
      showCard(cards[0]);
    }
  }

  Ceci.registerCeciPlugin("onload", convertCards);

  Ceci.showCardCallback = function(card){};

  var onCardChange = Ceci.onCardChange = function (callback){
    Ceci.showCardCallback = callback;

    // call the card change if we've already done one before it's wired up
    if (Ceci.currentCard){
      callback(Ceci.currentCard);
    }
  }

  return {
    onCardChange: onCardChange,
    load: convertCards,
    createCard: createCard,
    _cards: cards
  };
});
<commit_msg>Missing long-pause<commit_after>/**
 * This library allows component wrapping in "card" elements.
 * (right now these are just divs of class "ceci-card").
 */
define(["ceci"], function(Ceci) {
  "use strict";

  var cardClass = "ceci-card";
  var cards = [];
  Ceci.currentCard = null;

  function showCard(card) {
    Ceci.showCardCallback(card);
    cards.forEach(function(c) {
      if (c === card) {
        c.style.display = "block";
      } else {
        c.style.display = "none";
      }
    });
    Ceci.currentCard = card;
  }

  function extend(element, card) {
    card.elements.push(element);
    element.card = card;
    element.showCard = function() {
      showCard(card);
    };
  }

  function revert(element, card) {
    card.elements.splice(card.elements.indexOf(element), 1);
    if(element.card === card) {
      delete element.card;
      delete element.showCard;
    }
  }

  function observe(container, card) {
    var observer = new MutationObserver(function(mutations) {
      mutations.forEach(function(mutation) {
        if (mutation.type !== "childList")
          return;
        if (mutation.addedNodes) {
          Array.prototype.slice.call(mutation.addedNodes).forEach(function(child) {
            extend(child, card);
          });
        }
        else if(mutation.removedNodes) {
          Array.prototype.slice.call(mutation.addedNodes).forEach(function(child) {
            revert(child, card);
          });
        }
      });
    });
    observer.observe(container, { childList: true });

    // also process any already existing cards
    if(container.children.length > 0) {
      var children = Array.prototype.slice.call(container.children);
      children.forEach(function(child) {
        extend(child, card);
      });
    }
  }

  function processCard(card) {
    card.elements = [];
    if(card.children) {
      Array.prototype.slice.call(card.children).forEach(function(child) {
        extend(child, card);
      });
    }
    card.id = card.id || cardClass + "-" + (cards.length+1);
    ["fixed-top", "phone-canvas", "fixed-bottom"].forEach(function(segment) {
      var div = document.createElement("div");
      div.className = segment + " drophere";
      card.appendChild(div);
      observe(div, card);
    });
    card.showCard = function() {
      showCard(card);
    };
    card.describe = function() {
      return {
        id: card.id,
        elements: card.elements.map(function(e) {
          return e.describe();
        })
      };
    };
    cards.push(card);
  }

  // extend rehydration function for card rehydrating
  (function() {
    var oldFn = Ceci.rehydrate;
    Ceci.rehydrate = function(description) {
      console.log(description.elements);
      var elements = description.elements.map(function(desc) {
        return oldFn(desc);
      });
      var card = document.createElement("div");
      card.setAttribute("class", cardClass);
      card.id = description.id;
      elements.forEach(function(e) {
        card.appendChild(e);
      });
      return card;
    };
  }());

  var createCard = Ceci.createCard = function() {
    var card = document.createElement("div");
    card.setAttribute("class", cardClass);
    processCard(card);
    return card;
  };

  function convertCards() {
    var cardlist = document.querySelectorAll("div." + cardClass);
    if (cardlist.length > 0) {
      cardlist = Array.prototype.slice.call(cardlist);
      cardlist.forEach(function(card) {
        if(!card.showCard) {
          processCard(card);
        }
      });
      showCard(cards[0]);
    }
  }

  Ceci.registerCeciPlugin("onload", convertCards);

  Ceci.showCardCallback = function(card){};

  var onCardChange = Ceci.onCardChange = function (callback){
    Ceci.showCardCallback = callback;

    // call the card change if we've already done one before it's wired up
    if (Ceci.currentCard){
      callback(Ceci.currentCard);
    }
  };

  return {
    onCardChange: onCardChange,
    load: convertCards,
    createCard: createCard,
    _cards: cards
  };
});
<|endoftext|>


<commit_before>var globals = require('lib/globals');
exports.mainTabView = function() {
  var instance = Ti.UI.createTabGroup({
    exitOnClose: false
  });

  /*
  // Not Used after conference
  var scheduleWindow = require('ui/common/scheduleWindow').scheduleWindow;
  var scheduleTab = Ti.UI.createTab({
    icon: 'data/11-clock.png',
    title: 'Schedule',
    window: new scheduleWindow()
  });
  instance.addTab(scheduleTab);
  */
  var sessionWindow = require('ui/common/sessionWindow').window;
  var sessionTab = Ti.UI.createTab({
    //icon: 'data/120-headphones.png',
    title: 'Sessions',
    window: new sessionWindow()
  });
  instance.addTab(sessionTab);

  var mapsWindow = require('ui/common/mapsWindow').mapsWindow;
  var mapsTab = Ti.UI.createTab({
    //icon: 'data/103-map.png',
    title: 'Maps',
    window: new mapsWindow()
  });

  var newsWindow = require('ui/common/newsWindow').newsWindow;
  var newsTab = Ti.UI.createTab({
    //icon: 'data/45-movie-1.png',
    title: 'Videos',
    window: new newsWindow()
  });

  var speakersWindow = require('ui/common/speakersWindow').speakersWindow;
  var speakersTab = Ti.UI.createTab({
    //icon: 'data/112-group.png',
    title: 'Speakers',
    window: new speakersWindow()
  });

  var liveWindow = require('ui/iphon/liveWindow').liveWindow;
  var liveTab = Ti.UI.createTab({
    //icon: 'data/69-display.png',
    title: 'Live',
    window: new liveWindow()
  });

  instance.addTab(mapsTab);
  instance.addTab(newsTab);
  instance.addTab(speakersTab);
  if (globals.osname === 'iphone' || globals.osname === 'ipad') {
    instance.addTab(liveTab);
  } else if (globals.osname === 'android' && Ti.Platform.Android.API_LEVEL >= 14) {
    instance.addTab(liveTab);
  }

  // Workaround for not knowing the current tab
  // http://developer.appcelerator.com/question/98501/titaniumuicurrenttab-is-null
  instance.addEventListener('focus', function(e) {
    instance._activeTab = e.tab;
    instance._activeTabIndex = e.index;
    if (instance._activeTabIndex == -1) return;
    //Ti.API.info(instance._activeTabIndex);
    //Ti.API.info(instance._activeTab.title);
    Ti.API._activeTab = instance._activeTab;
    //Ti.API.info(Ti.API._activeTab.title);
  });

  return instance;
};
<commit_msg>Bringing back the menu for the tabs.<commit_after>var globals = require('lib/globals');
exports.mainTabView = function() {
  var instance = Ti.UI.createTabGroup({
    exitOnClose: false
  });
  var apiLevel = Ti.Platform.Android.API_LEVEL,
      activity;
  /*
  // Not Used after conference
  var scheduleWindow = require('ui/common/scheduleWindow').scheduleWindow;
  var scheduleTab = Ti.UI.createTab({
    icon: 'data/11-clock.png',
    title: 'Schedule',
    window: new scheduleWindow()
  });
  instance.addTab(scheduleTab);
  */
  var sessionWindow = require('ui/common/sessionWindow').window;
  var sessionTab = Ti.UI.createTab({
    title: 'Sessions',
    window: new sessionWindow()
  });
  instance.addTab(sessionTab);

  var mapsWindow = require('ui/common/mapsWindow').mapsWindow;
  var mapsTab = Ti.UI.createTab({
    title: 'Maps',
    window: new mapsWindow()
  });

  var newsWindow = require('ui/common/newsWindow').newsWindow;
  var newsTab = Ti.UI.createTab({
    title: 'Videos',
    window: new newsWindow()
  });

  var speakersWindow = require('ui/common/speakersWindow').speakersWindow;
  var speakersTab = Ti.UI.createTab({
    title: 'Speakers',
    window: new speakersWindow()
  });

  var liveWindow = require('ui/iphon/liveWindow').liveWindow;
  var liveTab = Ti.UI.createTab({
    title: 'Live',
    window: new liveWindow()
  });

  instance.addTab(mapsTab);
  instance.addTab(newsTab);
  instance.addTab(speakersTab);
  if (globals.osname === 'iphone' || globals.osname === 'ipad') {
    instance.addTab(liveTab);
  } else if (globals.osname === 'android' && Ti.Platform.Android.API_LEVEL >= 14) {
    instance.addTab(liveTab);
  }

  // Workaround for not knowing the current tab
  // http://developer.appcelerator.com/question/98501/titaniumuicurrenttab-is-null
  instance.addEventListener('focus', function(e) {
    instance._activeTab = e.tab;
    instance._activeTabIndex = e.index;
    if (instance._activeTabIndex == -1) return;
    //Ti.API.info(instance._activeTabIndex);
    //Ti.API.info(instance._activeTab.title);
    Ti.API._activeTab = instance._activeTab;
    //Ti.API.info(Ti.API._activeTab.title);
    activity.invalidateOptionsMenu();
  });

  instance.addEventListener('open', function(args) {
    activity = instance.getActivity();
    if (apiLevel >= 11) {
      actionBar = activity.actionBar;
      actionBar.setIcon(null);
      actionBar.setTitle('Spiritual Leadership Conference');
    }
    else {
      activity.onPrepareOptionsMenu = function(e) {
        createOptionsMenu(e);
      };
    }
    activity.onCreateOptionsMenu = function(e) {
      createOptionsMenu(e);
    };
    activity.invalidateOptionsMenu();
  });

  function createOptionsMenu(e) {
    var menu = e.menu;
    menu.clear();
    Ti.API.info(instance.activeTab.title);
    switch (instance.activeTab) {
      case 'Sessions':

        break;
      case 'Maps':

        break;
      case 'Videos':

        break;
      case 'Speakers':

        break;
      case 'Live':

        break;
    }
    var menuItem_help = menu.add({
      title: 'help',
      showAsAction: Ti.Android.SHOW_AS_ACTION_NEVER
    });
    menuItem_help.addEventListener('click', function(args) {
      alert('clicked: help');
    });
  }

  return instance;
};
<|endoftext|>


<commit_before>@import 'sketch-nibui.js';

function onRun(context) {
  var sketch = context.api();
  var doc = context.document;
  var app = NSApplication.sharedApplication();
  var language = [[NSSpellChecker sharedSpellChecker] language]

  // Filter layers using NSPredicate
	var scope = (typeof containerLayer !== 'undefined') ? [containerLayer children] : [[doc currentPage] children],
		predicate = NSPredicate.predicateWithFormat("(className == %@)", "MSTextLayer"),
		layers = [scope filteredArrayUsingPredicate:predicate];

	// Deselect current selection
	[[doc currentPage] deselectAllLayers]

	// Loop through filtered layers and select them
	var loop = [layers objectEnumerator], layer;
  var misspellingcount = 0;
  var stopChecking = false;
  var madeAChange = false;
  while (layer = [loop nextObject]) {
    if(stopChecking){
      break; //If the user hits "Done", stop checking
    }

    //do spellcheck on each layer
    var aString = [layer stringValue]
    range = [[NSSpellChecker sharedSpellChecker] checkSpellingOfString:aString startingAt:0];
    while(range.length >0 ){
      var cursorLoc=range.location+range.length;

      //Select the layer
      [layer select:true byExpandingSelection:false]

      misspellingcount ++;

      var misSpelledWord = aString.substring(range.location, (range.location+range.length))
      var guesses = [[NSSpellChecker sharedSpellChecker] guessesForWordRange:range inString:aString language:language inSpellDocumentWithTag:0];

      //Build our alert
      var alert = NSAlert.alloc().init();

      alert.setMessageText('Spell Check Whole Page');
      alert.addButtonWithTitle('Skip'); //We must have a button here, so Skip makes the most sense.
      //alert.setIcon(NSImage.alloc().initWithContentsOfFile(
      //    context.plugin.urlForResourceNamed('DialogIcon512.png').path()));
      var nibui = new NibUI(context,
        'UIBundle', 'SpellCheckWholePage',
        ['textMisSpelling', 'replaceComboBox', 'btnReplace','btnIgnoreAll','btnAddDict','btnDone','textFullText']);

      alert.setAccessoryView(nibui.view);

      //Set up our text
      nibui.textMisSpelling.stringValue = "Mispelling: "+ misSpelledWord;
      nibui.textFullText.stringValue = aString;

      //Put guesses into the combobox
      nibui.replaceComboBox.removeAllItems();
      if ( guesses ){
        if (guesses.length >0){
          nibui.replaceComboBox.addItemsWithObjectValues( guesses );
          nibui.replaceComboBox.selectItemAtIndex( 0 );
        }
      }

      //Set up our button functions
      nibui.attachTargetAndAction(nibui.btnReplace, function() {
        madeAChange=true;
        //replace it in our string
        //var newWord = nibui.replaceComboBox.objectValueOfSelectedItem();
        var newWord = nibui.replaceComboBox.stringValue();
        aString = aString.replace( misSpelledWord, newWord);
        cursorLoc = range.location + newWord.length();
        app.stopModal();
      });

      nibui.attachTargetAndAction(nibui.btnDone, function() {
        // Stop!
        stopChecking = true;
        app.stopModal();
      });

      nibui.attachTargetAndAction(nibui.btnIgnoreAll, function(){

        //Ignore word for this document
        [[NSSpellChecker sharedSpellChecker] ignoreWord: misSpelledWord inSpellDocumentWithTag: 0]
        app.stopModal();
      });

      nibui.attachTargetAndAction(nibui.btnAddDict, function() {

        // Add the word to the Dictionary.
        [[NSSpellChecker sharedSpellChecker] learnWord: misSpelledWord]
        app.stopModal();
      });
      alert.runModal();

      nibui.destroy();
      if(stopChecking){
        break; //If the user hits "Done", stop checking
      }
      //Recheck the text for a misspelling (and loop again if there is one)
      range = [[NSSpellChecker sharedSpellChecker] checkSpellingOfString:aString startingAt:cursorLoc];

      if (range.location < cursorLoc ){
        //Break out of the loop if the search is resetting to the beginning
        break;
      }
    }
    //Do text replacement if we updated anything
    if (madeAChange){
      layer.setIsEditingText(true);
      layer.setStringValue(aString);
      layer.setIsEditingText(false);
    }
    //Reset
    madeAChange = false;

  }
  if (misspellingcount == 0){
    doc.displayMessage("No Misspellings here!");
  } else if (misspellingcount == 1 ){
    doc.displayMessage(misspellingcount+ " misspelling found!");
  } else {
    doc.displayMessage(misspellingcount+ " misspellings found!");
  }

}
<commit_msg>Jet getting started looking into symbol overrides<commit_after>@import 'sketch-nibui.js';

function onRun(context) {
  var sketch = context.api();
  var doc = context.document;
  var app = NSApplication.sharedApplication();
  var language = [[NSSpellChecker sharedSpellChecker] language]

  // Filter layers using NSPredicate
	var scope = (typeof containerLayer !== 'undefined') ? [containerLayer children] : [[doc currentPage] children],
		predicate = NSPredicate.predicateWithFormat("(className == %@)", "MSTextLayer"),
		layers = [scope filteredArrayUsingPredicate:predicate];

	// Deselect current selection
	[[doc currentPage] deselectAllLayers]

	// Loop through filtered layers and select them
	var loop = [layers objectEnumerator], layer;
  var misspellingcount = 0;
  var stopChecking = false;
  var madeAChange = false;
  while (layer = [loop nextObject]) {
    if(stopChecking){
      break; //If the user hits "Done", stop checking
    }

    //do spellcheck on each layer
    var aString = [layer stringValue]
    range = [[NSSpellChecker sharedSpellChecker] checkSpellingOfString:aString startingAt:0];
    while(range.length >0 ){
      var cursorLoc=range.location+range.length;

      //Select the layer
      [layer select:true byExpandingSelection:false]

      misspellingcount ++;

      var misSpelledWord = aString.substring(range.location, (range.location+range.length))
      var guesses = [[NSSpellChecker sharedSpellChecker] guessesForWordRange:range inString:aString language:language inSpellDocumentWithTag:0];

      //Build our alert
      var alert = NSAlert.alloc().init();

      alert.setMessageText('Spell Check Whole Page');
      alert.addButtonWithTitle('Skip'); //We must have a button here, so Skip makes the most sense.
      //alert.setIcon(NSImage.alloc().initWithContentsOfFile(
      //    context.plugin.urlForResourceNamed('DialogIcon512.png').path()));
      var nibui = new NibUI(context,
        'UIBundle', 'SpellCheckWholePage',
        ['textMisSpelling', 'replaceComboBox', 'btnReplace','btnIgnoreAll','btnAddDict','btnDone','textFullText']);

      alert.setAccessoryView(nibui.view);

      //Set up our text
      nibui.textMisSpelling.stringValue = "Mispelling: "+ misSpelledWord;
      nibui.textFullText.stringValue = aString;

      //Put guesses into the combobox
      nibui.replaceComboBox.removeAllItems();
      if ( guesses ){
        if (guesses.length >0){
          nibui.replaceComboBox.addItemsWithObjectValues( guesses );
          nibui.replaceComboBox.selectItemAtIndex( 0 );
        }
      }

      //Set up our button functions
      nibui.attachTargetAndAction(nibui.btnReplace, function() {
        madeAChange=true;
        //replace it in our string
        //var newWord = nibui.replaceComboBox.objectValueOfSelectedItem();
        var newWord = nibui.replaceComboBox.stringValue();
        aString = aString.replace( misSpelledWord, newWord);
        cursorLoc = range.location + newWord.length();
        app.stopModal();
      });

      nibui.attachTargetAndAction(nibui.btnDone, function() {
        // Stop!
        stopChecking = true;
        app.stopModal();
      });

      nibui.attachTargetAndAction(nibui.btnIgnoreAll, function(){

        //Ignore word for this document
        [[NSSpellChecker sharedSpellChecker] ignoreWord: misSpelledWord inSpellDocumentWithTag: 0]
        app.stopModal();
      });

      nibui.attachTargetAndAction(nibui.btnAddDict, function() {

        // Add the word to the Dictionary.
        [[NSSpellChecker sharedSpellChecker] learnWord: misSpelledWord]
        app.stopModal();
      });
      alert.runModal();

      nibui.destroy();
      if(stopChecking){
        break; //If the user hits "Done", stop checking
      }
      //Recheck the text for a misspelling (and loop again if there is one)
      range = [[NSSpellChecker sharedSpellChecker] checkSpellingOfString:aString startingAt:cursorLoc];

      if (range.location < cursorLoc ){
        //Break out of the loop if the search is resetting to the beginning
        break;
      }
    }
    //Do text replacement if we updated anything
    if (madeAChange){
      layer.setIsEditingText(true);
      layer.setStringValue(aString);
      layer.setIsEditingText(false);
    }
    //Reset
    madeAChange = false;

  }

  // MESSY! Simply duplicating the loop (need to make functions out of this)
  // Search symbols for misspellings too

  var scope = (typeof containerLayer !== 'undefined') ? [containerLayer children] : [[doc currentPage] children],
		predicate = NSPredicate.predicateWithFormat("isSymbol == YES"),
		layers = [scope filteredArrayUsingPredicate:predicate];

	// Deselect current selection
	[[doc currentPage] deselectAllLayers]

	// Loop through filtered layers and select them
	var loop = [layers objectEnumerator], layer;

  while (layer = [loop nextObject]) {
    //We actually need to loop through the overrides themselves too. There's info here: http://sketchplugins.com/d/20-how-do-i-write-to-a-symbol-instance-override/6
    /* function executePopulateSymbol(instace, index) {

    var layerIDs = getLayerIDs(instance);
    var values = instance.overrides();

    if (!values){
        values = NSMutableDictionary.dictionary();
    }

    var existingOverrides = values;
    var mutableOverrides = NSMutableDictionary.dictionaryWithDictionary(existingOverrides)
    mutableOverrides.setObject_forKey(NSMutableDictionary.dictionaryWithDictionary(existingOverrides.objectForKey(0)),0)

    var imgURL = server + sectionDetailContent[index].thumb + "?" +token;
    var picture = NSImage.alloc().initWithData_( getImage(imgURL) );
    var imageData = MSImageData.alloc().initWithImage_convertColorSpace_(picture, nil);

    mutableOverrides.objectForKey(0).setObject_forKey(sectionDetailContent[index].title,layerIDs.title_ID)
    mutableOverrides.objectForKey(0).setObject_forKey(sectionDetailContent[index].year.toString(),layerIDs.year_ID)
    mutableOverrides.objectForKey(0).setObject_forKey(imageData,layerIDs.artwork_ID);

    instance.applyOverrides_allSymbols_(mutableOverrides,false);
}
*/

    if(stopChecking){
      break; //If the user hits "Done", stop checking
    }

    //do spellcheck on each layer
    var aString = [layer stringValue]
    range = [[NSSpellChecker sharedSpellChecker] checkSpellingOfString:aString startingAt:0];
    while(range.length >0 ){
      var cursorLoc=range.location+range.length;

      //Select the layer
      [layer select:true byExpandingSelection:false]

      misspellingcount ++;

      var misSpelledWord = aString.substring(range.location, (range.location+range.length))
      var guesses = [[NSSpellChecker sharedSpellChecker] guessesForWordRange:range inString:aString language:language inSpellDocumentWithTag:0];

      //Build our alert
      var alert = NSAlert.alloc().init();

      alert.setMessageText('Spell Check Whole Page');
      alert.addButtonWithTitle('Skip'); //We must have a button here, so Skip makes the most sense.
      //alert.setIcon(NSImage.alloc().initWithContentsOfFile(
      //    context.plugin.urlForResourceNamed('DialogIcon512.png').path()));
      var nibui = new NibUI(context,
        'UIBundle', 'SpellCheckWholePage',
        ['textMisSpelling', 'replaceComboBox', 'btnReplace','btnIgnoreAll','btnAddDict','btnDone','textFullText']);

      alert.setAccessoryView(nibui.view);

      //Set up our text
      nibui.textMisSpelling.stringValue = "Mispelling: "+ misSpelledWord;
      nibui.textFullText.stringValue = aString;

      //Put guesses into the combobox
      nibui.replaceComboBox.removeAllItems();
      if ( guesses ){
        if (guesses.length >0){
          nibui.replaceComboBox.addItemsWithObjectValues( guesses );
          nibui.replaceComboBox.selectItemAtIndex( 0 );
        }
      }

      //Set up our button functions
      nibui.attachTargetAndAction(nibui.btnReplace, function() {
        madeAChange=true;
        //replace it in our string
        //var newWord = nibui.replaceComboBox.objectValueOfSelectedItem();
        var newWord = nibui.replaceComboBox.stringValue();
        aString = aString.replace( misSpelledWord, newWord);
        cursorLoc = range.location + newWord.length();
        app.stopModal();
      });

      nibui.attachTargetAndAction(nibui.btnDone, function() {
        // Stop!
        stopChecking = true;
        app.stopModal();
      });

      nibui.attachTargetAndAction(nibui.btnIgnoreAll, function(){

        //Ignore word for this document
        [[NSSpellChecker sharedSpellChecker] ignoreWord: misSpelledWord inSpellDocumentWithTag: 0]
        app.stopModal();
      });

      nibui.attachTargetAndAction(nibui.btnAddDict, function() {

        // Add the word to the Dictionary.
        [[NSSpellChecker sharedSpellChecker] learnWord: misSpelledWord]
        app.stopModal();
      });
      alert.runModal();

      nibui.destroy();
      if(stopChecking){
        break; //If the user hits "Done", stop checking
      }
      //Recheck the text for a misspelling (and loop again if there is one)
      range = [[NSSpellChecker sharedSpellChecker] checkSpellingOfString:aString startingAt:cursorLoc];

      if (range.location < cursorLoc ){
        //Break out of the loop if the search is resetting to the beginning
        break;
      }
    }
    //Do text replacement if we updated anything
    if (madeAChange){
      layer.setIsEditingText(true);
      layer.setStringValue(aString);
      layer.setIsEditingText(false);
    }
    //Reset
    madeAChange = false;

  }

  if (misspellingcount == 0){
    doc.displayMessage("No Misspellings here!");
  } else if (misspellingcount == 1 ){
    doc.displayMessage(misspellingcount+ " misspelling found!");
  } else {
    doc.displayMessage(misspellingcount+ " misspellings found!");
  }

}
<|endoftext|>


<commit_before>describe("UI Window Tests",{
	before_all: function()
	{
		var self = this;
		this.async_window_open = function(test, assertFn, args)
		{
			var w = window.open.apply(window, args);
			value_of(w).should_be_object();
			Titanium.API.addEventListener(Titanium.PAGE_INITIALIZED, function(event)
			{
				if (!event.hasTitaniumObject)
					return;

				w.callback = function()
				{
					clearTimeout(timer);
					try
					{
						assertFn.apply(self, [w]);
						w.close();
						test.passed();
					}
					catch (e)
					{
						test.failed(e);
					}
				};
			});
			timer = setTimeout(function(){
				test.failed("open url timed out");
			}, 3000);
		};
	},
	test_open_no_url: function()
	{
		var w = window.open()
		value_of(w).should_be_object();
		value_of(w.Titanium).should_be_object();
		w.close();
	},
	test_open_with_url_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium).should_be_object();
		}, ["a.html"]);
	},
	test_open_with_name_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();
			value_of(w.Titanium.UI.getCurrentWindow().isFullscreen()).should_be_false();
		}, ["a.html", "a"]);
	},
	test_open_fullscreen_yes_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();
			if (Titanium.platform != 'linux')
			{
				value_of(w.Titanium.UI.getCurrentWindow().isFullscreen()).should_be_true();
			}
		}, ["a.html","a","fullscreen=yes"]);
	},
	test_open_fullscreen_no_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();

			if (Titanium.platform != 'linux')
			{
				value_of(w.Titanium.UI.getCurrentWindow().isFullscreen()).should_be_false();
			}
		}, ["a.html","a","fullscreen=no"]);
	},
	test_open_fullscreen_1_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();
			if (Titanium.platform != 'linux')
			{
				value_of(w.Titanium.UI.getCurrentWindow().isFullscreen()).should_be_true();
			}
		}, ["a.html","a","fullscreen=1"]);
	},
	test_open_fullscreen_0_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();
			if (Titanium.platform != 'linux')
			{
				value_of(w.Titanium.UI.getCurrentWindow().isFullscreen()).should_be_false();
			}
		}, ["a.html","a","fullscreen=0"]);
	},
	test_open_height_100_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();
			value_of(w.Titanium.UI.getCurrentWindow().getHeight()).should_be(100);
		}, ["a.html","a","height=100"]);
	},
	test_open_width_121_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();
			value_of(w.Titanium.UI.getCurrentWindow().getWidth()).should_be(121);
			value_of(w.Titanium.UI.getCurrentWindow().isResizable()).should_be_true();
		}, ["a.html","a","width=121"]);
	},
	// webkit and firefox both ignore the 'resizable' flag
	// see WebCore/page/WindowFeatures.cpp line 133
	test_open_left_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();
			value_of(w.Titanium.UI.getCurrentWindow().getX()).should_be(125);
		}, ["a.html","a","left=125"]);
	},
	test_open_top_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();
			value_of(w.Titanium.UI.getCurrentWindow().getY()).should_be(125);
		}, ["a.html","a","top=125"]);
	},
	test_open_multiple_props_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();
			value_of(w.Titanium.UI.getCurrentWindow().getY()).should_be(125);
			value_of(w.Titanium.UI.getCurrentWindow().getX()).should_be(125);
			value_of(w.Titanium.UI.getCurrentWindow().getWidth()).should_be(121);
			value_of(w.Titanium.UI.getCurrentWindow().getHeight()).should_be(101);
			value_of(w.Titanium.UI.getCurrentWindow().isFullscreen()).should_be_false();
		}, ["a.html","a","left=125,top=125,fullscreen=0,width=121,height=101"]);
	},
	test_open_child_dom_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.result).should_be('Hello');
		}, ["a.html"]);
	},
	test_open_relative_app_url_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.result).should_be('Hello');
			value_of(w.a_value).should_be(42);
		}, ["app://rel.html"]);
	},
	test_data_uri_non_base64_encoded_as_async: function(test)
	{
		var path = Titanium.App.appURLToPath("app://rel.html");
		var html = Titanium.Filesystem.getFile(path).read();

		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.result).should_be('Hello');
		}, ["data:text/html;charset=utf-8,"+html]);
	},
	test_data_uri_base64_encoded_as_async: function(test)
	{
		var path = Titanium.App.appURLToPath("app://rel.html");
		var html = Titanium.Filesystem.getFile(path).read();

		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.result).should_be('Hello');
		}, ["data:text/html;charset=utf-8;base64,"+Titanium.Codec.encodeBase64(html)]);
	},
	test_data_uri_with_html_parameter_as_async: function(test)
	{
		var path = Titanium.App.appURLToPath("app://rel.html");
		var html = Titanium.Filesystem.getFile(path).read();

		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.result).should_be('Hello');
		}, [{html:html}]);
	}
});
<commit_msg>Modify DOMWindow test to account for window.open() behavior.<commit_after>describe("UI Window Tests",{
	before_all: function()
	{
		var self = this;
		this.async_window_open = function(test, assertFn, args)
		{
			var w = window.open.apply(window, args);
			value_of(w).should_be_object();
			Titanium.API.addEventListener(Titanium.PAGE_INITIALIZED, function(event)
			{
				if (!event.hasTitaniumObject)
					return;

				w.callback = function()
				{
					clearTimeout(timer);
					try
					{
						assertFn.apply(self, [w]);
						w.close();
						test.passed();
					}
					catch (e)
					{
						test.failed(e);
					}
				};
			});
			timer = setTimeout(function(){
				test.failed("open url timed out");
			}, 3000);
		};
	},
	test_open_no_url_as_async: function(callback)
	{
		var w = window.open()
		setTimeout(function() {
			Titanium.API.debug(w.Titanium);
			if (typeof(w) != "object" || typeof(w.Titanium) != 'object')
				callback.failed("Could not find Titanium object in window");
			else
				callback.passed();
			w.close();
		}, 200);
	},
	test_open_with_url_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium).should_be_object();
		}, ["a.html"]);
	},
	test_open_with_name_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();
			value_of(w.Titanium.UI.getCurrentWindow().isFullscreen()).should_be_false();
		}, ["a.html", "a"]);
	},
	test_open_fullscreen_yes_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();
			if (Titanium.platform != 'linux')
			{
				value_of(w.Titanium.UI.getCurrentWindow().isFullscreen()).should_be_true();
			}
		}, ["a.html","a","fullscreen=yes"]);
	},
	test_open_fullscreen_no_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();

			if (Titanium.platform != 'linux')
			{
				value_of(w.Titanium.UI.getCurrentWindow().isFullscreen()).should_be_false();
			}
		}, ["a.html","a","fullscreen=no"]);
	},
	test_open_fullscreen_1_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();
			if (Titanium.platform != 'linux')
			{
				value_of(w.Titanium.UI.getCurrentWindow().isFullscreen()).should_be_true();
			}
		}, ["a.html","a","fullscreen=1"]);
	},
	test_open_fullscreen_0_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();
			if (Titanium.platform != 'linux')
			{
				value_of(w.Titanium.UI.getCurrentWindow().isFullscreen()).should_be_false();
			}
		}, ["a.html","a","fullscreen=0"]);
	},
	test_open_height_100_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();
			value_of(w.Titanium.UI.getCurrentWindow().getHeight()).should_be(100);
		}, ["a.html","a","height=100"]);
	},
	test_open_width_121_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();
			value_of(w.Titanium.UI.getCurrentWindow().getWidth()).should_be(121);
			value_of(w.Titanium.UI.getCurrentWindow().isResizable()).should_be_true();
		}, ["a.html","a","width=121"]);
	},
	// webkit and firefox both ignore the 'resizable' flag
	// see WebCore/page/WindowFeatures.cpp line 133
	test_open_left_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();
			value_of(w.Titanium.UI.getCurrentWindow().getX()).should_be(125);
		}, ["a.html","a","left=125"]);
	},
	test_open_top_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();
			value_of(w.Titanium.UI.getCurrentWindow().getY()).should_be(125);
		}, ["a.html","a","top=125"]);
	},
	test_open_multiple_props_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.Titanium.UI.getCurrentWindow()).should_be_object();
			value_of(w.Titanium.UI.getCurrentWindow().getY()).should_be(125);
			value_of(w.Titanium.UI.getCurrentWindow().getX()).should_be(125);
			value_of(w.Titanium.UI.getCurrentWindow().getWidth()).should_be(121);
			value_of(w.Titanium.UI.getCurrentWindow().getHeight()).should_be(101);
			value_of(w.Titanium.UI.getCurrentWindow().isFullscreen()).should_be_false();
		}, ["a.html","a","left=125,top=125,fullscreen=0,width=121,height=101"]);
	},
	test_open_child_dom_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.result).should_be('Hello');
		}, ["a.html"]);
	},
	test_open_relative_app_url_as_async: function(test)
	{
		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.result).should_be('Hello');
			value_of(w.a_value).should_be(42);
		}, ["app://rel.html"]);
	},
	test_data_uri_non_base64_encoded_as_async: function(test)
	{
		var path = Titanium.App.appURLToPath("app://rel.html");
		var html = Titanium.Filesystem.getFile(path).read();

		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.result).should_be('Hello');
		}, ["data:text/html;charset=utf-8,"+html]);
	},
	test_data_uri_base64_encoded_as_async: function(test)
	{
		var path = Titanium.App.appURLToPath("app://rel.html");
		var html = Titanium.Filesystem.getFile(path).read();

		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.result).should_be('Hello');
		}, ["data:text/html;charset=utf-8;base64,"+Titanium.Codec.encodeBase64(html)]);
	},
	test_data_uri_with_html_parameter_as_async: function(test)
	{
		var path = Titanium.App.appURLToPath("app://rel.html");
		var html = Titanium.Filesystem.getFile(path).read();

		this.async_window_open(test, function(w)
		{
			value_of(w).should_be_object();
			value_of(w.Titanium).should_be_object();
			value_of(w.document.title).should_be("Hello");
			value_of(w.result).should_be('Hello');
		}, [{html:html}]);
	}
});
<|endoftext|>


<commit_before>var desktop = {
  'mac-chrome-latest'       : ['Mac 10.11', 'chrome', '51.0'],
  'mac-firefox-latest'      : ['Mac 10.11', 'firefox', '47.0'],
  'mac-safari-latest'       : ['Mac 10.11', 'safari', '9.0'],
  'mac-chrome-previous'     : ['Mac 10.10', 'chrome', '50.0'],
  'mac-firefox-previous'    : ['Mac 10.10', 'firefox', '46.0'],
  'mac-safari-previous'     : ['Mac 10.10', 'safari', '8.0'],

  'windows-chrome-latest'   : ['Windows 10', 'chrome', '51.0'],
  'windows-firefox-latest'  : ['Windows 10', 'firefox', '47.0'],
  'windows-edge-latest'     : ['Windows 10', 'microsoftedge', '13.10586'],
  'windows-ie-latest'       : ['Windows 8.1', 'internet explorer', '11.0'],
  'windows-chrome-previous' : ['Windows 8.1', 'chrome', '50.0'],
  'windows-firefox-previous': ['Windows 8.1', 'firefox', '46.0'],

  'linux-chrome-latest'     : ['Linux', 'chrome', '48.0'],
  'linux-firefox-latest'    : ['Linux', 'firefox', '45.0'],
  'linux-chrome-previous'   : ['Linux', 'chrome', '47.0'],
  'linux-firefox-previous'  : ['Linux', 'firefox', '44.0']
};

var mobile = {
  'ios-latest'        : ['iPhone 6 Plus', 'iOS', '9.3', 'Safari'],
  'ios-previous'      : ['iPhone 6 Plus', 'iOS', '9.2', 'Safari'],

  'android-latest'    : ['Android Emulator', 'Android', '5.1', 'Browser'],
  'android-previous'  : ['Android Emulator', 'Android', '5.0', 'Browser']
};

Object.keys(desktop).forEach(function(key) {
  module.exports[key] = {
    base: 'SauceLabs',
    browserName: desktop[key][1],
    version: desktop[key][2],
    platform: desktop[key][0]
  };
});

Object.keys(mobile).forEach(function(key) {
  module.exports[key] = {
    base: 'SauceLabs',
    browserName: mobile[key][3],
    appiumVersion: '1.5.3',
    deviceName: mobile[key][0],
    deviceOrientation: 'portrait',
    platformVersion: mobile[key][2],
    platformName: mobile[key][1]
  };
});
<commit_msg>update platforms<commit_after>var desktop = {
  'mac-chrome-latest'       : ['Mac 10.11', 'chrome', '52.0'],
  'mac-firefox-latest'      : ['Mac 10.11', 'firefox', '48.0'],
  'mac-safari-latest'       : ['Mac 10.11', 'safari', '9.0'],
  'mac-chrome-previous'     : ['Mac 10.10', 'chrome', '51.0'],
  'mac-firefox-previous'    : ['Mac 10.10', 'firefox', '47.0'],
  'mac-safari-previous'     : ['Mac 10.10', 'safari', '8.0'],

  'windows-chrome-latest'   : ['Windows 10', 'chrome', '52.0'],
  'windows-firefox-latest'  : ['Windows 10', 'firefox', '48.0'],
  'windows-edge-latest'     : ['Windows 10', 'microsoftedge', '13.10586'],
  'windows-ie-latest'       : ['Windows 10', 'internet explorer', '11.0'],
  'windows-chrome-previous' : ['Windows 8.1', 'chrome', '51.0'],
  'windows-firefox-previous': ['Windows 8.1', 'firefox', '47.0'],

  'linux-chrome-latest'     : ['Linux', 'chrome', '48.0'],
  'linux-firefox-latest'    : ['Linux', 'firefox', '45.0'],
  'linux-chrome-previous'   : ['Linux', 'chrome', '47.0'],
  'linux-firefox-previous'  : ['Linux', 'firefox', '44.0']
};

var mobile = {
  'ios-latest'        : ['iPhone 6 Plus', 'iOS', '9.3', 'Safari'],
  'ios-previous'      : ['iPhone 6 Plus', 'iOS', '9.2', 'Safari'],

  'android-latest'    : ['Android Emulator', 'Android', '5.1', 'Browser'],
  'android-previous'  : ['Android Emulator', 'Android', '5.0', 'Browser']
};

Object.keys(desktop).forEach(function(key) {
  module.exports[key] = {
    base: 'SauceLabs',
    browserName: desktop[key][1],
    version: desktop[key][2],
    platform: desktop[key][0]
  };
});

Object.keys(mobile).forEach(function(key) {
  module.exports[key] = {
    base: 'SauceLabs',
    browserName: mobile[key][3],
    appiumVersion: '1.5.3',
    deviceName: mobile[key][0],
    deviceOrientation: 'portrait',
    platformVersion: mobile[key][2],
    platformName: mobile[key][1]
  };
});
<|endoftext|>


<commit_before>window.onload = function() {
  var status = document.createElement('div');
  status.innerHTML = 'Development mode';
  status.style.position = 'fixed';
  status.style.left = '10px';
  status.style.bottom = '10px';
  status.style.backgroundColor = '#eee';
  status.style.border = '1px solid #ccc';
  status.style.padding = '5px 10px';
  status.style.color = '#c00';
  console.log(status.style);
  document.body.appendChild(status);
}
<commit_msg>Dev console wip.<commit_after>window.onload = function() {
  var status = document.createElement('div');
  status.innerHTML = 'Development mode | Log (0) | Request data';
  status.style.position = 'fixed';
  status.style.left = '10px';
  status.style.bottom = '10px';
  status.style.backgroundColor = '#eee';
  status.style.border = '1px solid #ccc';
  status.style.padding = '5px 10px';
  status.style.color = '#c00';
  console.log(status.style);
  document.body.appendChild(status);
}
<|endoftext|>