angular-bulma
Advanced tools
Comparing version 0.1.2 to 0.3.0
{ | ||
"name": "angular-bulma", | ||
"version": "0.1.2", | ||
"version": "0.3.0", | ||
"homepage": "https://github.com/gfpacheco/angular-bulma", | ||
@@ -37,3 +37,6 @@ "repository": { | ||
"dependencies": { | ||
"bulma": "^0.0.28" | ||
"moment": "^2.14.1", | ||
"jquery": "^1.9.0", | ||
"bulma": "^0.1.2", | ||
"bulma-daterangepicker": "^2.2.0" | ||
}, | ||
@@ -40,0 +43,0 @@ "devDependencies": { |
@@ -19,9 +19,262 @@ (function (angular) { | ||
var DEFAULT_OPTIONS = { | ||
clearLabel: 'Clear', | ||
locale: { | ||
separator: ' - ', | ||
format: 'YYYY-MM-DD' | ||
} | ||
}; | ||
angular | ||
.module('bulma.directives') | ||
.directive('buDaterangepicker', buDaterangepicker); | ||
buDaterangepicker.$inject = ['$compile', '$timeout', '$parse']; | ||
function buDaterangepicker($compile, $timeout, $parse) { | ||
var directive = { | ||
require: 'ngModel', | ||
restrict: 'E', | ||
replace: true, | ||
scope: { | ||
min: '=', | ||
max: '=', | ||
model: '=ngModel', | ||
options: '=', | ||
clearable: '=' | ||
}, | ||
template: '<input class="input">', | ||
link: link | ||
}; | ||
return directive; | ||
/// | ||
function link($scope, element, attrs, modelCtrl) { | ||
var mergeOptions = function() { | ||
var extend, localeExtend; | ||
localeExtend = angular.extend.apply(angular, Array.prototype.slice.call(arguments).map(function(opt) { | ||
return opt != null ? opt.locale : void 0; | ||
}).filter(function(opt) { | ||
return !!opt; | ||
})); | ||
extend = angular.extend.apply(angular, arguments); | ||
extend.locale = localeExtend; | ||
return extend; | ||
}; | ||
var el = jQuery(element); | ||
var customOptions = $scope.options; | ||
var options = mergeOptions({}, DEFAULT_OPTIONS, customOptions); | ||
var picker = null; | ||
var clear = function() { | ||
if (picker) { | ||
picker.setStartDate(); | ||
picker.setEndDate(); | ||
} | ||
}; | ||
var setDatePoint = function(setter) { | ||
return function(newValue) { | ||
if (picker && newValue) { | ||
setter(moment(newValue)); | ||
} | ||
}; | ||
}; | ||
var setStartDate = setDatePoint(function(m) { | ||
if (picker.endDate < m) { | ||
picker.setEndDate(m); | ||
} | ||
options.startDate = m; | ||
picker.setStartDate(m); | ||
}); | ||
var setEndDate = setDatePoint(function(m) { | ||
if (picker.startDate > m) { | ||
picker.setStartDate(m); | ||
} | ||
options.endDate = m; | ||
picker.setEndDate(m); | ||
}); | ||
var validate = function(validator) { | ||
return function(boundary, actual) { | ||
if (boundary && actual) { | ||
return validator(moment(boundary), moment(actual)); | ||
} else { | ||
return true; | ||
} | ||
}; | ||
}; | ||
var validateMin = validate(function(min, start) { | ||
return min.isBefore(start) || min.isSame(start, 'day'); | ||
}); | ||
var validateMax = validate(function(max, end) { | ||
return max.isAfter(end) || max.isSame(end, 'day'); | ||
}); | ||
modelCtrl.$formatters.push(function(objValue) { | ||
var f = function(date) { | ||
if (!moment.isMoment(date)) { | ||
return moment(date).format(options.locale.format); | ||
} else { | ||
return date.format(options.locale.format); | ||
} | ||
}; | ||
if (options.singleDatePicker && objValue) { | ||
return f(objValue); | ||
} else if (objValue.startDate) { | ||
return [f(objValue.startDate), f(objValue.endDate)].join(options.locale.separator); | ||
} else { | ||
return ''; | ||
} | ||
}); | ||
modelCtrl.$render = function() { | ||
if (modelCtrl.$modelValue && modelCtrl.$modelValue.startDate) { | ||
setStartDate(modelCtrl.$modelValue.startDate); | ||
setEndDate(modelCtrl.$modelValue.endDate); | ||
} else { | ||
clear(); | ||
} | ||
el.val(modelCtrl.$viewValue); | ||
}; | ||
modelCtrl.$parsers.push(function(val) { | ||
var f = function(value) { | ||
return moment(value, options.locale.format); | ||
}; | ||
var objValue = { | ||
startDate: null, | ||
endDate: null | ||
}; | ||
if (angular.isString(val) && val.length > 0) { | ||
if (options.singleDatePicker) { | ||
objValue = f(val); | ||
} else { | ||
var parts = val.split(options.locale.separator).map(f); | ||
objValue.startDate = parts[0]; | ||
objValue.endDate = parts[1]; | ||
} | ||
} | ||
return objValue; | ||
}); | ||
modelCtrl.$isEmpty = function(val) { | ||
return !(angular.isString(val) && val.length > 0); | ||
}; | ||
var init = function() { | ||
el.daterangepicker(angular.extend(options, { | ||
autoUpdateInput: false | ||
}), function(start, end) { | ||
$scope.$apply(function() { | ||
$scope.model = options.singleDatePicker ? start : { | ||
startDate: start, | ||
endDate: end | ||
}; | ||
}); | ||
}); | ||
picker = el.data('daterangepicker'); | ||
var results = []; | ||
var eventType; | ||
for (eventType in options.eventHandlers) { | ||
if (options.eventHandlers.hasOwnProperty(eventType)) { | ||
results.push(el.on(eventType, function(e) { | ||
var eventName; | ||
eventName = e.type + '.' + e.namespace; | ||
$scope.$evalAsync(options.eventHandlers[eventName]); | ||
})); | ||
} | ||
} | ||
}; | ||
init(); | ||
$scope.$watch('model.startDate', function(n) { | ||
setStartDate(n); | ||
}); | ||
$scope.$watch('model.endDate', function(n) { | ||
setEndDate(n); | ||
}); | ||
var initBoundaryField = function(field, validator, modelField, optName) { | ||
if (attrs[field]) { | ||
modelCtrl.$validators[field] = function(value) { | ||
return value && validator(options[optName], value[modelField]); | ||
}; | ||
$scope.$watch(field, function(date) { | ||
options[optName] = date ? moment(date) : false; | ||
init(); | ||
}); | ||
} | ||
}; | ||
initBoundaryField('min', validateMin, 'startDate', 'minDate'); | ||
initBoundaryField('max', validateMax, 'endDate', 'maxDate'); | ||
if (attrs.options) { | ||
$scope.$watch('options', function(newOptions) { | ||
options = mergeOptions(options, newOptions); | ||
init(); | ||
}, true); | ||
} | ||
if (attrs.clearable) { | ||
$scope.$watch('clearable', function(newClearable) { | ||
if (newClearable) { | ||
options = mergeOptions(options, { | ||
locale: { | ||
cancelLabel: options.clearLabel | ||
} | ||
}); | ||
} | ||
init(); | ||
if (newClearable) { | ||
el.on('cancel.daterangepicker', function() { | ||
$scope.$apply(function() { | ||
$scope.model = options.singleDatePicker ? null : { | ||
startDate: null, | ||
endDate: null | ||
}; | ||
}); | ||
}); | ||
} | ||
}); | ||
} | ||
$scope.$on('$destroy', function() { | ||
if (picker) { | ||
picker.remove(); | ||
} | ||
}); | ||
} | ||
} | ||
})(angular); | ||
(function (angular) { | ||
angular | ||
.module('bulma.directives') | ||
.directive('buDropdown', buDropdown); | ||
buDropdown.$inject = ['$document']; | ||
buDropdown.$inject = ['$window', '$document']; | ||
function buDropdown($document) { | ||
function buDropdown($window, $document) { | ||
var directive = { | ||
@@ -46,3 +299,3 @@ restrict: 'C', | ||
event.stopPropagation(); | ||
if (body.css('display') === 'none') { | ||
if ($window.getComputedStyle(body[0], null).display === 'none') { | ||
open(); | ||
@@ -71,1 +324,83 @@ } else { | ||
})(angular); | ||
(function (angular) { | ||
var MILISECONDS_IN_ONE_MINUTE = 1000 * 60; | ||
var MILISECONDS_IN_ONE_HOUR = MILISECONDS_IN_ONE_MINUTE * 60; | ||
angular | ||
.module('bulma.directives') | ||
.directive('buTimepicker', buTimepicker); | ||
buTimepicker.$inject = ['$document']; | ||
function buTimepicker($document) { | ||
var directive = { | ||
restrict: 'E', | ||
require: '?ngModel', | ||
scope: {}, | ||
template: '<div class="bu-timepicker control is-grouped">' + | ||
'<input class="input" ng-model="hours" ng-change="onInputChange()">' + | ||
'<span>:</span>' + | ||
'<input class="input" ng-model="minutes" ng-change="onInputChange()">' + | ||
'</div>', | ||
link: link | ||
}; | ||
return directive; | ||
/// | ||
function link(scope, element, attrs, ngModel) { | ||
if (!ngModel) { | ||
return; | ||
} | ||
var timepicker = angular.element(element[0]); | ||
var inputs = element.find('input'); | ||
var hoursInput = inputs.eq(0); | ||
ngModel.$formatters.push(modelToView); | ||
ngModel.$parsers.push(viewToModel); | ||
ngModel.$render = render; | ||
scope.onInputChange = onInputChange; | ||
/// | ||
function formatInput(value, max) { | ||
value = ('' + value).replace(/[^0-9]/, ''); | ||
if (parseInt(value || 0, 10) > max) { | ||
value = max; | ||
} | ||
value = '00' + value; | ||
return value.substr(-2); | ||
} | ||
function modelToView(modelValue) { | ||
return { | ||
hours: formatInput(Math.floor(modelValue / MILISECONDS_IN_ONE_HOUR), 23), | ||
minutes: formatInput(Math.floor((modelValue % MILISECONDS_IN_ONE_HOUR) / MILISECONDS_IN_ONE_MINUTE), 59) | ||
}; | ||
} | ||
function viewToModel(viewValue) { | ||
return (viewValue.hours * MILISECONDS_IN_ONE_HOUR) + (viewValue.minutes * MILISECONDS_IN_ONE_MINUTE); | ||
} | ||
function render() { | ||
scope.hours = ngModel.$viewValue.hours; | ||
scope.minutes = ngModel.$viewValue.minutes; | ||
} | ||
function onInputChange() { | ||
ngModel.$setViewValue({ | ||
hours: formatInput(scope.hours, 23), | ||
minutes: formatInput(scope.minutes, 59) | ||
}); | ||
ngModel.$render(); | ||
} | ||
} | ||
} | ||
})(angular); |
@@ -1,1 +0,1 @@ | ||
!function(n){n.module("bulma",["bulma.directives"])}(angular),function(n){n.module("bulma.directives",[])}(angular),function(n){function o(o){function c(c,i){function e(n){n.stopPropagation(),"none"===l.css("display")?u():t()}function u(){l.css("display","block"),o.on("click",t)}function t(){l.css("display","none"),o.off("click",t)}i.on("click",e);var l=n.element(i[0].querySelector(".bu-dropdown-body"));c.$on("$destroy",function(){o.off("click",t)})}var i={restrict:"C",scope:{align:"@"},link:c};return i}n.module("bulma.directives").directive("buDropdown",o),o.$inject=["$document"]}(angular); | ||
!function(e){e.module("bulma",["bulma.directives"])}(angular),function(e){e.module("bulma.directives",[])}(angular),function(e){function n(n,a,r){function o(n,a,r,o){var i=function(){var n,t;return t=e.extend.apply(e,Array.prototype.slice.call(arguments).map(function(e){return null!=e?e.locale:void 0}).filter(function(e){return!!e})),n=e.extend.apply(e,arguments),n.locale=t,n},u=jQuery(a),l=n.options,c=i({},t,l),s=null,m=function(){s&&(s.setStartDate(),s.setEndDate())},d=function(e){return function(n){s&&n&&e(moment(n))}},f=d(function(e){s.endDate<e&&s.setEndDate(e),c.startDate=e,s.setStartDate(e)}),p=d(function(e){s.startDate>e&&s.setStartDate(e),c.endDate=e,s.setEndDate(e)}),D=function(e){return function(n,t){return!n||!t||e(moment(n),moment(t))}},$=D(function(e,n){return e.isBefore(n)||e.isSame(n,"day")}),v=D(function(e,n){return e.isAfter(n)||e.isSame(n,"day")});o.$formatters.push(function(e){var n=function(e){return moment.isMoment(e)?e.format(c.locale.format):moment(e).format(c.locale.format)};return c.singleDatePicker&&e?n(e):e.startDate?[n(e.startDate),n(e.endDate)].join(c.locale.separator):""}),o.$render=function(){o.$modelValue&&o.$modelValue.startDate?(f(o.$modelValue.startDate),p(o.$modelValue.endDate)):m(),u.val(o.$viewValue)},o.$parsers.push(function(n){var t=function(e){return moment(e,c.locale.format)},a={startDate:null,endDate:null};if(e.isString(n)&&n.length>0)if(c.singleDatePicker)a=t(n);else{var r=n.split(c.locale.separator).map(t);a.startDate=r[0],a.endDate=r[1]}return a}),o.$isEmpty=function(n){return!(e.isString(n)&&n.length>0)};var g=function(){u.daterangepicker(e.extend(c,{autoUpdateInput:!1}),function(e,t){n.$apply(function(){n.model=c.singleDatePicker?e:{startDate:e,endDate:t}})}),s=u.data("daterangepicker");var t,a=[];for(t in c.eventHandlers)c.eventHandlers.hasOwnProperty(t)&&a.push(u.on(t,function(e){var t;t=e.type+"."+e.namespace,n.$evalAsync(c.eventHandlers[t])}))};g(),n.$watch("model.startDate",function(e){f(e)}),n.$watch("model.endDate",function(e){p(e)});var h=function(e,t,a,i){r[e]&&(o.$validators[e]=function(e){return e&&t(c[i],e[a])},n.$watch(e,function(e){c[i]=!!e&&moment(e),g()}))};h("min",$,"startDate","minDate"),h("max",v,"endDate","maxDate"),r.options&&n.$watch("options",function(e){c=i(c,e),g()},!0),r.clearable&&n.$watch("clearable",function(e){e&&(c=i(c,{locale:{cancelLabel:c.clearLabel}})),g(),e&&u.on("cancel.daterangepicker",function(){n.$apply(function(){n.model=c.singleDatePicker?null:{startDate:null,endDate:null}})})}),n.$on("$destroy",function(){s&&s.remove()})}var i={require:"ngModel",restrict:"E",replace:!0,scope:{min:"=",max:"=",model:"=ngModel",options:"=",clearable:"="},template:'<input class="input">',link:o};return i}var t={clearLabel:"Clear",locale:{separator:" - ",format:"YYYY-MM-DD"}};e.module("bulma.directives").directive("buDaterangepicker",n),n.$inject=["$compile","$timeout","$parse"]}(angular),function(e){function n(n,t){function a(a,r){function o(e){e.stopPropagation(),"none"===n.getComputedStyle(l[0],null).display?i():u()}function i(){l.css("display","block"),t.on("click",u)}function u(){l.css("display","none"),t.off("click",u)}r.on("click",o);var l=e.element(r[0].querySelector(".bu-dropdown-body"));a.$on("$destroy",function(){t.off("click",u)})}var r={restrict:"C",scope:{align:"@"},link:a};return r}e.module("bulma.directives").directive("buDropdown",n),n.$inject=["$window","$document"]}(angular),function(e){function n(n){function r(n,r,o,i){function u(e,n){return e=(""+e).replace(/[^0-9]/,""),parseInt(e||0,10)>n&&(e=n),e="00"+e,e.substr(-2)}function l(e){return{hours:u(Math.floor(e/a),23),minutes:u(Math.floor(e%a/t),59)}}function c(e){return e.hours*a+e.minutes*t}function s(){n.hours=i.$viewValue.hours,n.minutes=i.$viewValue.minutes}function m(){i.$setViewValue({hours:u(n.hours,23),minutes:u(n.minutes,59)}),i.$render()}if(i){var d=(e.element(r[0]),r.find("input"));d.eq(0);i.$formatters.push(l),i.$parsers.push(c),i.$render=s,n.onInputChange=m}}var o={restrict:"E",require:"?ngModel",scope:{},template:'<div class="bu-timepicker control is-grouped"><input class="input" ng-model="hours" ng-change="onInputChange()"><span>:</span><input class="input" ng-model="minutes" ng-change="onInputChange()"></div>',link:r};return o}var t=6e4,a=60*t;e.module("bulma.directives").directive("buTimepicker",n),n.$inject=["$document"]}(angular); |
{ | ||
"name": "angular-bulma", | ||
"version": "0.1.2", | ||
"version": "0.3.0", | ||
"homepage": "https://github.com/gfpacheco/angular-bulma", | ||
@@ -22,3 +22,6 @@ "repository": { | ||
"dependencies": { | ||
"bulma": "^0.0.28" | ||
"bulma": "^0.1.2", | ||
"bulma-daterangepicker": "^2.2.0", | ||
"jquery": "^1.9.0", | ||
"moment": "^2.14.1" | ||
}, | ||
@@ -25,0 +28,0 @@ "devDependencies": { |
@@ -1,2 +0,2 @@ | ||
# angular-bulma | ||
# angular-bulma [![Build Status](https://travis-ci.org/gfpacheco/angular-bulma.svg?branch=master)](https://travis-ci.org/gfpacheco/angular-bulma) | ||
@@ -38,2 +38,64 @@ This is a (WIP) project to bring some interaction to the components of Bulma into the Angular world. | ||
## Components | ||
### Daterangepicker | ||
This component wraps the [bulma-daterangepicker](https://github.com/gfpacheco/bulma-daterangepicker) | ||
package into an Angular directive and is heavily inspired ~~(pretty much copy-pasted)~~ by | ||
[angular-daterangepicker](https://github.com/fragaria/angular-daterangepicker). | ||
```html | ||
<bu-daterangepicker ng-model="myDaterange"/> | ||
``` | ||
> Important! The model must be an Object and have `startDate` and `endDate` properties. | ||
Min and max value can be set via additional attributes: | ||
```html | ||
<bu-daterangepicker ng-model="date" min="'2000-01-01'" max="'2000-01-02'"/> | ||
``` | ||
It can be further customized by passing in the `options` attribute. | ||
```html | ||
<bu-daterangepicker ng-model="date" min="'2000-01-01'" max="'2000-01-02'" options="{separator: ':'}"/> | ||
``` | ||
### Dropdown | ||
Add the `bu-dropdown` class to any tag and the `bu-dropdown-body` to any of its descendants. The | ||
body will be hidden by default and any click on the outer element will make the body visible. After | ||
that any click anywhere inside the document will make the dropdown body to hide again. | ||
```html | ||
<div class="bu-dropdown"> | ||
<div class="button">Dropdown</div> | ||
<div class="bu-dropdown-body"> | ||
<nav class="menu"> | ||
<ul class="menu-list"> | ||
<li><a>Menu item</a></li> | ||
<li><a>Menu item</a></li> | ||
<li><a>Menu item</a></li> | ||
<li><a>Menu item</a></li> | ||
</ul> | ||
</nav> | ||
</div> | ||
</div> | ||
``` | ||
#### Options | ||
`bu-is-right` - Adding this class to the `bu-dropdown-body` element will make it align to the right | ||
side of the `bu-dropdown`. | ||
### Timepicker | ||
As mentioned before, this project will evolve with the need for features. This is a clear example of | ||
a feature implemented as the minimum needed. | ||
```html | ||
<bu-timepicker ng-model="myTime"/> | ||
``` | ||
## Contributing | ||
@@ -40,0 +102,0 @@ |
@@ -7,5 +7,5 @@ (function (angular) { | ||
buDropdown.$inject = ['$document']; | ||
buDropdown.$inject = ['$window', '$document']; | ||
function buDropdown($document) { | ||
function buDropdown($window, $document) { | ||
var directive = { | ||
@@ -30,3 +30,3 @@ restrict: 'C', | ||
event.stopPropagation(); | ||
if (body.css('display') === 'none') { | ||
if ($window.getComputedStyle(body[0], null).display === 'none') { | ||
open(); | ||
@@ -33,0 +33,0 @@ } else { |
@@ -10,2 +10,4 @@ 'use strict'; | ||
var $document; | ||
var element; | ||
var dropdownBody; | ||
@@ -16,6 +18,4 @@ beforeEach(inject(function(_$compile_, _$rootScope_, _$document_) { | ||
$document = _$document_; | ||
})); | ||
function getCompiledElement() { | ||
var element = $compile( | ||
element = $compile( | ||
'<div class="bu-dropdown">' + | ||
@@ -26,10 +26,8 @@ 'Dropdown' + | ||
)($rootScope); | ||
dropdownBody = element.find('.bu-dropdown-body'); | ||
$document.find('body').append(element); | ||
$rootScope.$digest(); | ||
return element; | ||
} | ||
})); | ||
it('Hides the .bu-dropdown-body div by default', function() { | ||
var element = getCompiledElement(); | ||
var dropdownBody = element.find('.bu-dropdown-body'); | ||
expect(dropdownBody.css('display')).to.equal('none'); | ||
@@ -39,4 +37,2 @@ }); | ||
it('Shows the .bu-dropdown-body div when clicked', function() { | ||
var element = getCompiledElement(); | ||
var dropdownBody = element.find('.bu-dropdown-body'); | ||
element.trigger('click'); | ||
@@ -47,4 +43,2 @@ expect(dropdownBody.css('display')).to.equal('block'); | ||
it('Hides the .bu-dropdown-body div if clicked twice', function() { | ||
var element = getCompiledElement(); | ||
var dropdownBody = element.find('.bu-dropdown-body'); | ||
element.trigger('click'); | ||
@@ -56,4 +50,2 @@ element.trigger('click'); | ||
it('Hides the .bu-dropdown-body div if clicked outside', function() { | ||
var element = getCompiledElement(); | ||
var dropdownBody = element.find('.bu-dropdown-body'); | ||
element.trigger('click'); | ||
@@ -65,4 +57,2 @@ $document.trigger('click'); | ||
it('Shows the .bu-dropdown-body div if clicked tree times', function() { | ||
var element = getCompiledElement(); | ||
var dropdownBody = element.find('.bu-dropdown-body'); | ||
element.trigger('click'); | ||
@@ -75,4 +65,2 @@ element.trigger('click'); | ||
it('Aligns the .bu-dropdown-body div to the left by default', function() { | ||
var element = getCompiledElement(); | ||
var dropdownBody = element.find('.bu-dropdown-body'); | ||
expect(dropdownBody.css('left')).to.equal('0px'); | ||
@@ -79,0 +67,0 @@ }); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
50315
28
1206
104
4
+ Addedbulma-daterangepicker@^2.2.0
+ Addedjquery@^1.9.0
+ Addedmoment@^2.14.1
+ Addedbulma@0.1.2(transitive)
+ Addedbulma-daterangepicker@2.2.2(transitive)
+ Addedjquery@1.12.4(transitive)
+ Addedmoment@2.30.1(transitive)
- Removedbulma@0.0.28(transitive)
Updatedbulma@^0.1.2