From af274a7184c1a1c4ac3297aff7fc5ea0edd81e5f Mon Sep 17 00:00:00 2001 From: beNjiox Date: Thu, 9 Jan 2014 02:57:34 +0100 Subject: [PATCH 1/2] v0.2 - Welcome Grunt & AngularJS + Routing improved Better routing ( more generic ) dropped jQuery for AngularJS Grunt for frontend automation (still WIP) --- .gitignore | 6 + Gruntfile.js | 143 ++++++++++ app/controllers/ColorsController.php | 13 +- app/lib/Larabooster/DbColorRepository.php | 6 +- .../Larabooster/MemcacheColorRepository.php | 8 +- app/lib/Larabooster/RedisColorRepository.php | 4 +- app/routes.php | 79 ++---- app/start/global.php | 1 + app/views/home.blade.php | 45 +-- app/views/master.blade.php | 3 +- larabooster.todo | 16 +- package.json | 16 ++ public/css/app.css | 40 ++- public/css/app.scss | 30 ++ public/js/app.coffee | 58 ++++ public/js/app.js | 77 ++++++ public/js/home.js | 76 ----- public/js/jquery.maskedinput.js | 260 ++++++++++++++++++ public/partials/storage_panel.html | 57 ++++ 19 files changed, 733 insertions(+), 205 deletions(-) create mode 100644 Gruntfile.js create mode 100644 package.json create mode 100644 public/css/app.scss create mode 100644 public/js/app.coffee create mode 100644 public/js/app.js delete mode 100644 public/js/home.js create mode 100644 public/js/jquery.maskedinput.js create mode 100644 public/partials/storage_panel.html diff --git a/.gitignore b/.gitignore index ce06e22..9cf7a91 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,9 @@ composer.lock Thumbs.db .vagrant/ dump.rdb + +*.scssc + +*.cdncache + +node_modules \ No newline at end of file diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..bbcccde --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,143 @@ +var PROD_DEST = "../www/" +var PUBLIC_PATH = "./public/" +/*global module:false*/ +module.exports = function(grunt) { + + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + + /* TEMPLATING */ + + template: { + views: { + options: { + data: { + env: 'dev' + }, + }, + files: { + './public/index.html': PUBLIC_PATH + './index.tpl' + } + }, + prod: { + options: { + data: { + env: 'prod' + } + }, + files: { + './public/index.html': PUBLIC_PATH + './index.tpl' + } + }, + dev: { + options: { + data: { + env: 'dev' + } + }, + files: { + './public/index.html': PUBLIC_PATH + './index.tpl' + } + }, + }, + + /* COMPILE OUR COFFEE SCRIPTS FILES */ + + coffee: { + dist: { + options: { + bare: true + }, + files: [{ + expand: true, + cwd: PUBLIC_PATH + 'js', + src: ['{,*/}*.coffee'], + dest: PUBLIC_PATH + 'js', + ext: '.js' + }] + } + }, + + /* CONCAT AND MINIFY OUR JS FILES */ + + uglify: { + options: { + banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + + '<%= grunt.template.today("yyyy-mm-dd") %> */', + mangle:false + }, + my_target: { + files: { + 'app.js': [ + PUBLIC_PATH + "js/storage.coffee" + ] + } + } + }, + + /* COMPILE OUR SCSS FILES */ + + sass: { + options: { + banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + + '<%= grunt.template.today("yyyy-mm-dd") %> */' + }, + dist: { + files: [{ + expand: true, + src: ['public/css/*.scss'], + ext: '.css' + }] + } + }, + + /* COMPRESS CSS RULE */ + + cssmin: { + minify: { + files: { + 'css/app.css': ['css/app.css'] + } + } + }, + + /* OUR WATCH RULES */ + + watch: { + html: { + files: ['app/**/*.blade.php', 'public/partials/*.html'], + options: { + livereload: true + } + }, + coffee: { + files: ['public/js/*.coffee'], + tasks: ['coffee'], + options: { + livereload: true + } + }, + scss: { + files: ['public/css/*.scss'], + tasks: ['sass'], + options: { + livereload: true + } + }, + } + +}); + +grunt.loadNpmTasks('grunt-contrib-watch'); +grunt.loadNpmTasks('grunt-contrib-coffee'); +grunt.loadNpmTasks('grunt-contrib-uglify'); +grunt.loadNpmTasks('grunt-contrib-watch'); +grunt.loadNpmTasks('grunt-contrib-sass'); +grunt.loadNpmTasks('grunt-template'); +grunt.loadNpmTasks('grunt-contrib-clean'); +grunt.loadNpmTasks('grunt-contrib-cssmin'); + + +grunt.registerTask('dev', ['watch']); +grunt.registerTask('prod', ['clean:prod' , 'sass', 'cssmin', 'coffee', 'uglify', 'template:prod', 'htmlmin' ]); +}; \ No newline at end of file diff --git a/app/controllers/ColorsController.php b/app/controllers/ColorsController.php index 47be847..f05497f 100644 --- a/app/controllers/ColorsController.php +++ b/app/controllers/ColorsController.php @@ -1,9 +1,14 @@ color->exists($code)) { $errors['msg'] = "color '{$code}' already exists in this storage!"; - return Response::json($errors, 400); + return Response::json($errors, 400); } $this->color->add($code); @@ -51,13 +56,13 @@ public function delete() $this->color->delete(Input::get('code')); return Response::json(null, 204); } - + $errors = [ 'errors' => 'VALIDATION_FAIL', 'msg' => 'You should pass a code to be able to delete a color.' ]; - return Response::json(400, $errors); + return Response::json($errors, 400); } } \ No newline at end of file diff --git a/app/lib/Larabooster/DbColorRepository.php b/app/lib/Larabooster/DbColorRepository.php index e40e37f..c41a223 100644 --- a/app/lib/Larabooster/DbColorRepository.php +++ b/app/lib/Larabooster/DbColorRepository.php @@ -2,7 +2,7 @@ use Larabooster\ColorRepositoryInterface; -class DbColorRepository implements ColorRepositoryInterface +class DbColorRepository implements ColorRepositoryInterface { public $whoami = "MySQL"; @@ -26,11 +26,11 @@ public function add($code) public function getAll($limit = 10) { - $colors_raw = \Color::orderBy('id', 'desc')->get()->toArray(); + $colors_raw = \Color::orderBy('id', 'desc')->take($limit)->get()->toArray(); $colors = []; foreach ($colors_raw as $color) { $colors[] = $color['code']; } return $colors; } -} +} diff --git a/app/lib/Larabooster/MemcacheColorRepository.php b/app/lib/Larabooster/MemcacheColorRepository.php index e63e045..d99c105 100644 --- a/app/lib/Larabooster/MemcacheColorRepository.php +++ b/app/lib/Larabooster/MemcacheColorRepository.php @@ -32,7 +32,7 @@ public function add($code) } public function delete($code) - { + { if (!(\Cache::has('colors'))) return false; $colors = \Cache::get('colors'); @@ -52,7 +52,7 @@ public function getAll($limit = 10) { $colors = \Cache::get('colors'); } - \Log::info(print_r($colors, true)); - return array_reverse($colors); + $colors = array_reverse($colors); + return array_splice($colors, 0, $limit); } -} \ No newline at end of file +} \ No newline at end of file diff --git a/app/lib/Larabooster/RedisColorRepository.php b/app/lib/Larabooster/RedisColorRepository.php index 59661bd..c2f8846 100644 --- a/app/lib/Larabooster/RedisColorRepository.php +++ b/app/lib/Larabooster/RedisColorRepository.php @@ -27,8 +27,8 @@ public function delete($code) public function getAll($limit = 10) { - $redis_colors = \Redis::smembers('colors'); - return $redis_colors; + $redis_colors = array_reverse(\Redis::smembers('colors')); + return array_splice($redis_colors, 0, $limit); } } \ No newline at end of file diff --git a/app/routes.php b/app/routes.php index 581d371..e8c6f00 100644 --- a/app/routes.php +++ b/app/routes.php @@ -1,62 +1,35 @@ getAll(); - $memcache_colors = $memcache_storage->getAll(); - $redis_colors = $redis_storage->getAll(); - - $to_view = [ - 'mysql_colors' => $mysql_colors, - 'memcache_colors' => $memcache_colors, - 'redis_colors' => $redis_colors - ]; - - return View::make('home')->with($to_view); +{ + return View::make('home'); }); Route::group(array('prefix' => 'api'), function() { - Route::post('mysql', function() { - $controller = new ColorsController(new DbColorRepository); - return $controller->store(); - }); - - Route::delete('mysql', function() { - $controller = new ColorsController(new DbColorRepository); - return $controller->delete(); - }); - - Route::post('memcache', function() { - $controller = new ColorsController(new MemcacheColorRepository); - return $controller->store(); - }); - - Route::delete('memcache', function() { - $controller = new ColorsController(new MemcacheColorRepository); - return $controller->delete(); - }); - - Route::post('redis', function() { - $controller = new ColorsController(new RedisColorRepository); - return $controller->store(); - }); - Route::delete('redis', function() { - $controller = new ColorsController(new RedisColorRepository); - return $controller->delete(); - }); + $storages = [ + 'mysql' => [ 'repo' => 'Larabooster\DbColorRepository' ], + 'memcache' => [ 'repo' => 'Larabooster\MemcacheColorRepository' ], + 'redis' => [ 'repo' => 'Larabooster\RedisColorRepository' ] + ]; + + foreach ($storages as $kStorage => $vStorage) + { + Route::group(array('prefix' => $kStorage), function() use ($kStorage, $vStorage) { + + $controller = new ColorsController(new $vStorage['repo']); + + Route::get("/", function() use ($controller) { + return $controller->getAll(3); + }); + Route::post("/", function() use ($controller) { + return $controller->store(); + }); + Route::delete("/", function() use ($controller) { + return $controller->delete(); + }); + + }); + } }); \ No newline at end of file diff --git a/app/start/global.php b/app/start/global.php index 82ab9ba..4e5a37c 100644 --- a/app/start/global.php +++ b/app/start/global.php @@ -79,3 +79,4 @@ */ require app_path().'/filters.php'; + diff --git a/app/views/home.blade.php b/app/views/home.blade.php index 7825c48..3acb08e 100644 --- a/app/views/home.blade.php +++ b/app/views/home.blade.php @@ -2,25 +2,19 @@ @section('javascript') - + + + @stop @section('content') -
+
-
- - {{ View::make('partials.storage_panel', ['colors' => $mysql_colors, - 'storage_name_lg' =>'MySQL Storage', - 'storage_name_sm' => 'MySQL' ]) }} - {{ View::make('partials.storage_panel', ['colors' => $memcache_colors, - 'storage_name_lg' =>'Memcache Storage', - 'storage_name_sm' => 'Memcache' ]) }} - {{ View::make('partials.storage_panel', ['colors' => $redis_colors, - 'storage_name_lg' =>'Redis Storage', - 'storage_name_sm' => 'Redis' ]) }} - +
+ + +
@@ -35,28 +29,15 @@
  • Add , Deletions capabilities
  • Vagrant install stable
  • +
  • v0.2

  • +
      +
    • UI using angularJS
    • +
    • Better routing
    • +
  • -
    -
    -

    About

    -
    - - {{ View::make('partials.techno_panel', [ 'title' => "Backend Stack", - 'list' => ["Vagrant using Precise32Box (Linux)", - "Laravel & PHP 5.5", - "Redis", - "Memcache", - "MySQL"] ])}} - - {{ View::make('partials.techno_panel', [ 'title' => "Frontend Stack", - 'list' => ["Bootstrap 3 + Bootswatch flatly", - "AngularJS & Restangular" ] ]) }} -
    - -
    @stop \ No newline at end of file diff --git a/app/views/master.blade.php b/app/views/master.blade.php index 95357c8..8c641ad 100644 --- a/app/views/master.blade.php +++ b/app/views/master.blade.php @@ -4,6 +4,7 @@ Larabooster + @@ -14,7 +15,7 @@ - @yield("javascript") + @yield("javascript") diff --git a/larabooster.todo b/larabooster.todo index d2ee5d1..4f3fe81 100644 --- a/larabooster.todo +++ b/larabooster.todo @@ -13,19 +13,19 @@ Larabooster: ✔ interactions on UI for delete @done (14-01-05) ✔ Error when deleting a just added element @done (14-01-05) V0.2 - UI revamp : - ☐ UI Using angularJS - ☐ Add - ☐ Delete - ☐ Toggling alerts - ☐ About page - ☐ Validations - ☐ UI limitations of X items - ☐ MaskInput for hexadecimal + ✔ UI Using angularJS @done (14-01-09) + ✔ Add @done (14-01-09) + ✔ Delete @done (14-01-09) + ✔ Toggling alerts @done (14-01-09) + ✔ Validations @done (14-01-09) + ✔ UI limitations of X items @done (14-01-09) + ✔ MaskInput for hexadecimal @done (14-01-09) V0.3 - Backend improvment: ☐ Http Middleware limit ☐ Exception on Errors ☐ Pagination handling V0.4 - Open source relase + hosting: + ☐ About page ☐ Hosting on DigitalOcean ☐ Google Analytics ☐ Explanation / about page diff --git a/package.json b/package.json new file mode 100644 index 0000000..d9ee283 --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "name": "Larabooster", + "version": "0.2.0", + "private": true, + "devDependencies": { + "grunt": "~0.4.2", + "grunt-contrib-jshint": "~0.7.2", + "grunt-contrib-watch": "~0.5.3", + "grunt-contrib-coffee": "~0.7.0", + "grunt-contrib-uglify": "~0.2.7", + "grunt-contrib-sass": "~0.5.1", + "grunt-template": "~0.2.1", + "grunt-contrib-clean": "~0.5.0", + "grunt-contrib-cssmin": "~0.7.0" + } +} diff --git a/public/css/app.css b/public/css/app.css index 92a7ced..ca9c535 100644 --- a/public/css/app.css +++ b/public/css/app.css @@ -1,30 +1,26 @@ +/*! Larabooster - v0.2.0 - 2014-01-08 */ .color_box { - display:inline-block; - height:25px; - width:25px; - padding:10px; -} + display: inline-block; + height: 25px; + width: 25px; + padding: 10px; } .color_code { - font-family:"Lato"; - display:inline-block; - width:50%; -} + font-family: "Lato"; + display: inline-block; + width: 50%; } .remove_color { - color:red; - padding-left:10px; -} + color: red; + padding-left: 10px; } -.modal-dialog{ - position: absolute; - left: 50%; - margin-left: -312px; - height: 500px; - top: 50%; - margin-top: -250px; -} +.modal-dialog { + position: absolute; + left: 50%; + margin-left: -312px; + height: 500px; + top: 50%; + margin-top: -250px; } .no_display { - display: none; -} \ No newline at end of file + display: none; } diff --git a/public/css/app.scss b/public/css/app.scss new file mode 100644 index 0000000..b0d543c --- /dev/null +++ b/public/css/app.scss @@ -0,0 +1,30 @@ +.color_box { + display:inline-block; + height:25px; + width:25px; + padding:10px; +} + +.color_code { + font-family:"Lato"; + display:inline-block; + width:50%; +} + +.remove_color { + color:red; + padding-left:10px; +} + +.modal-dialog{ + position: absolute; + left: 50%; + margin-left: -312px; + height: 500px; + top: 50%; + margin-top: -250px; +} + +.no_display { + display: none; +} \ No newline at end of file diff --git a/public/js/app.coffee b/public/js/app.coffee new file mode 100644 index 0000000..178da4a --- /dev/null +++ b/public/js/app.coffee @@ -0,0 +1,58 @@ +app = angular.module('app', []).config ($interpolateProvider) -> + $interpolateProvider.startSymbol('[[').endSymbol(']]') + +# Filters + +app.filter 'upper', () -> + return (data) -> + data.toUpperCase() + +# Directives + +app.directive 'storagePanel', ['$http', '$timeout', ($http, $timeout) -> + return { + restrict: 'E' + templateUrl: "partials/storage_panel.html" + scope: + 'storage': '@ngName' + link: (scope, element, attrs) -> + # fixme ; doesn't work without time + $timeout -> + jQuery("##{scope.storage} input[type=text]").mask("#hhhhhh"); + , 100 + + scope.loading = true + scope.list = [] + scope.name = scope.storage + $http.get("/api/#{scope.storage}").success (data) -> + scope.list = data + scope.loading = false + scope.addColor = (color) -> + q = $http.post("/api/#{scope.storage}", {code: color}) + q.success (data) -> + console.log "Color #{color} added successfuly" + scope.list.unshift color + $("input[type=text]").val("") + q.error (resp) -> + alert "An error occured [#{resp.msg}]" + scope.removeColor = (color) -> + if confirm "You are attempting to delete #{color} from #{scope.name}. Confirm?" + q = $http + method: "delete" + url: "/api/#{scope.storage}" + params: {code: color} + q.success (data) -> + console.log "Color #{color} removed successfuly" + id = "#{scope.storage}_#{color}"; + $(id).fadeOut() + scope.list = _.without(scope.list, _.findWhere(scope.list, color)) + q.error (resp) -> + alert "An error occured [#{resp.msg}]" + } +] + +# Controller + +app.controller 'StorageCtrl', [ '$scope', '$http', ($http, $scope) -> + console.log "Welcome on larabooster" +] \ No newline at end of file diff --git a/public/js/app.js b/public/js/app.js new file mode 100644 index 0000000..198517a --- /dev/null +++ b/public/js/app.js @@ -0,0 +1,77 @@ +var app; + +app = angular.module('app', []).config(function($interpolateProvider) { + return $interpolateProvider.startSymbol('[[').endSymbol(']]'); +}); + +app.filter('upper', function() { + return function(data) { + return data.toUpperCase(); + }; +}); + +app.directive('storagePanel', [ + '$http', '$timeout', function($http, $timeout) { + return { + restrict: 'E', + templateUrl: "partials/storage_panel.html", + scope: { + 'storage': '@ngName' + }, + link: function(scope, element, attrs) { + $timeout(function() { + return jQuery("#" + scope.storage + " input[type=text]").mask("#hhhhhh"); + }, 100); + scope.loading = true; + scope.list = []; + scope.name = scope.storage; + return $http.get("/api/" + scope.storage).success(function(data) { + scope.list = data; + scope.loading = false; + scope.addColor = function(color) { + var q; + q = $http.post("/api/" + scope.storage, { + code: color + }); + q.success(function(data) { + console.log("Color " + color + " added successfuly"); + scope.list.unshift(color); + return $("input[type=text]").val(""); + }); + return q.error(function(resp) { + return alert("An error occured [" + resp.msg + "]"); + }); + }; + return scope.removeColor = function(color) { + var q; + if (confirm("You are attempting to delete " + color + " from " + scope.name + ". Confirm?")) { + q = $http({ + method: "delete", + url: "/api/" + scope.storage, + params: { + code: color + } + }); + q.success(function(data) { + var id; + console.log("Color " + color + " removed successfuly"); + id = "" + scope.storage + "_" + color; + $(id).fadeOut(); + return scope.list = _.without(scope.list, _.findWhere(scope.list, color)); + }); + return q.error(function(resp) { + return alert("An error occured [" + resp.msg + "]"); + }); + } + }; + }); + } + }; + } +]); + +app.controller('StorageCtrl', [ + '$scope', '$http', function($http, $scope) { + return console.log("Welcome on larabooster"); + } +]); diff --git a/public/js/home.js b/public/js/home.js deleted file mode 100644 index d6cf6a2..0000000 --- a/public/js/home.js +++ /dev/null @@ -1,76 +0,0 @@ - -$(document).ready(function($) { - - /* --- add --- */ - - $(".add_color").on('click', function(){ - var context = $(this).attr('data-context'); - var color = $('.add_color_input_'+context).val(); - - if (color.length == 0) - { - alert("Please fill the input!") - return ; - } - - $.ajax({ - url: '/api/' + context, - type: 'POST', - data: { - code: color - }, - }) - .done(function() { - $new_color_el = $($("#color_item_tmpl").html().replace(/_CODE_/g, color)); - console.log ("["+context+"][POST ADD - Before insert] : How many items? " + $(".list_"+context+" div.color_code").length); - if ($(".list_"+context+" div.color_code").length == 0) - { - $(".alert_" + context).hide(); - - } - $(".list_"+context).prepend($new_color_el).show(); - $('.add_color_input_'+context).val(""); - console.log ("["+context+"][POST ADD - After insert] : How many items? " + $(".list_"+context+" div.color_code").length); - }) - .fail(function(resp) { - alert("An error happened: [_ERROR_]".replace('_ERROR_', resp.responseJSON.msg)); - }) - }); - - /* --- delete --- */ - - $("body").on('click', '.delete_color', function(){ - - var color = $(this).data('color'); - var context = $(this).data('context'); - console.log ("attempting to remove " + color + " from " + context); - $el_to_hidden = $(this).parent(); - - if (confirm("You are attempting to delete the color _COLOR_. Confirm?".replace('_COLOR_', color))) - { - console.log(".list_"+context+" div.color_code"); - console.log ("["+context+"][POST DELETE - Before remove] : How many items? " + $(".list_"+context+" div.color_code").length); - $.ajax({ - url: '/api/' + context, - type: 'DELETE', - data: { - code: color - } - }) - .done(function(){ - $el_to_hidden.hide().remove(); - console.log(".list_"+context+" div.color_code"); - console.log($(".list_"+context+" div.color_code").length); - - if ($(".list_"+context+" div.color_code").length == 0) - { - console.log ("Display alert_"+context); - $(".alert_" + context).fadeToggle(); - } - console.log ("["+context+"][POST DELETE - After remove] : How many items? " + $(".list_"+context+" div.color_code").length); - }); - } - - }); - -}); \ No newline at end of file diff --git a/public/js/jquery.maskedinput.js b/public/js/jquery.maskedinput.js new file mode 100644 index 0000000..3c0becc --- /dev/null +++ b/public/js/jquery.maskedinput.js @@ -0,0 +1,260 @@ +/* + Masked Input plugin for jQuery + Copyright (c) 2007-@Year Josh Bush (digitalbush.com) + Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license) + Version: @version +*/ +(function($) { + $.browser = {msie:false} + var pasteEventName = ($.browser.msie ? 'paste' : 'input') + ".mask"; + var iPhone = (window.orientation != undefined); + + $.mask = { + //Predefined character definitions + definitions: { + '9': "[0-9]", + 'a': "[A-Za-z]", + '*': "[A-Za-z0-9]", + 'h': "[A-Fa-f0-9]" + }, + dataName:"rawMaskFn" + }; + + $.fn.extend({ + //Helper Function for Caret positioning + caret: function(begin, end) { + if (this.length == 0) return; + if (typeof begin == 'number') { + end = (typeof end == 'number') ? end : begin; + return this.each(function() { + if (this.setSelectionRange) { + this.setSelectionRange(begin, end); + } else if (this.createTextRange) { + var range = this.createTextRange(); + range.collapse(true); + range.moveEnd('character', end); + range.moveStart('character', begin); + range.select(); + } + }); + } else { + if (this[0].setSelectionRange) { + begin = this[0].selectionStart; + end = this[0].selectionEnd; + } else if (document.selection && document.selection.createRange) { + var range = document.selection.createRange(); + begin = 0 - range.duplicate().moveStart('character', -100000); + end = begin + range.text.length; + } + return { begin: begin, end: end }; + } + }, + unmask: function() { return this.trigger("unmask"); }, + mask: function(mask, settings) { + if (!mask && this.length > 0) { + var input = $(this[0]); + return input.data($.mask.dataName)(); + } + settings = $.extend({ + placeholder: "_", + completed: null + }, settings); + + var defs = $.mask.definitions; + var tests = []; + var partialPosition = mask.length; + var firstNonMaskPos = null; + var len = mask.length; + + $.each(mask.split(""), function(i, c) { + if (c == '?') { + len--; + partialPosition = i; + } else if (defs[c]) { + tests.push(new RegExp(defs[c])); + if(firstNonMaskPos==null) + firstNonMaskPos = tests.length - 1; + } else { + tests.push(null); + } + }); + + return this.trigger("unmask").each(function() { + var input = $(this); + var buffer = $.map(mask.split(""), function(c, i) { if (c != '?') return defs[c] ? settings.placeholder : c }); + var focusText = input.val(); + + function seekNext(pos) { + while (++pos <= len && !tests[pos]); + return pos; + }; + function seekPrev(pos) { + while (--pos >= 0 && !tests[pos]); + return pos; + }; + + function shiftL(begin,end) { + if(begin<0) + return; + for (var i = begin,j = seekNext(end); i < len; i++) { + if (tests[i]) { + if (j < len && tests[i].test(buffer[j])) { + buffer[i] = buffer[j]; + buffer[j] = settings.placeholder; + } else + break; + j = seekNext(j); + } + } + writeBuffer(); + input.caret(Math.max(firstNonMaskPos, begin)); + }; + + function shiftR(pos) { + for (var i = pos, c = settings.placeholder; i < len; i++) { + if (tests[i]) { + var j = seekNext(i); + var t = buffer[i]; + buffer[i] = c; + if (j < len && tests[j].test(t)) + c = t; + else + break; + } + } + }; + + function keydownEvent(e) { + var k=e.which; + + //backspace, delete, and escape get special treatment + if(k == 8 || k == 46 || (iPhone && k == 127)){ + var pos = input.caret(), + begin = pos.begin, + end = pos.end; + + if(end-begin==0){ + begin=k!=46?seekPrev(begin):(end=seekNext(begin-1)); + end=k==46?seekNext(end):end; + } + clearBuffer(begin, end); + shiftL(begin,end-1); + + return false; + } else if (k == 27) {//escape + input.val(focusText); + input.caret(0, checkVal()); + return false; + } + }; + + function keypressEvent(e) { + var k = e.which, + pos = input.caret(); + if (e.ctrlKey || e.altKey || e.metaKey || k<32) {//Ignore + return true; + } else if (k) { + if(pos.end-pos.begin!=0){ + clearBuffer(pos.begin, pos.end); + shiftL(pos.begin, pos.end-1); + } + + var p = seekNext(pos.begin - 1); + if (p < len) { + var c = String.fromCharCode(k); + if (tests[p].test(c)) { + shiftR(p); + buffer[p] = c; + writeBuffer(); + var next = seekNext(p); + input.caret(next); + if (settings.completed && next >= len) + settings.completed.call(input); + } + } + return false; + } + }; + + function clearBuffer(start, end) { + for (var i = start; i < end && i < len; i++) { + if (tests[i]) + buffer[i] = settings.placeholder; + } + }; + + function writeBuffer() { return input.val(buffer.join('')).val(); }; + + function checkVal(allow) { + //try to place characters where they belong + var test = input.val(); + var lastMatch = -1; + for (var i = 0, pos = 0; i < len; i++) { + if (tests[i]) { + buffer[i] = settings.placeholder; + while (pos++ < test.length) { + var c = test.charAt(pos - 1); + if (tests[i].test(c)) { + buffer[i] = c; + lastMatch = i; + break; + } + } + if (pos > test.length) + break; + } else if (buffer[i] == test.charAt(pos) && i!=partialPosition) { + pos++; + lastMatch = i; + } + } + if (!allow && lastMatch + 1 < partialPosition) { + input.val(""); + clearBuffer(0, len); + } else if (allow || lastMatch + 1 >= partialPosition) { + writeBuffer(); + if (!allow) input.val(input.val().substring(0, lastMatch + 1)); + } + return (partialPosition ? i : firstNonMaskPos); + }; + + input.data($.mask.dataName,function(){ + return $.map(buffer, function(c, i) { + return tests[i]&&c!=settings.placeholder ? c : null; + }).join(''); + }) + + if (!input.attr("readonly")) + input + .one("unmask", function() { + input + .unbind(".mask") + .removeData($.mask.dataName); + }) + .bind("focus.mask", function() { + focusText = input.val(); + var pos = checkVal(); + writeBuffer(); + var moveCaret=function(){ + if (pos == mask.length) + input.caret(0, pos); + else + input.caret(pos); + }; + ($.browser.msie ? moveCaret:function(){setTimeout(moveCaret,0)})(); + }) + .bind("blur.mask", function() { + checkVal(); + if (input.val() != focusText) + input.change(); + }) + .bind("keydown.mask", keydownEvent) + .bind("keypress.mask", keypressEvent) + .bind(pasteEventName, function() { + setTimeout(function() { input.caret(checkVal(true)); }, 0); + }); + + checkVal(); //Perform initial check for existing values + }); + } + }); +})(jQuery); \ No newline at end of file diff --git a/public/partials/storage_panel.html b/public/partials/storage_panel.html new file mode 100644 index 0000000..dafc811 --- /dev/null +++ b/public/partials/storage_panel.html @@ -0,0 +1,57 @@ + + +
    +
    +
    +

    + [[ name ]] +

    +
    +
    +
    +

    +
    + Loading... +
    +
    + + + + Oops Nothing in the [[ name ]] storage. + +
    +
    +
    +
    + [[ c | upper ]] +
    +
    +
    + + + +
    +
    +
    + +
    + Add color to [[ name ]] +
    + +
    +
    + + + + +
    +
    + + +
    +
    +
    \ No newline at end of file From 0954296400b2c82a9bdaa80f9d1d6fdccc52816f Mon Sep 17 00:00:00 2001 From: beNjiox Date: Thu, 9 Jan 2014 03:00:21 +0100 Subject: [PATCH 2/2] Readme Updated --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 139fdf9..a2df7fd 100644 --- a/README.md +++ b/README.md @@ -56,11 +56,12 @@ Roadmap [x] Basic UI (jQuery based) [x] Boilerplate provisioning file # V0.2 - UI revamp : - [] UI Using angularJS - [] Better error handling (client side) - [] UI limitations of X items - [] Masked Input for hexadecimal + [x] UI Using angularJS + [x] Improved UI details + [x] Improved routing + [x] Grunt introduced # V0.3 - Backend improvment: + [x] getAll now account for limits [] Http Middleware limit [] Exception on Errors [] Pagination handling