From 9e9f4049cb62246b6e41290267836ee10b751532 Mon Sep 17 00:00:00 2001 From: Alexander Novikov Date: Mon, 30 Mar 2015 01:59:32 -0700 Subject: [PATCH 01/23] change jshint indent config from 2 to 4 --- .jshintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.jshintrc b/.jshintrc index 64b7ce8..3dca42d 100644 --- a/.jshintrc +++ b/.jshintrc @@ -8,7 +8,7 @@ "curly": true, "eqeqeq": true, "immed": true, - "indent": 2, + "indent": 4, "latedef": true, "newcap": true, "noarg": true, From f7f0c38dfde8c4613313e666a08f1ab8195c11e1 Mon Sep 17 00:00:00 2001 From: Alexander Novikov Date: Mon, 30 Mar 2015 02:01:02 -0700 Subject: [PATCH 02/23] add IDEA configs to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 170b50a..5a9cf7c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ node_modules .sass-cache app/components dist/components +/.idea From 36177a3b13e748803ea4de3c7e28f6c95b7d3ab4 Mon Sep 17 00:00:00 2001 From: Alexander Novikov Date: Mon, 30 Mar 2015 02:21:16 -0700 Subject: [PATCH 03/23] reformat Gruntfile.js --- Gruntfile.js | 621 ++++++++++++++++++++++++++------------------------- 1 file changed, 311 insertions(+), 310 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 12b70fa..f7d686a 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,327 +1,328 @@ 'use strict'; var lrSnippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet; var mountFolder = function (connect, dir) { - return connect.static(require('path').resolve(dir)); + return connect.static(require('path').resolve(dir)); }; module.exports = function (grunt) { - // load all grunt tasks - require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks); + // load all grunt tasks + require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks); - // configurable paths - var yeomanConfig = { - app: 'app', - dist: 'dist' - }; + // configurable paths + var yeomanConfig = { + app: 'app', + dist: 'dist' + }; - try { - yeomanConfig.app = require('./component.json').appPath || yeomanConfig.app; - } catch (e) {} + try { + yeomanConfig.app = require('./component.json').appPath || yeomanConfig.app; + } catch (e) { + } - grunt.initConfig({ - yeoman: yeomanConfig, - watch: { - haml: { - files: [ - '<%= yeoman.app %>/*.haml', - '<%= yeoman.app %>/views/{,*/}*.haml' - ], - tasks: ['haml:dist'] - }, - coffee: { - files: ['<%= yeoman.app %>/scripts/{,*/}*.coffee'], - tasks: ['coffee:dist'] - }, - coffeeTest: { - files: ['test/spec/{,*/}*.coffee'], - tasks: ['coffee:test'] - }, - compass: { - files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'], - tasks: ['compass'] - }, - livereload: { - files: [ - '<%= yeoman.app %>/{,*/}*.html', - '{.tmp,<%= yeoman.app %>}/styles/{,*/}*.css', - '{.tmp,<%= yeoman.app %>}/scripts/{,*/}*.js', - '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}' - ], - tasks: ['livereload'] - } - }, - connect: { - options: { - port: 9000, - // Change this to '0.0.0.0' to access the server from outside. - hostname: 'localhost' - }, - livereload: { - options: { - middleware: function (connect) { - return [ - lrSnippet, - mountFolder(connect, '.tmp'), - mountFolder(connect, yeomanConfig.app) - ]; - } - } - }, - test: { - options: { - middleware: function (connect) { - return [ - mountFolder(connect, '.tmp'), - mountFolder(connect, 'test') - ]; - } - } - } - }, - open: { - server: { - url: 'http://localhost:<%= connect.options.port %>' - } - }, - clean: { - dist: { - files: [{ - dot: true, - src: [ - '.tmp', - '<%= yeoman.dist %>/*', - '!<%= yeoman.dist %>/.git*' - ] - }] - }, - server: '.tmp' - }, - jshint: { - options: { - jshintrc: '.jshintrc' - }, - all: [ - 'Gruntfile.js', - '<%= yeoman.app %>/scripts/{,*/}*.js' - ] - }, - karma: { - unit: { - configFile: 'karma.conf.js', - singleRun: true - } - }, - haml: { - options: { - language: 'ruby' - }, - dist: { - files: [{ - expand: true, - cwd: '<%= yeoman.app %>', - src: '{,*/}*.haml', - dest: '.tmp', - ext: '.html' - }] - } - }, - coffee: { - dist: { - files: [{ - expand: true, - cwd: '<%= yeoman.app %>/scripts', - src: '{,*/}*.coffee', - dest: '.tmp/scripts', - ext: '.js' - }] - }, - test: { - files: [{ - expand: true, - cwd: 'test/spec', - src: '{,*/}*.coffee', - dest: '.tmp/spec', - ext: '.js' - }] - } - }, - compass: { - options: { - sassDir: '<%= yeoman.app %>/styles', - cssDir: '.tmp/styles', - imagesDir: '<%= yeoman.app %>/images', - javascriptsDir: '<%= yeoman.app %>/scripts', - fontsDir: '<%= yeoman.app %>/styles/fonts', - importPath: '<%= yeoman.app %>/components', - relativeAssets: true - }, - dist: {}, - server: { - options: { - debugInfo: true - } - } - }, - concat: { - dist: { - files: { - '<%= yeoman.dist %>/scripts/scripts.js': [ - '.tmp/scripts/{,*/}*.js', - '<%= yeoman.app %>/scripts/{,*/}*.js' - ] - } - } - }, - useminPrepare: { - html: '<%= yeoman.app %>/index.html', - options: { - dest: '<%= yeoman.dist %>' - } - }, - usemin: { - html: ['<%= yeoman.dist %>/{,*/}*.html'], - css: ['<%= yeoman.dist %>/styles/{,*/}*.css'], - options: { - dirs: ['<%= yeoman.dist %>'] - } - }, - imagemin: { - dist: { - files: [{ - expand: true, - cwd: '<%= yeoman.app %>/images', - src: '{,*/}*.{png,jpg,jpeg}', - dest: '<%= yeoman.dist %>/images' - }] - } - }, - cssmin: { - dist: { - files: { - '<%= yeoman.dist %>/styles/main.css': [ - '.tmp/styles/{,*/}*.css', - '<%= yeoman.app %>/styles/{,*/}*.css' - ] - } - } - }, - htmlmin: { - dist: { - options: { - /*removeCommentsFromCDATA: true, - // https://github.com/yeoman/grunt-usemin/issues/44 - //collapseWhitespace: true, - collapseBooleanAttributes: true, - removeAttributeQuotes: true, - removeRedundantAttributes: true, - useShortDoctype: true, - removeEmptyAttributes: true, - removeOptionalTags: true*/ + grunt.initConfig({ + yeoman: yeomanConfig, + watch: { + haml: { + files: [ + '<%= yeoman.app %>/*.haml', + '<%= yeoman.app %>/views/{,*/}*.haml' + ], + tasks: ['haml:dist'] + }, + coffee: { + files: ['<%= yeoman.app %>/scripts/{,*/}*.coffee'], + tasks: ['coffee:dist'] + }, + coffeeTest: { + files: ['test/spec/{,*/}*.coffee'], + tasks: ['coffee:test'] + }, + compass: { + files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'], + tasks: ['compass'] + }, + livereload: { + files: [ + '<%= yeoman.app %>/{,*/}*.html', + '{.tmp,<%= yeoman.app %>}/styles/{,*/}*.css', + '{.tmp,<%= yeoman.app %>}/scripts/{,*/}*.js', + '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}' + ], + tasks: ['livereload'] + } }, - files: [{ - expand: true, - cwd: '<%= yeoman.app %>', - src: ['*.html', 'views/*.html'], - dest: '<%= yeoman.dist %>' - }] - } - }, - cdnify: { - dist: { - html: ['<%= yeoman.dist %>/*.html'] - } - }, - ngmin: { - dist: { - files: [{ - expand: true, - cwd: '<%= yeoman.dist %>/scripts', - src: '*.js', - dest: '<%= yeoman.dist %>/scripts' - }] - } - }, - uglify: { - dist: { - files: { - '<%= yeoman.dist %>/scripts/scripts.js': [ - '<%= yeoman.dist %>/scripts/scripts.js' - ] - } - } - }, - rev: { - dist: { - files: { - src: [ - '<%= yeoman.dist %>/scripts/{,*/}*.js', - '<%= yeoman.dist %>/styles/{,*/}*.css', - '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}', - '<%= yeoman.dist %>/styles/fonts/*' - ] + connect: { + options: { + port: 9000, + // Change this to '0.0.0.0' to access the server from outside. + hostname: 'localhost' + }, + livereload: { + options: { + middleware: function (connect) { + return [ + lrSnippet, + mountFolder(connect, '.tmp'), + mountFolder(connect, yeomanConfig.app) + ]; + } + } + }, + test: { + options: { + middleware: function (connect) { + return [ + mountFolder(connect, '.tmp'), + mountFolder(connect, 'test') + ]; + } + } + } + }, + open: { + server: { + url: 'http://localhost:<%= connect.options.port %>' + } + }, + clean: { + dist: { + files: [{ + dot: true, + src: [ + '.tmp', + '<%= yeoman.dist %>/*', + '!<%= yeoman.dist %>/.git*' + ] + }] + }, + server: '.tmp' + }, + jshint: { + options: { + jshintrc: '.jshintrc' + }, + all: [ + 'Gruntfile.js', + '<%= yeoman.app %>/scripts/{,*/}*.js' + ] + }, + karma: { + unit: { + configFile: 'karma.conf.js', + singleRun: true + } + }, + haml: { + options: { + language: 'ruby' + }, + dist: { + files: [{ + expand: true, + cwd: '<%= yeoman.app %>', + src: '{,*/}*.haml', + dest: '.tmp', + ext: '.html' + }] + } + }, + coffee: { + dist: { + files: [{ + expand: true, + cwd: '<%= yeoman.app %>/scripts', + src: '{,*/}*.coffee', + dest: '.tmp/scripts', + ext: '.js' + }] + }, + test: { + files: [{ + expand: true, + cwd: 'test/spec', + src: '{,*/}*.coffee', + dest: '.tmp/spec', + ext: '.js' + }] + } + }, + compass: { + options: { + sassDir: '<%= yeoman.app %>/styles', + cssDir: '.tmp/styles', + imagesDir: '<%= yeoman.app %>/images', + javascriptsDir: '<%= yeoman.app %>/scripts', + fontsDir: '<%= yeoman.app %>/styles/fonts', + importPath: '<%= yeoman.app %>/components', + relativeAssets: true + }, + dist: {}, + server: { + options: { + debugInfo: true + } + } + }, + concat: { + dist: { + files: { + '<%= yeoman.dist %>/scripts/scripts.js': [ + '.tmp/scripts/{,*/}*.js', + '<%= yeoman.app %>/scripts/{,*/}*.js' + ] + } + } + }, + useminPrepare: { + html: '<%= yeoman.app %>/index.html', + options: { + dest: '<%= yeoman.dist %>' + } + }, + usemin: { + html: ['<%= yeoman.dist %>/{,*/}*.html'], + css: ['<%= yeoman.dist %>/styles/{,*/}*.css'], + options: { + dirs: ['<%= yeoman.dist %>'] + } + }, + imagemin: { + dist: { + files: [{ + expand: true, + cwd: '<%= yeoman.app %>/images', + src: '{,*/}*.{png,jpg,jpeg}', + dest: '<%= yeoman.dist %>/images' + }] + } + }, + cssmin: { + dist: { + files: { + '<%= yeoman.dist %>/styles/main.css': [ + '.tmp/styles/{,*/}*.css', + '<%= yeoman.app %>/styles/{,*/}*.css' + ] + } + } + }, + htmlmin: { + dist: { + options: { + /*removeCommentsFromCDATA: true, + // https://github.com/yeoman/grunt-usemin/issues/44 + //collapseWhitespace: true, + collapseBooleanAttributes: true, + removeAttributeQuotes: true, + removeRedundantAttributes: true, + useShortDoctype: true, + removeEmptyAttributes: true, + removeOptionalTags: true*/ + }, + files: [{ + expand: true, + cwd: '<%= yeoman.app %>', + src: ['*.html', 'views/*.html'], + dest: '<%= yeoman.dist %>' + }] + } + }, + cdnify: { + dist: { + html: ['<%= yeoman.dist %>/*.html'] + } + }, + ngmin: { + dist: { + files: [{ + expand: true, + cwd: '<%= yeoman.dist %>/scripts', + src: '*.js', + dest: '<%= yeoman.dist %>/scripts' + }] + } + }, + uglify: { + dist: { + files: { + '<%= yeoman.dist %>/scripts/scripts.js': [ + '<%= yeoman.dist %>/scripts/scripts.js' + ] + } + } + }, + rev: { + dist: { + files: { + src: [ + '<%= yeoman.dist %>/scripts/{,*/}*.js', + '<%= yeoman.dist %>/styles/{,*/}*.css', + '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}', + '<%= yeoman.dist %>/styles/fonts/*' + ] + } + } + }, + copy: { + dist: { + files: [{ + expand: true, + dot: true, + cwd: '<%= yeoman.app %>', + dest: '<%= yeoman.dist %>', + src: [ + '*.{ico,txt}', + '.htaccess', + 'components/**/*', + 'images/{,*/}*.{gif,webp}', + 'styles/fonts/*' + ] + }] + } } - } - }, - copy: { - dist: { - files: [{ - expand: true, - dot: true, - cwd: '<%= yeoman.app %>', - dest: '<%= yeoman.dist %>', - src: [ - '*.{ico,txt}', - '.htaccess', - 'components/**/*', - 'images/{,*/}*.{gif,webp}', - 'styles/fonts/*' - ] - }] - } - } - }); + }); - grunt.renameTask('regarde', 'watch'); + grunt.renameTask('regarde', 'watch'); - grunt.registerTask('server', [ - 'clean:server', - 'haml:dist', - 'coffee:dist', - 'compass:server', - 'livereload-start', - 'connect:livereload', - 'open', - 'watch' - ]); + grunt.registerTask('server', [ + 'clean:server', + 'haml:dist', + 'coffee:dist', + 'compass:server', + 'livereload-start', + 'connect:livereload', + 'open', + 'watch' + ]); - grunt.registerTask('test', [ - 'clean:server', - 'haml', - 'coffee', - 'compass', - 'connect:test', - //'karma' - ]); + grunt.registerTask('test', [ + 'clean:server', + 'haml', + 'coffee', + 'compass', + 'connect:test', + //'karma' + ]); - grunt.registerTask('build', [ - 'clean:dist', - 'jshint', - 'test', - 'haml', - 'coffee', - 'compass:dist', - 'useminPrepare', - 'imagemin', - 'cssmin', - 'htmlmin', - 'concat', - 'copy', - 'cdnify', - 'ngmin', - 'uglify', - 'rev', - 'usemin' - ]); + grunt.registerTask('build', [ + 'clean:dist', + 'jshint', + 'test', + 'haml', + 'coffee', + 'compass:dist', + 'useminPrepare', + 'imagemin', + 'cssmin', + 'htmlmin', + 'concat', + 'copy', + 'cdnify', + 'ngmin', + 'uglify', + 'rev', + 'usemin' + ]); - grunt.registerTask('default', ['build']); + grunt.registerTask('default', ['build']); }; From d7d13b78e9910250efe1f5d2b96d9c302a482258 Mon Sep 17 00:00:00 2001 From: Alexander Novikov Date: Mon, 30 Mar 2015 13:31:38 +0200 Subject: [PATCH 04/23] add Gemfile with haml dependency --- Gemfile | 1 + 1 file changed, 1 insertion(+) create mode 100644 Gemfile diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..4eee842 --- /dev/null +++ b/Gemfile @@ -0,0 +1 @@ +gem 'haml' From 9d9b8400f9fe04ed0bc9e92bd2a87c4514e037b5 Mon Sep 17 00:00:00 2001 From: Alexander Novikov Date: Mon, 30 Mar 2015 14:37:17 +0200 Subject: [PATCH 05/23] add Compass gem --- Gemfile | 3 +++ Gemfile.lock | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 Gemfile.lock diff --git a/Gemfile b/Gemfile index 4eee842..45d72e0 100644 --- a/Gemfile +++ b/Gemfile @@ -1 +1,4 @@ +source 'https://rubygems.org' + gem 'haml' +gem 'compass' diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..7d3a779 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,32 @@ +GEM + remote: https://rubygems.org/ + specs: + chunky_png (1.3.4) + compass (1.0.3) + chunky_png (~> 1.2) + compass-core (~> 1.0.2) + compass-import-once (~> 1.0.5) + rb-fsevent (>= 0.9.3) + rb-inotify (>= 0.9) + sass (>= 3.3.13, < 3.5) + compass-core (1.0.3) + multi_json (~> 1.0) + sass (>= 3.3.0, < 3.5) + compass-import-once (1.0.5) + sass (>= 3.2, < 3.5) + ffi (1.9.8) + haml (4.0.6) + tilt + multi_json (1.11.0) + rb-fsevent (0.9.4) + rb-inotify (0.9.5) + ffi (>= 0.5.0) + sass (3.4.13) + tilt (2.0.1) + +PLATFORMS + ruby + +DEPENDENCIES + compass + haml From 5efb28788eaab0174ec939a497b018782d6886c7 Mon Sep 17 00:00:00 2001 From: Alexander Novikov Date: Mon, 30 Mar 2015 18:48:21 +0200 Subject: [PATCH 06/23] remove minifiers --- Gruntfile.js | 96 ++-------------------------------------------------- 1 file changed, 2 insertions(+), 94 deletions(-) mode change 100644 => 100755 Gruntfile.js diff --git a/Gruntfile.js b/Gruntfile.js old mode 100644 new mode 100755 index f7d686a..033f23e --- a/Gruntfile.js +++ b/Gruntfile.js @@ -163,94 +163,11 @@ module.exports = function (grunt) { } } }, - concat: { - dist: { - files: { - '<%= yeoman.dist %>/scripts/scripts.js': [ - '.tmp/scripts/{,*/}*.js', - '<%= yeoman.app %>/scripts/{,*/}*.js' - ] - } - } - }, - useminPrepare: { - html: '<%= yeoman.app %>/index.html', - options: { - dest: '<%= yeoman.dist %>' - } - }, - usemin: { - html: ['<%= yeoman.dist %>/{,*/}*.html'], - css: ['<%= yeoman.dist %>/styles/{,*/}*.css'], - options: { - dirs: ['<%= yeoman.dist %>'] - } - }, - imagemin: { - dist: { - files: [{ - expand: true, - cwd: '<%= yeoman.app %>/images', - src: '{,*/}*.{png,jpg,jpeg}', - dest: '<%= yeoman.dist %>/images' - }] - } - }, - cssmin: { - dist: { - files: { - '<%= yeoman.dist %>/styles/main.css': [ - '.tmp/styles/{,*/}*.css', - '<%= yeoman.app %>/styles/{,*/}*.css' - ] - } - } - }, - htmlmin: { - dist: { - options: { - /*removeCommentsFromCDATA: true, - // https://github.com/yeoman/grunt-usemin/issues/44 - //collapseWhitespace: true, - collapseBooleanAttributes: true, - removeAttributeQuotes: true, - removeRedundantAttributes: true, - useShortDoctype: true, - removeEmptyAttributes: true, - removeOptionalTags: true*/ - }, - files: [{ - expand: true, - cwd: '<%= yeoman.app %>', - src: ['*.html', 'views/*.html'], - dest: '<%= yeoman.dist %>' - }] - } - }, cdnify: { dist: { html: ['<%= yeoman.dist %>/*.html'] } }, - ngmin: { - dist: { - files: [{ - expand: true, - cwd: '<%= yeoman.dist %>/scripts', - src: '*.js', - dest: '<%= yeoman.dist %>/scripts' - }] - } - }, - uglify: { - dist: { - files: { - '<%= yeoman.dist %>/scripts/scripts.js': [ - '<%= yeoman.dist %>/scripts/scripts.js' - ] - } - } - }, rev: { dist: { files: { @@ -300,8 +217,7 @@ module.exports = function (grunt) { 'haml', 'coffee', 'compass', - 'connect:test', - //'karma' + 'connect:test' ]); grunt.registerTask('build', [ @@ -311,17 +227,9 @@ module.exports = function (grunt) { 'haml', 'coffee', 'compass:dist', - 'useminPrepare', - 'imagemin', - 'cssmin', - 'htmlmin', - 'concat', 'copy', 'cdnify', - 'ngmin', - 'uglify', - 'rev', - 'usemin' + 'rev' ]); grunt.registerTask('default', ['build']); From 861340e429e205604618a8b4f7a0e5ba570dd332 Mon Sep 17 00:00:00 2001 From: Alexander Novikov Date: Tue, 31 Mar 2015 08:38:04 +0200 Subject: [PATCH 07/23] fix & reformat main.css --- app/styles/main.css | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) mode change 100644 => 100755 app/styles/main.css diff --git a/app/styles/main.css b/app/styles/main.css old mode 100644 new mode 100755 index a039126..8d150b6 --- a/app/styles/main.css +++ b/app/styles/main.css @@ -1,37 +1,32 @@ -@media (max-width: 767px) -{ - body { - padding-right: 0px; - padding-left: 0px; - } +@media (max-width: 767px) { + body { + padding-right: 0; + padding-left: 0; + } } .chatbox { - font-family:Lato; - width:100%; - height:20em; - margin-top:6px; - overflow:scroll; + font-family: Lato; + width: 100%; + height: 20em; + margin-top: 6px; + overflow: scroll; } .userlabel { - margin-right:8px; - margin-top:6px; + margin-right: 8px; + margin-top: 6px; } .roomlabel { - margin-right:8px; - margin-top:6px; -} - -#getting_started { - background-color:; + margin-right: 8px; + margin-top: 6px; } .brandP { - padding-top:20px; + padding-top: 20px; } .padding-20 { - padding:20px; + padding: 20px; } From 5d4e8beac9553b7e671338e53b3dc85a829f6174 Mon Sep 17 00:00:00 2001 From: Alexander Novikov Date: Tue, 31 Mar 2015 08:53:46 +0200 Subject: [PATCH 08/23] fix compile destinations --- Gruntfile.js | 62 ++++++++-------------------------------------------- 1 file changed, 9 insertions(+), 53 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 033f23e..364b362 100755 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -37,10 +37,6 @@ module.exports = function (grunt) { files: ['test/spec/{,*/}*.coffee'], tasks: ['coffee:test'] }, - compass: { - files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'], - tasks: ['compass'] - }, livereload: { files: [ '<%= yeoman.app %>/{,*/}*.html', @@ -106,12 +102,6 @@ module.exports = function (grunt) { '<%= yeoman.app %>/scripts/{,*/}*.js' ] }, - karma: { - unit: { - configFile: 'karma.conf.js', - singleRun: true - } - }, haml: { options: { language: 'ruby' @@ -121,7 +111,7 @@ module.exports = function (grunt) { expand: true, cwd: '<%= yeoman.app %>', src: '{,*/}*.haml', - dest: '.tmp', + dest: 'dist', ext: '.html' }] } @@ -132,7 +122,7 @@ module.exports = function (grunt) { expand: true, cwd: '<%= yeoman.app %>/scripts', src: '{,*/}*.coffee', - dest: '.tmp/scripts', + dest: 'dist/scripts', ext: '.js' }] }, @@ -146,40 +136,6 @@ module.exports = function (grunt) { }] } }, - compass: { - options: { - sassDir: '<%= yeoman.app %>/styles', - cssDir: '.tmp/styles', - imagesDir: '<%= yeoman.app %>/images', - javascriptsDir: '<%= yeoman.app %>/scripts', - fontsDir: '<%= yeoman.app %>/styles/fonts', - importPath: '<%= yeoman.app %>/components', - relativeAssets: true - }, - dist: {}, - server: { - options: { - debugInfo: true - } - } - }, - cdnify: { - dist: { - html: ['<%= yeoman.dist %>/*.html'] - } - }, - rev: { - dist: { - files: { - src: [ - '<%= yeoman.dist %>/scripts/{,*/}*.js', - '<%= yeoman.dist %>/styles/{,*/}*.css', - '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}', - '<%= yeoman.dist %>/styles/fonts/*' - ] - } - } - }, copy: { dist: { files: [{ @@ -192,7 +148,12 @@ module.exports = function (grunt) { '.htaccess', 'components/**/*', 'images/{,*/}*.{gif,webp}', - 'styles/fonts/*' + 'styles/fonts/*', + 'images/**/*', + 'styles/*', + 'fonts/**/*', + 'index.html', + 'mini.html' ] }] } @@ -205,7 +166,6 @@ module.exports = function (grunt) { 'clean:server', 'haml:dist', 'coffee:dist', - 'compass:server', 'livereload-start', 'connect:livereload', 'open', @@ -216,7 +176,6 @@ module.exports = function (grunt) { 'clean:server', 'haml', 'coffee', - 'compass', 'connect:test' ]); @@ -226,10 +185,7 @@ module.exports = function (grunt) { 'test', 'haml', 'coffee', - 'compass:dist', - 'copy', - 'cdnify', - 'rev' + 'copy' ]); grunt.registerTask('default', ['build']); From 12f32f994765b758dc17eb2996142ba13d17c129 Mon Sep 17 00:00:00 2001 From: Alexander Novikov Date: Tue, 31 Mar 2015 11:01:47 +0200 Subject: [PATCH 09/23] update dist/main.css --- dist/styles/main.css | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/dist/styles/main.css b/dist/styles/main.css index a039126..8d150b6 100644 --- a/dist/styles/main.css +++ b/dist/styles/main.css @@ -1,37 +1,32 @@ -@media (max-width: 767px) -{ - body { - padding-right: 0px; - padding-left: 0px; - } +@media (max-width: 767px) { + body { + padding-right: 0; + padding-left: 0; + } } .chatbox { - font-family:Lato; - width:100%; - height:20em; - margin-top:6px; - overflow:scroll; + font-family: Lato; + width: 100%; + height: 20em; + margin-top: 6px; + overflow: scroll; } .userlabel { - margin-right:8px; - margin-top:6px; + margin-right: 8px; + margin-top: 6px; } .roomlabel { - margin-right:8px; - margin-top:6px; -} - -#getting_started { - background-color:; + margin-right: 8px; + margin-top: 6px; } .brandP { - padding-top:20px; + padding-top: 20px; } .padding-20 { - padding:20px; + padding: 20px; } From 26de44c5004e860abf2f96849bdda86c05fd9c12 Mon Sep 17 00:00:00 2001 From: Alexander Novikov Date: Wed, 1 Apr 2015 16:33:29 +0200 Subject: [PATCH 10/23] move blog_* files to blog folder --- blog_01.asciidoc => blog/blog_01.asciidoc | 0 blog_01.md => blog/blog_01.md | 0 blog_02.asciidoc => blog/blog_02.asciidoc | 0 blog_02.md => blog/blog_02.md | 0 blog_03.asciidoc => blog/blog_03.asciidoc | 0 blog_03.md => blog/blog_03.md | 0 blog_04.asciidoc => blog/blog_04.asciidoc | 0 blog_04.md => blog/blog_04.md | 0 blog_05.asciidoc => blog/blog_05.asciidoc | 0 blog_05.md => blog/blog_05.md | 0 blog_06.asciidoc => blog/blog_06.asciidoc | 0 blog_06.md => blog/blog_06.md | 0 blog_07.asciidoc => blog/blog_07.asciidoc | 0 blog_07.md => blog/blog_07.md | 0 blog_08.asciidoc => blog/blog_08.asciidoc | 0 blog_08.md => blog/blog_08.md | 0 blog_09.asciidoc => blog/blog_09.asciidoc | 0 blog_09.md => blog/blog_09.md | 0 blog_10.asciidoc => blog/blog_10.asciidoc | 0 blog_10.md => blog/blog_10.md | 0 blog_11.asciidoc => blog/blog_11.asciidoc | 0 blog_11.md => blog/blog_11.md | 0 blog_12.asciidoc => blog/blog_12.asciidoc | 0 23 files changed, 0 insertions(+), 0 deletions(-) rename blog_01.asciidoc => blog/blog_01.asciidoc (100%) rename blog_01.md => blog/blog_01.md (100%) rename blog_02.asciidoc => blog/blog_02.asciidoc (100%) rename blog_02.md => blog/blog_02.md (100%) rename blog_03.asciidoc => blog/blog_03.asciidoc (100%) rename blog_03.md => blog/blog_03.md (100%) rename blog_04.asciidoc => blog/blog_04.asciidoc (100%) rename blog_04.md => blog/blog_04.md (100%) rename blog_05.asciidoc => blog/blog_05.asciidoc (100%) rename blog_05.md => blog/blog_05.md (100%) rename blog_06.asciidoc => blog/blog_06.asciidoc (100%) rename blog_06.md => blog/blog_06.md (100%) rename blog_07.asciidoc => blog/blog_07.asciidoc (100%) rename blog_07.md => blog/blog_07.md (100%) rename blog_08.asciidoc => blog/blog_08.asciidoc (100%) rename blog_08.md => blog/blog_08.md (100%) rename blog_09.asciidoc => blog/blog_09.asciidoc (100%) rename blog_09.md => blog/blog_09.md (100%) rename blog_10.asciidoc => blog/blog_10.asciidoc (100%) rename blog_10.md => blog/blog_10.md (100%) rename blog_11.asciidoc => blog/blog_11.asciidoc (100%) rename blog_11.md => blog/blog_11.md (100%) rename blog_12.asciidoc => blog/blog_12.asciidoc (100%) diff --git a/blog_01.asciidoc b/blog/blog_01.asciidoc similarity index 100% rename from blog_01.asciidoc rename to blog/blog_01.asciidoc diff --git a/blog_01.md b/blog/blog_01.md similarity index 100% rename from blog_01.md rename to blog/blog_01.md diff --git a/blog_02.asciidoc b/blog/blog_02.asciidoc similarity index 100% rename from blog_02.asciidoc rename to blog/blog_02.asciidoc diff --git a/blog_02.md b/blog/blog_02.md similarity index 100% rename from blog_02.md rename to blog/blog_02.md diff --git a/blog_03.asciidoc b/blog/blog_03.asciidoc similarity index 100% rename from blog_03.asciidoc rename to blog/blog_03.asciidoc diff --git a/blog_03.md b/blog/blog_03.md similarity index 100% rename from blog_03.md rename to blog/blog_03.md diff --git a/blog_04.asciidoc b/blog/blog_04.asciidoc similarity index 100% rename from blog_04.asciidoc rename to blog/blog_04.asciidoc diff --git a/blog_04.md b/blog/blog_04.md similarity index 100% rename from blog_04.md rename to blog/blog_04.md diff --git a/blog_05.asciidoc b/blog/blog_05.asciidoc similarity index 100% rename from blog_05.asciidoc rename to blog/blog_05.asciidoc diff --git a/blog_05.md b/blog/blog_05.md similarity index 100% rename from blog_05.md rename to blog/blog_05.md diff --git a/blog_06.asciidoc b/blog/blog_06.asciidoc similarity index 100% rename from blog_06.asciidoc rename to blog/blog_06.asciidoc diff --git a/blog_06.md b/blog/blog_06.md similarity index 100% rename from blog_06.md rename to blog/blog_06.md diff --git a/blog_07.asciidoc b/blog/blog_07.asciidoc similarity index 100% rename from blog_07.asciidoc rename to blog/blog_07.asciidoc diff --git a/blog_07.md b/blog/blog_07.md similarity index 100% rename from blog_07.md rename to blog/blog_07.md diff --git a/blog_08.asciidoc b/blog/blog_08.asciidoc similarity index 100% rename from blog_08.asciidoc rename to blog/blog_08.asciidoc diff --git a/blog_08.md b/blog/blog_08.md similarity index 100% rename from blog_08.md rename to blog/blog_08.md diff --git a/blog_09.asciidoc b/blog/blog_09.asciidoc similarity index 100% rename from blog_09.asciidoc rename to blog/blog_09.asciidoc diff --git a/blog_09.md b/blog/blog_09.md similarity index 100% rename from blog_09.md rename to blog/blog_09.md diff --git a/blog_10.asciidoc b/blog/blog_10.asciidoc similarity index 100% rename from blog_10.asciidoc rename to blog/blog_10.asciidoc diff --git a/blog_10.md b/blog/blog_10.md similarity index 100% rename from blog_10.md rename to blog/blog_10.md diff --git a/blog_11.asciidoc b/blog/blog_11.asciidoc similarity index 100% rename from blog_11.asciidoc rename to blog/blog_11.asciidoc diff --git a/blog_11.md b/blog/blog_11.md similarity index 100% rename from blog_11.md rename to blog/blog_11.md diff --git a/blog_12.asciidoc b/blog/blog_12.asciidoc similarity index 100% rename from blog_12.asciidoc rename to blog/blog_12.asciidoc From d5b5d18488a4fc56dbeaf981cf7be3a9385f649d Mon Sep 17 00:00:00 2001 From: Alexander Novikov Date: Wed, 1 Apr 2015 17:53:48 +0200 Subject: [PATCH 11/23] remove component.json --- Gruntfile.js | 5 ----- component.json | 16 ---------------- 2 files changed, 21 deletions(-) delete mode 100644 component.json diff --git a/Gruntfile.js b/Gruntfile.js index 364b362..c8d8a92 100755 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -14,11 +14,6 @@ module.exports = function (grunt) { dist: 'dist' }; - try { - yeomanConfig.app = require('./component.json').appPath || yeomanConfig.app; - } catch (e) { - } - grunt.initConfig({ yeoman: yeomanConfig, watch: { diff --git a/component.json b/component.json deleted file mode 100644 index de03e85..0000000 --- a/component.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "angularPubnubApp", - "version": "0.0.0", - "dependencies": { - "angular": "~1.0.5", - "json3": "~3.2.4", - "es5-shim": "~2.0.8", - "angular-resource": "~1.0.5", - "angular-cookies": "~1.0.5", - "angular-sanitize": "~1.0.5" - }, - "devDependencies": { - "angular-mocks": "~1.0.5", - "angular-scenario": "~1.0.5" - } -} From a02ba77ec4575e5be9c25286c3b60c56fe5bb9b6 Mon Sep 17 00:00:00 2001 From: Alexander Novikov Date: Wed, 8 Apr 2015 08:21:35 +0200 Subject: [PATCH 12/23] working on app --- bower.json | 11 + dist/index.html | 12 +- dist/scripts/app.js | 20 +- dist/scripts/controllers/main.js | 497 +++++++++++++++++++------------ dist/scripts/pubnub-angular.js | 193 ------------ dist/views/chat.html | 8 +- 6 files changed, 334 insertions(+), 407 deletions(-) create mode 100755 bower.json mode change 100644 => 100755 dist/index.html mode change 100644 => 100755 dist/scripts/app.js mode change 100644 => 100755 dist/scripts/controllers/main.js delete mode 100644 dist/scripts/pubnub-angular.js mode change 100644 => 100755 dist/views/chat.html diff --git a/bower.json b/bower.json new file mode 100755 index 0000000..5dd3819 --- /dev/null +++ b/bower.json @@ -0,0 +1,11 @@ +{ + "name": "pubnub-angular-demo-app", + "version": "0.9.1", + "dependencies": { + "pubnub-angular": "../pubnub-angular/src/pubnub-angular.js", + "angular": "1.4.0-beta.6", + "angular-route": "1.4.0-beta.6", + "jquery": "~2.1.3", + "underscore": "~1.8.3" + } +} diff --git a/dist/index.html b/dist/index.html old mode 100644 new mode 100755 index 0b3313e..54af3a4 --- a/dist/index.html +++ b/dist/index.html @@ -5,10 +5,12 @@ AngularJS PubNub Chat Application - - - - + + + + + + @@ -22,7 +24,7 @@
- + diff --git a/dist/scripts/app.js b/dist/scripts/app.js old mode 100644 new mode 100755 index 149b574..71aadae --- a/dist/scripts/app.js +++ b/dist/scripts/app.js @@ -1,15 +1,13 @@ -(function() { - 'use strict'; - angular.module('PubNubAngularApp', ["pubnub.angular.service"]).config(function($routeProvider) { +angular.module('PubNubAngularApp', ["pubnub.angular.service", 'ngRoute']).config(function ($routeProvider) { + 'use strict'; + return $routeProvider.when('/join', { - templateUrl: 'views/join.html', - controller: 'JoinCtrl' + templateUrl: 'views/join.html', + controller: 'JoinCtrl' }).when('/chat', { - templateUrl: 'views/chat.html', - controller: 'ChatCtrl' + templateUrl: 'views/chat.html', + controller: 'ChatCtrl' }).otherwise({ - redirectTo: '/join' + redirectTo: '/join' }); - }); - -}).call(this); +}); diff --git a/dist/scripts/controllers/main.js b/dist/scripts/controllers/main.js old mode 100644 new mode 100755 index 60d2d3b..4cc3956 --- a/dist/scripts/controllers/main.js +++ b/dist/scripts/controllers/main.js @@ -1,229 +1,338 @@ -(function() { - 'use strict'; - /* - The JoinCtrl is responsible for collecting the username and calling the PubNub.init() method - when the "Join" button is clicked. - */ - - angular.module('PubNubAngularApp').controller('JoinCtrl', function($rootScope, $scope, $location, PubNub) { +// TODO: super user behaviour +angular.module('PubNubAngularApp').controller('JoinCtrl', function ($rootScope, $scope, $location, Pubnub) { + "use strict"; + + $rootScope.initialized = false; + $scope.data = { - username: 'Anonymous ' + Math.floor(Math.random() * 1000) + username: 'Anonymous ' + Math.floor(Math.random() * 1000) }; - $scope.join = function() { - var _ref, _ref1, _ref2; - $rootScope.data || ($rootScope.data = {}); - $rootScope.data.username = (_ref = $scope.data) != null ? _ref.username : void 0; - $rootScope.data.city = (_ref1 = $scope.data) != null ? _ref1.city : void 0; - $rootScope.data["super"] = (_ref2 = $scope.data) != null ? _ref2["super"] : void 0; - $rootScope.data.uuid = Math.floor(Math.random() * 1000000) + '__' + $scope.data.username; - $rootScope.secretKey = $scope.data["super"] ? 'sec-c-MmIzMDAzNDMtODgxZC00YzM3LTk1NTQtMzc4NWQ1NmZhYjIy' : null; - $rootScope.authKey = $scope.data["super"] ? 'ChooseABetterSecret' : null; - PubNub.init({ - subscribe_key: 'sub-c-d66562f0-62b0-11e3-b12d-02ee2ddab7fe', - publish_key: 'pub-c-e2b65946-31f0-4941-a1b8-45bab0032dd8', - secret_key: $rootScope.secretKey, - auth_key: $rootScope.authKey, - uuid: $rootScope.data.uuid, - ssl: true - }); - if ($scope.data["super"]) { - /* Grant access to the SuperHeroes room for supers only!*/ - - PubNub.ngGrant({ - channel: 'SuperHeroes', - auth_key: $rootScope.authKey, - read: true, - write: true, - callback: function() { - return console.log('SuperHeroes! all set', arguments); - } - }); - PubNub.ngGrant({ - channel: "SuperHeroes-pnpres", - auth_key: $rootScope.authKey, - read: true, - write: false, - callback: function() { - return console.log('SuperHeroes! presence all set', arguments); - } - }); - PubNub.ngGrant({ - channel: '__controlchannel', - read: true, - write: true, - callback: function() { - return console.log('control channel all set', arguments); - } - }); - PubNub.ngGrant({ - channel: '__controlchannel-pnpres', - read: true, - write: false, - callback: function() { - return console.log('control channel presence all set', arguments); - } + + $scope.join = function () { + var _ref, _ref1, _ref2; + + // TODO: simplify initialization + $rootScope.data || ($rootScope.data = {}); + $rootScope.data.username = (_ref = $scope.data) != null ? _ref.username : void 0; + $rootScope.data.city = (_ref1 = $scope.data) != null ? _ref1.city : void 0; + $rootScope.data.super = (_ref2 = $scope.data) != null ? _ref2.super : void 0; + $rootScope.data.uuid = Math.floor(Math.random() * 1000000) + '__' + $scope.data.username; + $rootScope.secretKey = $scope.data["super"] ? 'sec-c-MmIzMDAzNDMtODgxZC00YzM3LTk1NTQtMzc4NWQ1NmZhYjIy' : null; + $rootScope.authKey = $scope.data["super"] ? 'ChooseABetterSecret' : null; + + Pubnub.init({ + subscribe_key: 'sub-c-d66562f0-62b0-11e3-b12d-02ee2ddab7fe', + publish_key: 'pub-c-e2b65946-31f0-4941-a1b8-45bab0032dd8', + secret_key: $rootScope.secretKey, + auth_key: $rootScope.authKey, + uuid: $rootScope.data.uuid, + ssl: true }); - } - return $location.path('/chat'); - }; - return $(".prettyprint"); - }); - /* - The ChatCtrl is responsible for creating, displaying, subscribing to, and - chatting in channels - */ + $rootScope.initialized = true; + + if ($scope.data["super"]) { + + /* Grant access to the SuperHeroes room for supers only!*/ + Pubnub.grant({ + channel: 'SuperHeroes', + auth_key: $rootScope.authKey, + read: true, + write: true, + callback: function () { + return console.log('SuperHeroes! all set', arguments); + } + }); + Pubnub.grant({ + channel: "SuperHeroes-pnpres", + auth_key: $rootScope.authKey, + read: true, + write: false, + callback: function () { + return console.log('SuperHeroes! presence all set', arguments); + } + }); - angular.module('PubNubAngularApp').controller('ChatCtrl', function($rootScope, $scope, $location, PubNub) { + Pubnub.grant({ + channel: '__controlchannel', + read: true, + write: true, + callback: function () { + return console.log('control channel all set', arguments); + } + }); + + Pubnub.grant({ + channel: '__controlchannel-pnpres', + read: true, + write: false, + callback: function () { + return console.log('control channel presence all set', arguments); + } + }); + } + + $location.path('/chat'); + }; +}); + +angular.module('PubNubAngularApp').controller('ChatCtrl', function ($rootScope, $scope, $location, Pubnub) { var _ref; - if (!PubNub.initialized()) { - $location.path('/join'); + + if (!$rootScope.initialized) { + $location.path('/join'); } - /* Use a "control channel" to collect channel creation messages*/ + /* Use a "control channel" to collect channel creation messages*/ $scope.controlChannel = '__controlchannel'; $scope.channels = []; - /* Publish a chat message*/ - - $scope.publish = function() { - console.log('publish', $scope); - if (!$scope.selectedChannel) { - return; - } - PubNub.ngPublish({ - channel: $scope.selectedChannel, - message: { - text: $scope.newMessage, - user: $scope.data.username + + $scope.publish = function () { + if (!$scope.selectedChannel) { + return; } - }); - return $scope.newMessage = ''; + + Pubnub.publish({ + channel: $scope.selectedChannel, + message: { + text: $scope.newMessage, + user: $scope.data.username + } + }); + + $scope.newMessage = ''; }; - /* Create a new channel*/ - - $scope.createChannel = function() { - var channel; - console.log('createChannel', $scope); - if (!($scope.data["super"] && $scope.newChannel)) { - return; - } - channel = $scope.newChannel; - $scope.newChannel = ''; - PubNub.ngGrant({ - channel: channel, - read: true, - write: true, - callback: function() { - return console.log("" + channel + " all set", arguments); - } - }); - PubNub.ngGrant({ - channel: "" + channel + "-pnpres", - read: true, - write: false, - callback: function() { - return console.log("" + channel + " presence all set", arguments); + + $scope.createChannel = function () { + var channel; + + if (!($scope.data.super && $scope.newChannel)) { + return; } - }); - PubNub.ngPublish({ - channel: $scope.controlChannel, - message: channel - }); - return setTimeout(function() { - $scope.subscribe(channel); - return $scope.showCreate = false; - }, 100); + + channel = $scope.newChannel; + $scope.newChannel = ''; + + Pubnub.grant({ + channel: channel, + read: true, + write: true, + callback: function () { + console.log(channel + " all set", arguments); + } + }); + + Pubnub.grant({ + channel: channel + "-pnpres", + read: true, + write: false, + callback: function () { + console.log(channel + " presence all set", arguments); + } + }); + + Pubnub.publish({ + channel: $scope.controlChannel, + message: channel + }); + + setTimeout(function () { + $scope.subscribe(channel); + $scope.showCreate = false; + }, 100); }; + /* Select a channel to display chat history & presence*/ + $scope.subscribe = function (channel) { + if (channel === $scope.selectedChannel) { + return; + } + + var scheduledHereNowIntervalMs = 60000, + presencePool = []; + + $scope.users = {}; + + if ($scope.selectedChannel) { + Pubnub.unsubscribe({ + channel: $scope.selectedChannel + }); + } + + $scope.selectedChannel = channel; + $scope.messages = ['Welcome to ' + channel]; - $scope.subscribe = function(channel) { - var _ref; - console.log('subscribe', channel); - if (channel === $scope.selectedChannel) { - return; - } - if ($scope.selectedChannel) { - PubNub.ngUnsubscribe({ - channel: $scope.selectedChannel + Pubnub.subscribe({ + channel: $scope.selectedChannel, + auth_key: $scope.authKey, + state: { + city: $rootScope.data.city || 'unknown city', + name: $scope.data.username + }, + connect: function () { + synchronizeUsers(); + setInterval(synchronizeUsers, scheduledHereNowIntervalMs); + } }); - } - $scope.selectedChannel = channel; - $scope.messages = ['Welcome to ' + channel]; - PubNub.ngSubscribe({ - channel: $scope.selectedChannel, - auth_key: $scope.authKey, - state: { - "city": ((_ref = $rootScope.data) != null ? _ref.city : void 0) || 'unknown' - }, - error: function() { - return console.log(arguments); + + function addToPresencePool (pnEvent) { + presencePool.push(pnEvent); } - }); - $rootScope.$on(PubNub.ngPrsEv($scope.selectedChannel), function(ngEvent, payload) { - return $scope.$apply(function() { - var newData, userData; - userData = PubNub.ngPresenceData($scope.selectedChannel); - newData = {}; - $scope.users = PubNub.map(PubNub.ngListPresence($scope.selectedChannel), function(x) { - var newX; - newX = x; - if (x.replace) { - newX = x.replace(/\w+__/, ""); + + function applyPresencePool () { + if (presencePool === null) return; + + var l = presencePool.length, + i; + + for (i = 0; i < l; i++) { + applyEvent(presencePool[i]); + } + + presencePool = null; + } + + function applyEvent (pnEvent) { + if ('data' in pnEvent) { + switch (pnEvent.action) { + case 'join': + // fallback to previous version user naming + if ('data' in pnEvent && !('name' in pnEvent.data)) { + pnEvent.data.name = pnEvent.uuid.replace(/\w+__/, ""); + } + + $scope.$apply(function () { + $scope.users[pnEvent.uuid] = pnEvent.data; + }); + break; + case 'leave': + $scope.$apply(function () { + delete $scope.users[pnEvent.uuid]; + }); + delete $scope.users[pnEvent.uuid]; + break; + default: + break; + } } - if (x.uuid) { - newX = x.uuid.replace(/\w+__/, ""); + } + + function synchronizeUsers () { + Pubnub.here_now({ + channel: $scope.selectedChannel, + state: true, + callback: function (response) { + if (!('uuids' in response)) { + console.warn("There are not users on channel '" + $scope.selectedChannel + "'"); + return; + } + + var newUsersData = {}, + length = response.uuids.length, + currentUser, + i; + + for (i = 0; i < length; i++) { + currentUser = response.uuids[i]; + newUsersData[currentUser.uuid] = currentUser.state; + + // fallback to previous version user naming + if ('state' in currentUser && !('name' in currentUser.state)) { + newUsersData[currentUser.uuid]['name'] = currentUser.uuid.replace(/\w+__/, ""); + } + } + + $scope.$apply(function () { + $scope.users = newUsersData; + }); + + applyPresencePool(); + } + }); + } + + $rootScope.$on(Pubnub.getPresenceEventNameFor($scope.selectedChannel), function (ngEvent, message) { + var pnEvent = message[0], + channel = message[2]; + + if (channel === $scope.selectedChannel) { + if (presencePool === null) { + applyEvent(pnEvent); + } else { + addToPresencePool(pnEvent); + } } - newData[newX] = userData[x] || {}; - return newX; - }); - return $scope.userData = newData; }); - }); - PubNub.ngHereNow({ - channel: $scope.selectedChannel - }); - $rootScope.$on(PubNub.ngMsgEv($scope.selectedChannel), function(ngEvent, payload) { - var msg; - msg = payload.message.user ? "[" + payload.message.user + "] " + payload.message.text : "[unknown] " + payload.message; - return $scope.$apply(function() { - return $scope.messages.unshift(msg); + + function wrapMessage(message) { + return message.user ? "[" + message.user + "] " + message.text : "[unknown] " + message; + } + + $rootScope.$on(Pubnub.getMessageEventNameFor($scope.selectedChannel), function (ngEvent, payload) { + $scope.$apply(function () { + $scope.messages.unshift(wrapMessage(payload[0])); + }); + }); + + Pubnub.history({ + channel: $scope.selectedChannel, + auth_key: $scope.authKey, + count: 500, + reverse: false, + callback: function (result) { + var messages = result[0], + wrappedMessagesArray = [], + length = messages.length, + i; + + for (i = 0; i < length; i++) { + wrappedMessagesArray[i] = wrapMessage(messages[i]); + } + + $scope.$apply(function () { + $scope.messages = wrappedMessagesArray.reverse(); + }) + } }); - }); - return PubNub.ngHistory({ - channel: $scope.selectedChannel, - auth_key: $scope.authKey, - count: 500 - }); }; - /* When controller initializes, subscribe to retrieve channels from "control channel"*/ - PubNub.ngSubscribe({ - channel: $scope.controlChannel + Pubnub.subscribe({ + channel: $scope.controlChannel, + triggerEvent: true }); - /* Register for channel creation message events*/ - $rootScope.$on(PubNub.ngMsgEv($scope.controlChannel), function(ngEvent, payload) { - return $scope.$apply(function() { - if ($scope.channels.indexOf(payload.message) < 0) { - return $scope.channels.push(payload.message); - } - }); + $rootScope.$on(Pubnub.getMessageEventNameFor($scope.controlChannel), function (ngEvent, payload) { + $scope.$apply(function () { + if ($scope.channels.indexOf(payload.message) < 0) { + $scope.channels.push(payload.message); + } + }); }); - /* Get a reasonable historical backlog of messages to populate the channels list*/ - PubNub.ngHistory({ - channel: $scope.controlChannel, - count: 500 + /* Get a reasonable historical backlog of messages to populate the channels list*/ + Pubnub.history({ + channel: $scope.controlChannel, + count: 500, + callback: function (response) { + $scope.channels = _.uniq(response[0]); + } }); - /* and finally, create and/or enter the 'WaitingRoom' channel*/ + /* and finally, create and/or enter the 'WaitingRoom' channel*/ if ((_ref = $scope.data) != null ? _ref["super"] : void 0) { - $scope.newChannel = 'WaitingRoom'; - return $scope.createChannel(); + $scope.newChannel = 'WaitingRoom'; + $scope.createChannel(); } else { - return $scope.subscribe('WaitingRoom'); + $scope.subscribe('WaitingRoom'); } - }); -}).call(this); + $scope.sign_out = function () { + Pubnub.unsubscribe({ + channel: $scope.channels, + callback: function () { + $location.path('/join'); + } + }); + }; +}); diff --git a/dist/scripts/pubnub-angular.js b/dist/scripts/pubnub-angular.js deleted file mode 100644 index f7df831..0000000 --- a/dist/scripts/pubnub-angular.js +++ /dev/null @@ -1,193 +0,0 @@ -(function() { - 'use strict'; - angular.module('pubnub.angular.service', []).factory('PubNub', [ - '$rootScope', function($rootScope) { - var c, k, _i, _len, _ref; - c = { - '_instance': null, - '_channels': [], - '_presence': {}, - 'jsapi': {} - }; - _ref = ['map', 'each']; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - k = _ref[_i]; - if ((typeof PUBNUB !== "undefined" && PUBNUB !== null ? PUBNUB[k] : void 0) instanceof Function) { - (function(kk) { - return c[kk] = function() { - var _ref1; - return (_ref1 = c['_instance']) != null ? _ref1[kk].apply(c['_instance'], arguments) : void 0; - }; - })(k); - } - } - for (k in PUBNUB) { - if ((typeof PUBNUB !== "undefined" && PUBNUB !== null ? PUBNUB[k] : void 0) instanceof Function) { - (function(kk) { - return c['jsapi'][kk] = function() { - var _ref1; - return (_ref1 = c['_instance']) != null ? _ref1[kk].apply(c['_instance'], arguments) : void 0; - }; - })(k); - } - } - c.initialized = function() { - return !!c['_instance']; - }; - c.init = function() { - c['_instance'] = PUBNUB.init.apply(PUBNUB, arguments); - c['_channels'] = []; - c['_presence'] = {}; - c['_presData'] = {}; - return c['_instance']; - }; - c.destroy = function() { - c['_instance'] = null; - c['_channels'] = null; - c['_presence'] = null; - return c['_presData'] = null; - }; - c._ngFireMessages = function(realChannel) { - return function(messages, t1, t2) { - return c.each(messages[0], function(message) { - return $rootScope.$broadcast("pn-message:" + realChannel, { - message: message, - channel: realChannel - }); - }); - }; - }; - c._ngInstallHandlers = function(args) { - var oldmessage, oldpresence; - oldmessage = args.message; - args.message = function() { - $rootScope.$broadcast(c.ngMsgEv(args.channel), { - message: arguments[0], - env: arguments[1], - channel: args.channel - }); - if (oldmessage) { - return oldmessage(arguments); - } - }; - oldpresence = args.presence; - args.presence = function() { - var channel, cpos, event, _base, _base1; - event = arguments[0]; - channel = args.channel; - if (event.uuids) { - c.each(event.uuids, function(uuid) { - var state, _base, _base1; - state = uuid.state ? uuid.state : null; - uuid = uuid.uuid ? uuid.uuid : uuid; - (_base = c['_presence'])[channel] || (_base[channel] = []); - if (c['_presence'][channel].indexOf(uuid) < 0) { - c['_presence'][channel].push(uuid); - } - (_base1 = c['_presData'])[channel] || (_base1[channel] = {}); - if (state) { - return c['_presData'][channel][uuid] = state; - } - }); - } else { - if (event.uuid && event.action) { - (_base = c['_presence'])[channel] || (_base[channel] = []); - (_base1 = c['_presData'])[channel] || (_base1[channel] = {}); - if (event.action === 'leave') { - cpos = c['_presence'][channel].indexOf(event.uuid); - if (cpos !== -1) { - c['_presence'][channel].splice(cpos, 1); - } - delete c['_presData'][channel][event.uuid]; - } else { - if (c['_presence'][channel].indexOf(event.uuid) < 0) { - c['_presence'][channel].push(event.uuid); - } - if (event.data) { - c['_presData'][channel][event.uuid] = event.data; - } - } - } - } - $rootScope.$broadcast(c.ngPrsEv(args.channel), { - event: event, - message: arguments[1], - channel: channel - }); - if (oldpresence) { - return oldpresence(arguments); - } - }; - return args; - }; - c.ngListChannels = function() { - return c['_channels'].slice(0); - }; - c.ngListPresence = function(channel) { - var _ref1; - return (_ref1 = c['_presence'][channel]) != null ? _ref1.slice(0) : void 0; - }; - c.ngPresenceData = function(channel) { - return c['_presData'][channel] || {}; - }; - c.ngSubscribe = function(args) { - var _base, _name; - if (c['_channels'].indexOf(args.channel) < 0) { - c['_channels'].push(args.channel); - } - (_base = c['_presence'])[_name = args.channel] || (_base[_name] = []); - args = c._ngInstallHandlers(args); - return c.jsapi.subscribe(args); - }; - c.ngUnsubscribe = function(args) { - var cpos; - cpos = c['_channels'].indexOf(args.channel); - if (cpos !== -1) { - c['_channels'].splice(cpos, 1); - } - c['_presence'][args.channel] = null; - delete $rootScope.$$listeners[c.ngMsgEv(args.channel)]; - delete $rootScope.$$listeners[c.ngPrsEv(args.channel)]; - return c.jsapi.unsubscribe(args); - }; - c.ngPublish = function() { - return c['_instance']['publish'].apply(c['_instance'], arguments); - }; - c.ngHistory = function(args) { - args.callback = c._ngFireMessages(args.channel); - return c.jsapi.history(args); - }; - c.ngHereNow = function(args) { - args = c._ngInstallHandlers(args); - args.state = true; - args.callback = args.presence; - delete args.presence; - delete args.message; - return c.jsapi.here_now(args); - }; - c.ngWhereNow = function(args) { - return c.jsapi.where_now(args); - }; - c.ngState = function(args) { - return c.jsapi.state(args); - }; - c.ngMsgEv = function(channel) { - return "pn-message:" + channel; - }; - c.ngPrsEv = function(channel) { - return "pn-presence:" + channel; - }; - c.ngAuth = function() { - return c['_instance']['auth'].apply(c['_instance'], arguments); - }; - c.ngAudit = function() { - return c['_instance']['audit'].apply(c['_instance'], arguments); - }; - c.ngGrant = function() { - return c['_instance']['grant'].apply(c['_instance'], arguments); - }; - return c; - } - ]); - -}).call(this); diff --git a/dist/views/chat.html b/dist/views/chat.html old mode 100644 new mode 100755 index e7f918c..678aa12 --- a/dist/views/chat.html +++ b/dist/views/chat.html @@ -18,7 +18,7 @@

Welcome {{data.username}}, click to select a channel below ( -sign out +sign out )
+ +
+
    +
  • + +   + {{message}} +
  • +
+
+

+ + +
diff --git a/views/join.html b/views/join.html old mode 100644 new mode 100755 index 9d200ec..32e06c2 --- a/views/join.html +++ b/views/join.html @@ -1,18 +1,19 @@
-
-
-

-PubNub AngularJS Chat Example -

-

-Not Connected Yet -To enter the sample Chat application, choose a username and press the "Join" button above -

- -
-
+
+
+

+ PubNub AngularJS Chat Example +

+ +

+ Not Connected Yet + To enter the sample Chat application, choose a username and press the "Join" button above +

+ +
+
From 0ffb739b77a8939d849fcc16d36e4977819f8146 Mon Sep 17 00:00:00 2001 From: Alexander Novikov Date: Tue, 21 Apr 2015 11:09:19 +0200 Subject: [PATCH 21/23] remove obsolete docs --- views/_content.html | 250 -------------------------------------------- 1 file changed, 250 deletions(-) diff --git a/views/_content.html b/views/_content.html index 1fcc005..35e03ea 100755 --- a/views/_content.html +++ b/views/_content.html @@ -1,252 +1,2 @@
-
-
-
-
-
-

Getting Started

- -

The HTML page includes 3 key libraries:

-
    -
  • The core PubNub JS Library (generally from the CDN)
  • -
  • AngularJS (usually as a Bower component)
  • -
  • PubNub Angular (copy & paste for now - bower component coming soon!)
  • -
-

The HTML script includes look like this:

-
<script src="http://cdn.pubnub.com/pubnub.min.js"></script>
-<script src="components/angular/angular.js"></script>
-<script src="scripts/pubnub-angular.js"></script>
-

The app is Angular-enabled with an ng-app attribute:

-
<body ng-app="PubNubAngularApp">
-

Where 'PubNubAngularApp' is the name of the Angular module containing our app.

- -

The code for the app lives in:

-
<script src="scripts/app.js"></script>
-
-
-
-
-
-
-

PubNub Angular API Tour

- -

The PubNub Angular API lives in the scripts/pubnub-angular.js file.

- -

Notice the dependency on the PubNub Angular library (pubnub.angular.service):

-
angular.module('PubNubAngularApp', ["pubnub.angular.service"])
-

The code for the controllers lives in:

-
<script src="scripts/controllers/main.js"></script>
-

Now, the PubNub service can be injected into the controller by name!

-
.controller('JoinCtrl', function($scope, PubNub) { ... });
-

Using the Special AngularJS PubNub API

- -

Publishing to channels is trivial - just use the PubNub.ngPublish() method.

-
$scope.publish = function() {
-  PubNub.ngPublish({
-    channel: $scope.selectedChannel,
-    message: $scope.newMessage
-  });
-};
-

- As you can see, we call the PubNub publish method passing in the desired - channel and message to transmit. It is also possible to transmit structured - data as JSON objects, so go wild! -

- -

- It's not necessary to subscribe to a channel in order to publish to a channel. -

- -

- Subscribing to channels is accomplished by calling the PubNub.ngSubscribe() - method. After the channel is subscribed, the app can register root scope message events - by calling $rootScope.$on with the event string returned by - PubNub.ngMsgEv(channel). -

-
$scope.subscribe = function() {
-  ...
-  PubNub.ngSubscribe({ channel: theChannel })
-  ...
-  $rootScope.$on(PubNub.ngMsgEv(theChannel), function(event, payload) {
-    // payload contains message, channel, env...
-    console.log('got a message event:', payload);    
-  })
-

- This is the core of the PubNub API - allowing clients to subscribe and - publish to channels, and have those events propagate in real-time to other - applications connected to the same channels. -

-

Integrating Presence Events

- -

- It's also easy to integrate presence events using the Angular API. In - the example above, we just add an additional couple lines of code to - call the PubNub.ngHereNow() method (retrieve current users), and register - for presence events by calling $rootScope.$on with the event string - returned by PubNub.ngPrsEv(channel). -

-
$scope.subscribe = function() {
-  ...
-  PubNub.ngSubscribe({ channel: theChannel })
-  $rootScope.$on(PubNub.ngMsgEv(theChannel), function(event, payload) { ... })
-  ...
-  $rootScope.$on(PubNub.ngPrsEv(theChannel), function(event, payload) {
-    // payload contains message, channel, env...
-    console.log('got a presence event:', payload);
-  })
-
-  PubNub.ngHereNow { channel: theChannel }
-

- Using the presence event as a trigger, we retrieve the Presence - list for a channel using the PubNub.ngListPresence(channel) - function. -

-
$rootScope.$on(PubNub.ngPrsEv(theChannel), function(event, payload) {
-  $scope.users = PubNub.ngListPresence(theChannel);
-})
-

- It's also possible to retrieve the extended Presence state data - for a channel using the PubNub.ngPresenceData(channel) - function. -

-
$rootScope.$on(PubNub.ngPrsEv(theChannel), function(event, payload) {
-  $scope.userData = PubNub.ngPresenceData(theChannel);
-})
-

Retrieving History

- -

- It can be super-handy to gather the previous several hundred messages - from the PubNub channel history. The PubNub Angular API makes this easy - by bridging the event model of the PubNub JS history API and the AngularJS - event broadcast model so that historical messages come through the same - event interface. -

-
PubNub.ngHistory({channel:theChannel, count:500});
-// messages will be broadcast via $rootScope...
-

Listing & Unsubscribing from Channels

- -

- The PubNub Angular API takes care of keeping track of currently subscribed - channels. Call the PubNub.ngListChannels() method to return a - list of presently subscribed channels. -

-
$scope.channels = PubNub.ngListChannels()
-

- Unsubscribing is as easy as calling the PubNub.ngUnsubscribe() - method. The library even takes care of removing the Angular event handlers - for you to prevent unsightly memory leaks! -

-
PubNub.ngUnsubscribe({channel:theChannel})
-

Restricting Access (Advanced)

- -

- Often times, it's desirable to lock down applications and channels. - With PAM (PubNub Access Manager), it's easy. There are 2 calls: - grant which grants access for users having a specified - auth key, and audit which returns the current policy - configuration. -

- -

- Note: to perform access control operations, the PubNub client must - be initialized with the secret key (which should always be protected - by server-only access). -

-
PubNub.ngGrant({channel:theChannel,auth_key:'readers_must_have_this_secret',read:true,write:false,callback:function(){...}});
-# now clients providing the auth key can read...
-
-PubNub.ngAudit({channel:theChannel,auth_key:'readers_must_have_this_secret',callback:function(policy){...}});
-# calls back with the policy description as a JSON object...
-

- If this is interesting to you, see http://www.pubnub.com/docs/javascript/overview/security.html - for more details! -

-
-
-
-

PubNub Angular API Reference

-

Core Angular API Methods

-
    -
  • PubNub.init({publish_key:'your_key',subscribe_key:'your_key',uuid:'an_optional_user_uuid'}): - initialize the PubNub Angular API with the specified values -
  • -
  • PubNub.ngSubscribe({channel:aChannel,message:aCallback,presence:anotherCallback}): - subscribe to the specified channel; the provided callbacks (if any) will be invoked by wrapper - functions that also maintain the Angular data structures for channels list and presence -
  • -
  • PubNub.ngUnsubscribe({channel:aChannel}): unsubscribe from the specified channel - including any message/presence events -
  • -
  • PubNub.ngPublish({channel:aChannel,message:aMessage}): publish a message to the - specified channel -
  • -
  • PubNub.ngHistory({channel:aChannel}): calls PUBNUB.history with the specified - channel to produce root scope message broadcast events (make sure the code is subscribed to the - channel and channel message events) -
  • -
  • PubNub.ngHereNow({channel:aChannel}): calls PUBNUB.here_now with the specified - channel to produce root scope presence broadcast events (make sure the code is subscribed to the - channel and channel presence events) -
  • -
  • PubNub.ngWhereNow(): returns user/channel subscription data
  • -
  • PubNub.ngAuth(): updates the auth_key associated with the PubNub session
  • -
  • PubNub.ngAudit(): displays PAM (PubNub Access Manager) settings, see - http://www.pubnub.com/docs/javascript/api/reference.html#access -
  • -
  • PubNub.ngGrant(): grants acccess via PAM (PubNub Access Manager), see - http://www.pubnub.com/docs/javascript/api/reference.html#grant -
  • -
  • PubNub.ngRevoke(): revokes acccess via PAM (PubNub Access Manager), see - http://www.pubnub.com/docs/javascript/api/reference.html#grant -
  • -
  • PubNub.ngListPresence(channel): returns the list of subscribers for a channel
  • -
  • PubNub.ngPresenceData(channel): returns the map of uuid to extended state data for - a channel -
  • -
  • PubNub.ngListChannels(): returns the list of channels that the PubNub Angular API - is connected to -
  • -
  • PubNub.ngListPresence(channel): returns the list of subscribers for a channel
  • -
  • PubNub.ngState({channel:channel}): retrieves extended user state for a channel
  • -
  • PubNub.ngState({channel:channel,state:newState}): updates extended user state for a - channel -
  • -
  • PubNub.ngMsgEv(channel): returns the root scope broadcast event name for message - events for a given channel -
  • -
  • PubNub.ngPrsEv(channel): returns the root scope broadcast event name for presence - events for a given channel -
  • -
-

Using the PubNub JS API directly (advanced)

- -

- In unusual cases where you need to access the PubNub API directly, we make it - easy by exposing the PUBNUB methods via the PubNub.jsapi.*. So if - you really need to call PUBNUB.each(), you can do it by calling - PubNub.jsapi.each(). -

- -

For example:

-
    -
  • PubNub.jsapi.publish
  • -
  • PubNub.jsapi.subscribe
  • -
  • PubNub.jsapi.unsubscribe
  • -
  • PubNub.jsapi.here_now
  • -
  • PubNub.jsapi.history
  • -
-

- NOTE - These methods do not call the internal AngularJS bookkeeping methods - to make sure the channel lists and rootScope broadcast events - get propagated - make sure you know what you're doing! -

- -

- And... Stay tuned! We're adding support for more PubNub APIs all the - time. -

-
-
-
From 7fe1d2c72313a27b73a20cb04db07d8ff0dd03b4 Mon Sep 17 00:00:00 2001 From: Josh Marinacci Date: Tue, 16 Feb 2016 21:24:41 -0800 Subject: [PATCH 22/23] testing changes --- views/_happy.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/_happy.html b/views/_happy.html index 75d4ae0..a4338d1 100755 --- a/views/_happy.html +++ b/views/_happy.html @@ -26,7 +26,7 @@

There's a new AngularJS PubNub API in town, optimized to make - building real-time web applications as easy as possible. + building real-time web applications as eassy as possible.

From 975a7f405c087138abab9ec3357aa0026e74ec99 Mon Sep 17 00:00:00 2001 From: Josh Marinacci Date: Tue, 16 Feb 2016 21:25:34 -0800 Subject: [PATCH 23/23] remove testing --- views/_happy.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/_happy.html b/views/_happy.html index a4338d1..75d4ae0 100755 --- a/views/_happy.html +++ b/views/_happy.html @@ -26,7 +26,7 @@

There's a new AngularJS PubNub API in town, optimized to make - building real-time web applications as eassy as possible. + building real-time web applications as easy as possible.