From 2591a5a12e89e8e131dd567cc8ef3f80f1c2f382 Mon Sep 17 00:00:00 2001 From: lordfriend Date: Sun, 9 Feb 2014 21:42:29 +0000 Subject: [PATCH] first commit --- .editorconfig | 21 ++++++++++ .gitignore | 3 ++ .jshintrc | 25 ++++++++++++ Gruntfile.js | 75 +++++++++++++++++++++++++++++++++++ LICENSE | 21 ++++++++++ README.md | 6 +++ bower.json | 14 +++++++ examples/app.js | 39 ++++++++++++++++++ examples/index.html | 79 +++++++++++++++++++++++++++++++++++++ examples/main.css | 33 ++++++++++++++++ package.json | 16 ++++++++ src/nya-bootstrap-select.js | 73 ++++++++++++++++++++++++++++++++++ 12 files changed, 405 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 .jshintrc create mode 100644 Gruntfile.js create mode 100644 LICENSE create mode 100644 README.md create mode 100644 bower.json create mode 100644 examples/app.js create mode 100644 examples/index.html create mode 100644 examples/main.css create mode 100644 package.json create mode 100644 src/nya-bootstrap-select.js diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c2cdfb8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,21 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + + +[*] + +# Change these settings to your own preference +indent_style = space +indent_size = 2 + +# We recommend you to keep these unchanged +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..78dbd62 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules +bower_components +.idea \ No newline at end of file diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..cd7357a --- /dev/null +++ b/.jshintrc @@ -0,0 +1,25 @@ +{ + "node": true, + "browser": true, + "esnext": true, + "bitwise": true, + "camelcase": true, + "curly": true, + "eqeqeq": true, + "immed": true, + "indent": 2, + "latedef": true, + "newcap": true, + "noarg": true, + "quotmark": "single", + "regexp": true, + "undef": true, + "unused": true, + "strict": true, + "trailing": true, + "smarttabs": true, + "jquery": true, + "globals": { + "angular": false + } +} diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..00f95a4 --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,75 @@ +'use strict'; + +module.exports = function(grunt) { + + // Load all grunt tasks automatically + require('load-grunt-tasks')(grunt); + + // Time how long grunt task take. Can help when optimizing build times + require('time-grunt')(grunt); + + //Configure grunt + grunt.initConfig({ + + // The actual grunt server settings + connect: { + options: { + port: 9000, + // Change this to '0.0.0.0' to access the server from outside. + hostname: 'localhost', + livereload: 35729 + }, + livereload: { + options: { + open: true, + base: [ + '.', + 'examples' + ] + } + } + }, + + //Watch files for changes, and run tasks base on the changed files. + watch: { + js: { + files: ['src/*.js'], + tasks: ['newer:jshint:all'], + options: { + livereload: true + } + }, + livereload: { + options: { + livereload: '<%= connect.options.livereload %>' + }, + files: [ + 'examples/*.html', + 'examples/{,*/*.js}', + 'examples{,*/}*.css', + 'examples/{,*/}*.{png,jpg,jpeg,gif,webp,svg}' + ] + } + }, + + // Make sure code styles are up to par and there are no obvious mistakes + jshint: { + options: { + jshintrc: '.jshintrc', + reporter: require('jshint-stylish') + }, + all: [ + 'Gruntfile.js', + 'src/*.js', + 'examples/{,*/}*.js' + ] + + } + }); + + // Creates the 'serve' task + grunt.registerTask('serve', [ + 'connect:livereload', + 'watch' + ]); +}; diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fbac739 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2014 Nyasoft + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..fa3a188 --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# nya-bootstrap-select # +--- + +An AngularJS directive wrapper for silviomoreto's Bootstrap-select, which supports `ngRepeat` in options to dynamically build a Bootstrap-select + +This project is not ready for publish yet. Test case is not written. So take your own risk. \ No newline at end of file diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..0d7bf60 --- /dev/null +++ b/bower.json @@ -0,0 +1,14 @@ +{ + "name": "nya-bootstrap-select", + "version": "1.0.0", + "dependencies": { + "angular": "*", + "bootstrap-select": "*", + "jquery": ">=1.7" + }, + "devDependencies": { + "bootstrap-css":"~3.0", + "angular-mocks": "*", + "angular-scenario": "*" + } +} diff --git a/examples/app.js b/examples/app.js new file mode 100644 index 0000000..db71944 --- /dev/null +++ b/examples/app.js @@ -0,0 +1,39 @@ +'use strict'; + +angular.module('demoApp',['nyaBootstrapSelect']) + .controller('MainCtrl', function($scope){ + + var options = ['Alpha', 'Bravo', 'Charlie', 'Delta', + 'Echo', 'Foxtrot', 'Golf', 'Hotel', 'Juliet', 'Kilo', 'Lima', + 'Mike', 'November', 'Oscar', 'Papa', 'Quebec', 'Romeo', 'Sierra', + 'Tango', 'Uniform', 'Victor', 'Whiskey', 'X-ray', 'Yankee', 'Zulu' + ]; + + $scope.options1 = [ + 'Alpha', + 'Bravo', + 'Charlie' + ]; + + $scope.myModel = ['Bravo']; + + $scope.changeOptions = function(targetOption) { + var length = Math.max(Math.min(Math.floor(Math.random() * options.length), 10), 3); + var newOptions = {}; + for(var i = 0; i < length; i++) { + newOptions[options[Math.floor(Math.random() * options.length)]] = true; + } + $scope[targetOption] = Object.keys(newOptions); + }; + + $scope.options2 = options.splice(0, 6); + + $scope.changeModel = function(model) { + var length = Math.floor(Math.random() * $scope.options2.length); + var newModel = {}; + for(var i = 0; i < length; i++) { + newModel[$scope.options2[Math.floor(Math.random() * $scope.options2.length)]] = true; + } + $scope[model] = Object.keys(newModel); + }; + }); \ No newline at end of file diff --git a/examples/index.html b/examples/index.html new file mode 100644 index 0000000..de5ee0d --- /dev/null +++ b/examples/index.html @@ -0,0 +1,79 @@ + + + + + nya-bootstrap-select demo + + + + + + + +
+
+

nya-bootstrap-select

+

An angular wrapper for Bootstrap-select with dynamic loading options support

+ View on Github +
+
+
+
+

Overview

+

This is an angular directive wrapping for popular custom select Bootstrap-select. + Unlike other directives. This directive support ng-repeat in option. +

+

All of the Bootstrap-select's function is supported. + The select result is bound to a model, so you don't need to use + Bootstrap-select's api to get value. + just write your select in the angular way +

+

ngOptions directive is not supported yet.

+
+
+

Example

+

Dynamic modify options

+

The select has three options initially. Click the Change Options button to change the options randomly.

+ +
+

The options of the select is {{options1}}

+

You have select {{myModel}}

+ + ----> + +
+ +

Dynamic modify selection

+

The model change will affect the selection. Click the Change Model button to change the model randomly.

+
+

The options of the select is {{options2}}

+

You have select {{model2}}

+ + ----> + +
+ +
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/main.css b/examples/main.css new file mode 100644 index 0000000..347d5b4 --- /dev/null +++ b/examples/main.css @@ -0,0 +1,33 @@ +.masthead { + color: #ffffff; + padding-top: 10px; + padding-bottom: 20px; + background: #000000; /* Old browsers */ + background: -moz-linear-gradient(top, #000000 0%, #45484d 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#000000), color-stop(100%,#45484d)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #000000 0%,#45484d 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #000000 0%,#45484d 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #000000 0%,#45484d 100%); /* IE10+ */ + background: linear-gradient(to bottom, #000000 0%,#45484d 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#000000', endColorstr='#45484d',GradientType=0 ); /* IE6-9 */ +} + +.masthead h1 { + margin-top: 20px; + margin-bottom: 15px; +} + +.footer { + text-align: center; + padding: 30px 0; + margin-top: 70px; + color: #ffffff; + background: #000000; /* Old browsers */ + background: -moz-linear-gradient(top, #45484d 0%, #000000 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#45484d), color-stop(100%,#000000)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #45484d 0%,#000000 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #45484d 0%,#000000 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #45484d 0%,#000000 100%); /* IE10+ */ + background: linear-gradient(to bottom, #45484d 0%,#000000 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#45484d', endColorstr='#000000',GradientType=0 ); /* IE6-9 */ +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..d3d4799 --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "name": "nya-bootstrap-select", + "version": "1.0.0", + "devDependencies": { + "grunt": "~0.4.2", + "grunt-contrib-connect": "~0.6.0", + "grunt-contrib-watch": "~0.5.3", + "load-grunt-tasks": "~0.3.0", + "time-grunt": "~0.2.9", + "jshint-stylish": "~0.1.5", + "grunt-newer": "~0.6.1", + "grunt-contrib-jshint": "~0.8.0", + "karma-phantomjs-launcher": "~0.1.2", + "karma": "~0.10.9" + } +} diff --git a/src/nya-bootstrap-select.js b/src/nya-bootstrap-select.js new file mode 100644 index 0000000..88675a9 --- /dev/null +++ b/src/nya-bootstrap-select.js @@ -0,0 +1,73 @@ +'use strict'; + +angular.module('nyaBootstrapSelect',[]) + .directive('nyaSelectpicker', function () { + return { + restrict: 'CA', + scope: false, + require: ['^ngModel', 'select'], + + link: function(scope, element, attrs, ctrls) { + var ngCtrl = ctrls[0]; + var selectCtrl = ctrls[1]; + // prevent selectDirective render an unknownOption. + selectCtrl.renderUnknownOption = angular.noop; + var optionArray = []; + scope.$watch(function optionDOMWatch(){ + // check every option if has changed. + var optionElements = $(element).find('option.ng-scope'); + + if(optionElements.length !== optionArray.length) { + optionArray = makeOptionArray(optionElements); + buildSelector(); + } else { + var hasChanged = false; + optionElements.each(function(index, value){ + if(optionArray[index].text !== value.text || optionArray[index].value !== value.value) { + hasChanged = true; + + } + }); + if(hasChanged) { + buildSelector(); + } + optionArray = makeOptionArray(optionElements); + } + + }); + + ngCtrl.$render = function() { + // model -> view + var data = $(element).data('selectpicker'); + if(data) { + $(element).val(ngCtrl.$viewValue).selectpicker('render'); + } + }; + + function makeOptionArray(optionElements) { + var optionArray = []; + optionElements.each(function(index, childNode){ + optionArray.push({ + value: childNode.value, + text: childNode.text + }); + }); + return optionArray; + } + + function buildSelector() { + // build new selector. if previous select exists. remove previous data and DOM + var oldSelectPicker = $(element).data('selectpicker'); + if(oldSelectPicker) { + oldSelectPicker.$menu.parent().remove(); + oldSelectPicker.$newElement.remove(); + $(element).removeData('selectpicker'); + } + $(element).selectpicker(); +// console.log(ngCtrl.$modelValue); + $(element).val(ngCtrl.$modelValue).selectpicker('render'); + } + + } + }; + });