From 7c4e74a91798e1de3677cf5c13bbc4f4b0fff354 Mon Sep 17 00:00:00 2001 From: Michael Benford Date: Sun, 16 Mar 2014 01:20:16 -0300 Subject: [PATCH] refactor(css): Convert CSS to SCSS Convert CSS files to SCSS in order to better structure the stylesheets and remove duplicate code. --- CONTRIBUTING.md | 24 +++++---- Gruntfile.js | 47 ++++++++++++----- css/autocomplete.css | 40 --------------- css/tags-input.css | 103 -------------------------------------- package.json | 1 + scss/auto-complete.scss | 46 +++++++++++++++++ scss/main.scss | 20 ++++++++ scss/mixins.scss | 10 ++++ scss/tags-input.scss | 72 ++++++++++++++++++++++++++ scss/variables.scss | 40 +++++++++++++++ templates/tags-input.html | 2 +- test/tags-input.spec.js | 12 +++-- test/test-page.html | 8 ++- 13 files changed, 254 insertions(+), 171 deletions(-) delete mode 100644 css/autocomplete.css delete mode 100644 css/tags-input.css create mode 100644 scss/auto-complete.scss create mode 100644 scss/main.scss create mode 100644 scss/mixins.scss create mode 100644 scss/tags-input.scss create mode 100644 scss/variables.scss diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d4548a68..a2093b19 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,23 +7,24 @@ So you want to contribute to ngTagsInput... that's awesome! I really appreciate Before writing your killing feature you need to have a few things set up: 1. Install Node.js (0.10.22 or higher) -2. Install `grunt-cli` and `karma` globally +2. Install `grunt-cli` and `karma-cli` globally - npm install -g grunt-cli karma + npm install -g grunt-cli karma-cli -3. Clone your repository +3. Install Ruby and the `sass` gem if you want to compile the SCSS files +4. Clone your repository git clone https://github.com//ngTagsInput -4. Go to the ngTagsInput directory +5. Go to the ngTagsInput directory cd ngTagsInput -5. Add the main ngTagsInput repo as an upstream remote +6. Add the main ngTagsInput repo as an upstream remote git remote add upstream https://github.com/mbenford/ngTagsInput -6. Install the development dependencies +7. Install the development dependencies npm install @@ -39,12 +40,15 @@ That performs all tasks needed to produce the final JavaScript and CSS files. Af ng-tags-input.js ng-tags-input.css - ng-tags-input.zip - ng-tags-input.min.zip + ng-tags-input.min.js + ng-tags-input.min.css -While coding you can execute `grunt test` to run the tests or `grunt watch` to run them automatically every time the source code files change. You can use `karma start` as well, of course. +In addition to `pack` there are other useful tasks you might want to use: -You can also generate the code coverage report by running `grunt coverage`. This may help you be sure nothing is left untested. +- `pack:js`: Generates only the Javascript files. +- `test`: Runs all tests using PhantomJS (you can use `karma start` as well, of course). +- `watch`: Runs all tests automatically every time the source code files change. +- `coverage`: Generates the code coverage report. This may help you be sure nothing is left untested. # Guidelines diff --git a/Gruntfile.js b/Gruntfile.js index 9d3ffd9d..0f9a4d65 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -26,7 +26,7 @@ module.exports = function(grunt) { outMin: 'build/<%= pkg.name %>.min.js' }, css: { - src: ['css/tags-input.css', 'css/autocomplete.css'], + src: 'scss/main.scss', out: 'build/<%= pkg.name %>.css', outMin: 'build/<%= pkg.name %>.min.css' }, @@ -129,11 +129,6 @@ module.exports = function(grunt) { files: { '<%= files.js.out %>': ['<%= files.js.src %>', '<%= files.html.out %>'] } - }, - css: { - files: { - '<%= files.css.out %>': ['<%= files.css.src %>'] - } } }, // Adds AngularJS dependency injection annotations @@ -144,6 +139,17 @@ module.exports = function(grunt) { } } }, + sass: { + build: { + options: { + style: 'expanded', + noCache: true + }, + files: { + '<%= files.css.out %>': ['<%= files.css.src %>'] + } + } + }, // Minifies the JS file uglify: { build: { @@ -280,20 +286,37 @@ module.exports = function(grunt) { grunt.registerTask('travis', ['test', 'coveralls']); grunt.registerTask('coverage', ['test', 'open:coverage']); - grunt.registerTask('pack', [ + grunt.registerTask('javascript-only', [ 'test', - 'clean', 'ngtemplates', 'concat', 'ngAnnotate', - 'uglify', - 'cssmin', - 'compress', - 'clean:tmp' + 'uglify' + ]); + + grunt.registerTask('css-only', [ + 'sass', + 'cssmin' ]); + grunt.registerTask('pack', function(output) { + var tasks = ['clean']; + + if (!output || output === 'js') { + tasks.push('javascript-only'); + } + if (!output || output === 'css') { + tasks.push('css-only'); + } + + tasks.push('clean:tmp'); + + grunt.task.run(tasks); + }); + grunt.registerTask('release', [ 'pack', + 'compress', 'changelog', 'replace:changelog', 'shell:git', diff --git a/css/autocomplete.css b/css/autocomplete.css deleted file mode 100644 index 484a8c3d..00000000 --- a/css/autocomplete.css +++ /dev/null @@ -1,40 +0,0 @@ -tags-input .autocomplete { - margin-top: 5px; - position: absolute; - padding: 8px 0; - background-color: #fff; - border: 1px solid rgba(0, 0, 0, 0.2); - -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2); - -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2); - box-shadow: 0 5px 10px rgba(0,0,0,.2); - width: 100%; - z-index: 999; -} - -tags-input .autocomplete .suggestion-list { - margin: 0; - padding: 0; - list-style-type: none; -} - -tags-input .autocomplete .suggestion-item { - padding: 3px 16px; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 16px; - line-height: 20px; - cursor: pointer; - text-align: left; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -tags-input .autocomplete .suggestion-item.selected { - color: #fff; - background-color: #0097cf -} - -tags-input .autocomplete .suggestion-item em { - font-weight: bold; - font-style: normal; -} \ No newline at end of file diff --git a/css/tags-input.css b/css/tags-input.css deleted file mode 100644 index 6f706ca2..00000000 --- a/css/tags-input.css +++ /dev/null @@ -1,103 +0,0 @@ -tags-input *, *:before, *:after { - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; -} - -tags-input .host { - position: relative; -} - -tags-input .host:active { - outline: none; -} - -tags-input .tags { - -moz-appearance: textfield; - -webkit-appearance: textfield; - background-color: white; - background-color: -moz-field; - border: 1px solid darkgray; - box-shadow: 1px 1px 1px 0 lightgray inset; - margin-top: 5px; - padding: 2px 2px; - overflow-y: auto; - overflow-x: hidden; - word-wrap: break-word; - font-size: 14px; - cursor: text; -} - -tags-input .tags.focused { - outline: none; - -webkit-box-shadow: 0px 0px 3px 1px rgba(5,139,242,0.6); - -moz-box-shadow: 0px 0px 3px 1px rgba(5,139,242,0.6); - box-shadow: 0px 0px 3px 1px rgba(5,139,242,0.6); -} - -tags-input .tags .tag-list { - margin: 0px; - padding: 0px; - overflow: visible; - list-style-type: none; -} - -tags-input .tags .tag-item { - margin: 2px; - padding-left: 4px; - display: inline-block; - border-radius: 3px; - height: 21px; - line-height: 1.3; - border: 1px solid rgb(172, 172, 172); - float: left; - background: rgb(240,249,255); /* Old browsers */ - background: -moz-linear-gradient(top, rgba(240,249,255,1) 0%, rgba(203,235,255,1) 47%, rgba(161,219,255,1) 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(240,249,255,1)), color-stop(47%,rgba(203,235,255,1)), color-stop(100%,rgba(161,219,255,1))); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, rgba(240,249,255,1) 0%,rgba(203,235,255,1) 47%,rgba(161,219,255,1) 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, rgba(240,249,255,1) 0%,rgba(203,235,255,1) 47%,rgba(161,219,255,1) 100%); /* Opera 11.10+ */ - background: -ms-linear-gradient(top, rgba(240,249,255,1) 0%,rgba(203,235,255,1) 47%,rgba(161,219,255,1) 100%); /* IE10+ */ - background: linear-gradient(to bottom, rgba(240,249,255,1) 0%,rgba(203,235,255,1) 47%,rgba(161,219,255,1) 100%); /* W3C */ -} - -tags-input .tags .tag-item.selected { - background: rgb(254,187,187); /* Old browsers */ - background: -moz-linear-gradient(top, rgba(254,187,187,1) 0%, rgba(254,144,144,1) 45%, rgba(255,92,92,1) 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(254,187,187,1)), color-stop(45%,rgba(254,144,144,1)), color-stop(100%,rgba(255,92,92,1))); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, rgba(254,187,187,1) 0%,rgba(254,144,144,1) 45%,rgba(255,92,92,1) 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, rgba(254,187,187,1) 0%,rgba(254,144,144,1) 45%,rgba(255,92,92,1) 100%); /* Opera 11.10+ */ - background: -ms-linear-gradient(top, rgba(254,187,187,1) 0%,rgba(254,144,144,1) 45%,rgba(255,92,92,1) 100%); /* IE10+ */ - background: linear-gradient(to bottom, rgba(254,187,187,1) 0%,rgba(254,144,144,1) 45%,rgba(255,92,92,1) 100%); /* W3C */ -} - -tags-input .tags .tag-item span { - font: 13px "Helvetica Neue", Helvetica, Arial, sans-serif; -} - -tags-input .tags .tag-item button { - margin: 0px; - border: none; - background: none; - color: #585858; - cursor: pointer; - font: bold 16px Arial, sans-serif; - vertical-align: middle; -} - -tags-input .tags .tag-item button:active { - color: #ff0000; -} - -tags-input .tags .input { - border: 0px; - outline: none; - margin: 2px; - padding: 0px 0px 0px 4px; - height: 21px; - float: left; - font: 13px "Helvetica Neue", Helvetica, Arial, sans-serif; -} - -tags-input .tags input::-ms-clear { - display: none; -} \ No newline at end of file diff --git a/package.json b/package.json index 8573e334..1096fb83 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "grunt-text-replace": "0.3.11", "grunt-shell": "0.6.4", "grunt-ngdocs": "0.2.1", + "grunt-contrib-sass": "0.7.3", "karma-coverage": "0.1.5", "karma-jasmine": "0.2.2", "karma-chrome-launcher": "0.1.2", diff --git a/scss/auto-complete.scss b/scss/auto-complete.scss new file mode 100644 index 00000000..e0f0c959 --- /dev/null +++ b/scss/auto-complete.scss @@ -0,0 +1,46 @@ +@import "mixins"; +@import "variables"; + +tags-input .autocomplete { + margin-top: 5px; + position: absolute; + padding: 5px 0; + z-index: $suggestion-box-z-index; + width: $suggestion-box-width; + background-color: $suggestion-box-color; + border: $suggestion-box-border; + @include box-shadow($suggestion-box-shadow); + + .suggestion-list { + margin: 0; + padding: 0; + list-style-type: none; + } + + .suggestion-item { + padding: 5px 10px; + cursor: pointer; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + font: $suggestion-font; + color: $suggestion-color; + background-color: $suggestion-bgcolor; + + &.selected { + color: $suggestion-color-selected; + background-color: $suggestion-bgcolor-selected; + + em { + color: $suggestion-highlight-color-selected; + background-color: $suggestion-highlight-bgcolor-selected; + } + } + + em { + font: $suggestion-highlight-font; + color: $suggestion-highlight-color; + background-color: $suggestion-highlight-bgcolor; + } + } +} \ No newline at end of file diff --git a/scss/main.scss b/scss/main.scss new file mode 100644 index 00000000..700f91e4 --- /dev/null +++ b/scss/main.scss @@ -0,0 +1,20 @@ +tags-input *, *:before, *:after { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +tags-input { + .host { + position: relative; + margin-top: 5px; + margin-bottom: 5px; + + &:active { + outline: none; + } + } +} + +@import "tags-input"; +@import "auto-complete"; \ No newline at end of file diff --git a/scss/mixins.scss b/scss/mixins.scss new file mode 100644 index 00000000..20473b8b --- /dev/null +++ b/scss/mixins.scss @@ -0,0 +1,10 @@ +@mixin gradient($steps...) { + background: -webkit-linear-gradient(top, $steps); + background: linear-gradient(to bottom, $steps); +} + +@mixin box-shadow($args...) { + -webkit-box-shadow: $args; + -moz-box-shadow: $args; + box-shadow: $args; +} \ No newline at end of file diff --git a/scss/tags-input.scss b/scss/tags-input.scss new file mode 100644 index 00000000..7cce859d --- /dev/null +++ b/scss/tags-input.scss @@ -0,0 +1,72 @@ +@import "mixins"; +@import "variables"; + +tags-input .tags { + -moz-appearance: textfield; + -webkit-appearance: textfield; + padding: 1px; + overflow: hidden; + word-wrap: break-word; + cursor: text; + background-color: $tags-bgcolor; + border: $tags-border; + box-shadow: $tags-border-shadow; + + &.focused { + outline: none; + @include box-shadow($tags-outline-box-shadow); + } + + .tag-list { + margin: 0; + padding: 0; + list-style-type: none; + } + + .tag-item { + margin: 2px; + padding: 0 5px; + display: inline-block; + float: left; + font: $tag-font; + height: $tag-height; + line-height: $tag-height - 1px; + border: $tag-border; + border-radius: $tag-border-radius; + @include gradient($tag-color); + + &.selected { + @include gradient($tag-color-selected); + } + + .remove-button { + margin: 0 0 0 5px; + padding: 0; + border: none; + background: none; + cursor: pointer; + vertical-align: middle; + font: $remove-button-font; + color: $remove-button-color; + + &:active { + color: $remove-button-color-active; + } + } + } + + .input { + border: 0; + outline: none; + margin: 2px; + padding: 0; + padding-left: 5px; + float: left; + height: $tag-height; + font: $input-font; + } + + .input::-ms-clear { + display: none; + } +} \ No newline at end of file diff --git a/scss/variables.scss b/scss/variables.scss new file mode 100644 index 00000000..721ba37a --- /dev/null +++ b/scss/variables.scss @@ -0,0 +1,40 @@ +// general +$base-font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + +// tagsInput +$tags-bgcolor: #fff; +$tags-border: 1px solid darkgray; +$tags-border-shadow: 1px 1px 1px 0 lightgray inset; +$tags-outline-box-shadow: 0 0 3px 1px rgba(5, 139, 242, 0.6); + +$tag-height: 26px; +$tag-font: 14px $base-font-family; +$tag-color: rgba(240, 249, 255, 1) 0%, rgba(203, 235, 255, 1) 47%, rgba(161, 219, 255, 1) 100%; +$tag-border: 1px solid rgb(172, 172, 172); +$tag-border-radius: 3px; +$tag-color-selected: rgba(254, 187, 187, 1) 0%, rgba(254, 144, 144, 1) 45%, rgba(255, 92, 92, 1) 100%; + +$remove-button-color: #585858; +$remove-button-color-active: #ff0000; +$remove-button-font: bold 16px Arial, sans-serif; + +$input-font: $tag-font; + +// autoComplete +$suggestion-box-z-index: 999; +$suggestion-box-width: 100%; +$suggestion-box-color: #fff; +$suggestion-box-border: 1px solid rgba(0, 0, 0, 0.2); +$suggestion-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + +$suggestion-font: 16px $base-font-family; +$suggestion-color: #000; +$suggestion-bgcolor: #fff; +$suggestion-color-selected: #fff; +$suggestion-bgcolor-selected: #0097cf; + +$suggestion-highlight-font: normal bold $suggestion-font; +$suggestion-highlight-color: $suggestion-color; +$suggestion-highlight-bgcolor: $suggestion-bgcolor; +$suggestion-highlight-color-selected: $suggestion-color-selected; +$suggestion-highlight-bgcolor-selected: $suggestion-bgcolor-selected; \ No newline at end of file diff --git a/templates/tags-input.html b/templates/tags-input.html index b41d8f5c..cc7509c7 100644 --- a/templates/tags-input.html +++ b/templates/tags-input.html @@ -3,7 +3,7 @@ - + +