diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0cfc89f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +bower_components/ +node_modules/ \ No newline at end of file diff --git a/bower.json b/bower.json index 8a806b6..8fe6e79 100644 --- a/bower.json +++ b/bower.json @@ -5,7 +5,7 @@ "type": "git", "url": "git://github.com/leocaseiro/angular-chosen.git" }, - "main": "chosen.js", + "main": "dist/angular-chosen.js", "dependencies": { "chosen": "^1.1.0", "angular": "^1.2.0" diff --git a/chosen.js b/chosen.js index d32e697..c74f12a 100644 --- a/chosen.js +++ b/chosen.js @@ -1,135 +1 @@ -// Generated by CoffeeScript 1.10.0 -(function() { - var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; - - angular.module('localytics.directives', []); - - angular.module('localytics.directives').directive('chosen', [ - '$timeout', function($timeout) { - var CHOSEN_OPTION_WHITELIST, NG_OPTIONS_REGEXP, isEmpty, snakeCase; - NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/; - CHOSEN_OPTION_WHITELIST = ['noResultsText', 'allowSingleDeselect', 'disableSearchThreshold', 'disableSearch', 'enableSplitWordSearch', 'inheritSelectClasses', 'maxSelectedOptions', 'placeholderTextMultiple', 'placeholderTextSingle', 'searchContains', 'singleBackstrokeDelete', 'displayDisabledOptions', 'displaySelectedOptions', 'width']; - snakeCase = function(input) { - return input.replace(/[A-Z]/g, function($1) { - return "_" + ($1.toLowerCase()); - }); - }; - isEmpty = function(value) { - var key; - if (angular.isArray(value)) { - return value.length === 0; - } else if (angular.isObject(value)) { - for (key in value) { - if (value.hasOwnProperty(key)) { - return false; - } - } - } - return true; - }; - return { - restrict: 'A', - require: '?ngModel', - priority: 1, - link: function(scope, element, attr, ngModel) { - var chosen, defaultText, disableWithMessage, empty, initOrUpdate, match, options, origRender, removeEmptyMessage, startLoading, stopLoading, valuesExpr, viewWatch; - scope.disabledValuesHistory = scope.disabledValuesHistory ? scope.disabledValuesHistory : []; - element.addClass('localytics-chosen'); - options = scope.$eval(attr.chosen) || {}; - angular.forEach(attr, function(value, key) { - if (indexOf.call(CHOSEN_OPTION_WHITELIST, key) >= 0) { - return options[snakeCase(key)] = String(element.attr(attr.$attr[key])).slice(0, 2) === '{{' ? value : scope.$eval(value); - } - }); - startLoading = function() { - var disabledValueOfElement, elementAlreadyExists; - disabledValueOfElement = {}; - elementAlreadyExists = false; - angular.forEach(scope.disabledValuesHistory, function(data) { - if (data.hasOwnProperty(element.context.id)) { - data[element.context.id] = element.context.disabled; - elementAlreadyExists = true; - } - }); - if (!elementAlreadyExists) { - disabledValueOfElement[element.context.id] = element.context.disabled; - scope.disabledValuesHistory.push(disabledValueOfElement); - } - return element.addClass('loading').attr('disabled', true).trigger('chosen:updated'); - }; - stopLoading = function() { - var disabledValue; - disabledValue = false; - angular.forEach(scope.disabledValuesHistory, function(data) { - disabledValue = data.hasOwnProperty(element.context.id) ? data[element.context.id] : disabledValue; - }); - return element.removeClass('loading').attr('disabled', disabledValue).trigger('chosen:updated'); - }; - chosen = null; - defaultText = null; - empty = false; - initOrUpdate = function() { - if (chosen) { - return element.trigger('chosen:updated'); - } else { - chosen = element.chosen(options); - return defaultText = chosen.default_text; - } - }; - removeEmptyMessage = function() { - empty = false; - return element.attr('data-placeholder', defaultText).trigger('chosen:updated'); - }; - disableWithMessage = function() { - empty = true; - return element.attr('data-placeholder', chosen.results_none_found).attr('disabled', true).trigger('chosen:updated'); - }; - if (ngModel) { - origRender = ngModel.$render; - ngModel.$render = function() { - origRender(); - return initOrUpdate(); - }; - if (attr.multiple) { - viewWatch = function() { - return ngModel.$viewValue; - }; - scope.$watch(viewWatch, ngModel.$render, true); - } - } else { - initOrUpdate(); - } - attr.$observe('disabled', function() { - return element.trigger('chosen:updated'); - }); - if (attr.ngOptions && ngModel) { - match = attr.ngOptions.match(NG_OPTIONS_REGEXP); - valuesExpr = match[7]; - scope.$watchCollection(valuesExpr, function(newVal, oldVal) { - var timer; - return timer = $timeout(function() { - if (angular.isUndefined(newVal)) { - return startLoading(); - } else { - if (empty) { - removeEmptyMessage(); - } - stopLoading(); - if (isEmpty(newVal) && !attr.allowEmptyResultsList) { - return disableWithMessage(); - } - } - }); - }); - return scope.$on('$destroy', function(event) { - if (typeof timer !== "undefined" && timer !== null) { - return $timeout.cancel(timer); - } - }); - } - } - }; - } - ]); - -}).call(this); +console.warn('the file ./chosen.js is deprecated, you must include ./dist/angular-chosen.js or ./dist/angular-chosen.min.js instead'); \ No newline at end of file diff --git a/dist/angular-chosen.js b/dist/angular-chosen.js new file mode 100644 index 0000000..2788013 --- /dev/null +++ b/dist/angular-chosen.js @@ -0,0 +1,137 @@ +/** + * angular-chosen-localytics - Angular Chosen directive is an AngularJS Directive that brings the Chosen jQuery in a Angular way + * @version v1.2.0 + * @link http://github.com/leocaseiro/angular-chosen + * @license MIT + */ +var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + +angular.module('localytics.directives', []); + +angular.module('localytics.directives').directive('chosen', [ + '$timeout', function($timeout) { + var CHOSEN_OPTION_WHITELIST, NG_OPTIONS_REGEXP, isEmpty, snakeCase; + NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/; + CHOSEN_OPTION_WHITELIST = ['noResultsText', 'allowSingleDeselect', 'disableSearchThreshold', 'disableSearch', 'enableSplitWordSearch', 'inheritSelectClasses', 'maxSelectedOptions', 'placeholderTextMultiple', 'placeholderTextSingle', 'searchContains', 'singleBackstrokeDelete', 'displayDisabledOptions', 'displaySelectedOptions', 'width']; + snakeCase = function(input) { + return input.replace(/[A-Z]/g, function($1) { + return "_" + ($1.toLowerCase()); + }); + }; + isEmpty = function(value) { + var key; + if (angular.isArray(value)) { + return value.length === 0; + } else if (angular.isObject(value)) { + for (key in value) { + if (value.hasOwnProperty(key)) { + return false; + } + } + } + return true; + }; + return { + restrict: 'A', + require: '?ngModel', + priority: 1, + link: function(scope, element, attr, ngModel) { + var chosen, defaultText, disableWithMessage, empty, initOrUpdate, match, options, origRender, removeEmptyMessage, startLoading, stopLoading, valuesExpr, viewWatch; + scope.disabledValuesHistory = scope.disabledValuesHistory ? scope.disabledValuesHistory : []; + element.addClass('localytics-chosen'); + options = scope.$eval(attr.chosen) || {}; + angular.forEach(attr, function(value, key) { + if (indexOf.call(CHOSEN_OPTION_WHITELIST, key) >= 0) { + return options[snakeCase(key)] = String(element.attr(attr.$attr[key])).slice(0, 2) === '{{' ? value : scope.$eval(value); + } + }); + startLoading = function() { + var disabledValueOfElement, elementAlreadyExists; + disabledValueOfElement = {}; + elementAlreadyExists = false; + angular.forEach(scope.disabledValuesHistory, function(data) { + if (data.hasOwnProperty(element.context.id)) { + data[element.context.id] = element.context.disabled; + elementAlreadyExists = true; + } + }); + if (!elementAlreadyExists) { + disabledValueOfElement[element.context.id] = element.context.disabled; + scope.disabledValuesHistory.push(disabledValueOfElement); + } + return element.addClass('loading').attr('disabled', true).trigger('chosen:updated'); + }; + stopLoading = function() { + var disabledValue; + disabledValue = false; + angular.forEach(scope.disabledValuesHistory, function(data) { + disabledValue = data.hasOwnProperty(element.context.id) ? data[element.context.id] : disabledValue; + }); + return element.removeClass('loading').attr('disabled', disabledValue).trigger('chosen:updated'); + }; + chosen = null; + defaultText = null; + empty = false; + initOrUpdate = function() { + if (chosen) { + return element.trigger('chosen:updated'); + } else { + chosen = element.chosen(options); + return defaultText = chosen.default_text; + } + }; + removeEmptyMessage = function() { + empty = false; + return element.attr('data-placeholder', defaultText).trigger('chosen:updated'); + }; + disableWithMessage = function() { + empty = true; + return element.attr('data-placeholder', chosen.results_none_found).attr('disabled', true).trigger('chosen:updated'); + }; + if (ngModel) { + origRender = ngModel.$render; + ngModel.$render = function() { + origRender(); + return initOrUpdate(); + }; + if (attr.multiple) { + viewWatch = function() { + return ngModel.$viewValue; + }; + scope.$watch(viewWatch, ngModel.$render, true); + } + } else { + initOrUpdate(); + } + attr.$observe('disabled', function() { + return element.trigger('chosen:updated'); + }); + if (attr.ngOptions && ngModel) { + match = attr.ngOptions.match(NG_OPTIONS_REGEXP); + valuesExpr = match[7]; + scope.$watchCollection(valuesExpr, function(newVal, oldVal) { + var timer; + return timer = $timeout(function() { + if (angular.isUndefined(newVal)) { + return startLoading(); + } else { + if (empty) { + removeEmptyMessage(); + } + stopLoading(); + if (isEmpty(newVal) && !attr.allowEmptyResultsList) { + return disableWithMessage(); + } + } + }); + }); + return scope.$on('$destroy', function(event) { + if (typeof timer !== "undefined" && timer !== null) { + return $timeout.cancel(timer); + } + }); + } + } + }; + } +]); diff --git a/dist/angular-chosen.min.js b/dist/angular-chosen.min.js new file mode 100644 index 0000000..d8fc989 --- /dev/null +++ b/dist/angular-chosen.min.js @@ -0,0 +1,7 @@ +/** + * angular-chosen-localytics - Angular Chosen directive is an AngularJS Directive that brings the Chosen jQuery in a Angular way + * @version v1.2.0 + * @link http://github.com/leocaseiro/angular-chosen + * @license MIT + */ +var indexOf=[].indexOf||function(e){for(var t=0,r=this.length;r>t;t++)if(t in this&&this[t]===e)return t;return-1};angular.module("localytics.directives",[]),angular.module("localytics.directives").directive("chosen",["$timeout",function(e){var t,r,n,i;return r=/^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/,t=["noResultsText","allowSingleDeselect","disableSearchThreshold","disableSearch","enableSplitWordSearch","inheritSelectClasses","maxSelectedOptions","placeholderTextMultiple","placeholderTextSingle","searchContains","singleBackstrokeDelete","displayDisabledOptions","displaySelectedOptions","width"],i=function(e){return e.replace(/[A-Z]/g,function(e){return"_"+e.toLowerCase()})},n=function(e){var t;if(angular.isArray(e))return 0===e.length;if(angular.isObject(e))for(t in e)if(e.hasOwnProperty(t))return!1;return!0},{restrict:"A",require:"?ngModel",priority:1,link:function(a,s,l,o){var d,u,c,f,h,g,p,y,b,v,$,w,x;return a.disabledValuesHistory=a.disabledValuesHistory?a.disabledValuesHistory:[],s.addClass("localytics-chosen"),p=a.$eval(l.chosen)||{},angular.forEach(l,function(e,r){return indexOf.call(t,r)>=0?p[i(r)]="{{"===String(s.attr(l.$attr[r])).slice(0,2)?e:a.$eval(e):void 0}),v=function(){var e,t;return e={},t=!1,angular.forEach(a.disabledValuesHistory,function(e){e.hasOwnProperty(s.context.id)&&(e[s.context.id]=s.context.disabled,t=!0)}),t||(e[s.context.id]=s.context.disabled,a.disabledValuesHistory.push(e)),s.addClass("loading").attr("disabled",!0).trigger("chosen:updated")},$=function(){var e;return e=!1,angular.forEach(a.disabledValuesHistory,function(t){e=t.hasOwnProperty(s.context.id)?t[s.context.id]:e}),s.removeClass("loading").attr("disabled",e).trigger("chosen:updated")},d=null,u=null,f=!1,h=function(){return d?s.trigger("chosen:updated"):(d=s.chosen(p),u=d.default_text)},b=function(){return f=!1,s.attr("data-placeholder",u).trigger("chosen:updated")},c=function(){return f=!0,s.attr("data-placeholder",d.results_none_found).attr("disabled",!0).trigger("chosen:updated")},o?(y=o.$render,o.$render=function(){return y(),h()},l.multiple&&(x=function(){return o.$viewValue},a.$watch(x,o.$render,!0))):h(),l.$observe("disabled",function(){return s.trigger("chosen:updated")}),l.ngOptions&&o?(g=l.ngOptions.match(r),w=g[7],a.$watchCollection(w,function(t,r){var i;return i=e(function(){return angular.isUndefined(t)?v():(f&&b(),$(),n(t)&&!l.allowEmptyResultsList?c():void 0)})}),a.$on("$destroy",function(t){return"undefined"!=typeof timer&&null!==timer?e.cancel(timer):void 0})):void 0}}}]); \ No newline at end of file diff --git a/example/index.html b/example/index.html index ad45e84..2b50765 100644 --- a/example/index.html +++ b/example/index.html @@ -6,7 +6,7 @@ - + diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..ff3730b --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,82 @@ +var config = { + src: './src/', + dist: './dist/', + file: 'angular-chosen' +}; + +var banner = ['/**', + ' * <%= pkg.name %> - <%= pkg.description %>', + ' * @version v<%= pkg.version %>', + ' * @link <%= pkg.homepage %>', + ' * @license <%= pkg.license %>', + ' */', + ''].join('\n'); + +var args = require('yargs').argv, + gulp = require('gulp'), + del = require('del'), + $ = require('gulp-load-plugins')({ lazy: true }), + pkg = require('./package.json'); + +// List Tasks by default +gulp.task('default', $.taskListing.withFilters(null, ['build-hint'])); + +//TODO rewrite Coffee Script of coffeelint() +gulp.task('build-hint', function() { + return gulp.src(config.src + '/*.coffee') + .pipe($.if(args.debug, $.debug())) + .pipe($.plumber()) + .pipe($.coffeelint()) + .pipe($.coffeelint.reporter()); + // .pipe($.jshint()) + // .pipe($.jshint.reporter('jshint-stylish', { verbose: true })); + // .pipe($.jscs()); +}); + +// gulp.task('build-coffee-script', ['build-hint'], function() { +/** + * Compile CoffeeScript into ./dist/angular-chose.js + */ +gulp.task('build-coffee-script', function() { + return gulp.src(config.src + '/*.coffee') + .pipe($.if(args.debug, $.debug())) + .pipe($.plumber()) + .pipe($.coffee({bare: true}).on('error', $.util.log)) + .pipe($.rename(config.file + '.js')) + .pipe($.header(banner, { pkg : pkg })) + .pipe(gulp.dest(config.dist)); +}); + +/** + * Minify ./dist/angular-chose.js into ./dist/angular-chose.min.js + */ +gulp.task('build-minify', ['build-coffee-script'], function() { + return gulp.src(config.dist + '/angular-chosen.js') + .pipe($.if(args.debug, $.debug())) + .pipe($.plumber()) + .pipe($.uglify({mangle: true})) + .pipe($.rename(config.file + '.min.js')) + .pipe($.header(banner, {pkg : pkg})) + .pipe(gulp.dest(config.dist)); +}); + +/** + * Run Clean Javascripts, than minify(coffee-script) + */ +gulp.task('build', ['build-clean-javascripts'], function() { + gulp.start('build-minify'); +}); + +/** + * Clean Javascripts from .dist/ + */ +gulp.task('build-clean-javascripts', function() { + return del(config.dist); +}); + +/** + * Watch files and compile Coffee Script in real-time + */ +gulp.task('watcher', ['minify'], function() { + gulp.watch([config.src + '*.coffee', config.dist + '*.js'], ['minify']); +}); \ No newline at end of file diff --git a/package.json b/package.json index 77ad199..43c6c00 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "angular-chosen-localytics", "filename": "chosen.js", - "version": "1.1.0", + "version": "1.2.0", "description": "Angular Chosen directive is an AngularJS Directive that brings the Chosen jQuery in a Angular way", "homepage": "http://github.com/leocaseiro/angular-chosen", "repository": { @@ -39,11 +39,31 @@ "slobo" ], "dependencies": { - "jquery": "~2.0.3", - "chosen": "~1.1.0", - "angular": "~1.2.0" + "jquery": "^2.0.3", + "chosen": "^1.1.0", + "angular": "^1.2.0" }, "bugs": { "url": "https://github.com/leocaseiro/angular-chosen/issues" + }, + "devDependencies": { + "del": "^2.2.0", + "gulp": "^3.9.1", + "gulp-coffee": "^2.3.1", + "gulp-coffeelint": "^0.6.0", + "gulp-debug": "^2.1.2", + "gulp-header": "^1.7.1", + "gulp-if": "^2.0.0", + "gulp-jscs": "^3.0.2", + "gulp-jshint": "^2.0.0", + "gulp-load-plugins": "^1.2.0", + "gulp-plumber": "^1.1.0", + "gulp-rename": "^1.2.2", + "gulp-task-listing": "^1.0.1", + "gulp-uglify": "^1.5.3", + "gulp-util": "^3.0.7", + "jshint": "^2.9.1", + "jshint-stylish": "^2.1.0", + "yargs": "^4.2.0" } -} \ No newline at end of file +}