app.directive('Daypart', ['$window', '$document', '$timeout', function ($window, $document, $timeout) { return { restrict: 'E', scope: { options: '=?' }, templateUrl: 'template.html', controller: ['$scope', '$element', '$attrs', function($scope, $element, $attrs) { console.log($scope) $scope.options = $scope.options || {}; $scope.options.reset = ($scope.options.reset === undefined) ? true : $scope.options.reset; $scope.year = new Date().getFullYear(); $scope.days = [{name:'星期一', position: 1}, {name:'星期二', position: 2}, {name:'星期三', position: 3}, {name: '星期四', position: 4}, {name: '星期五', position: 5}, {name: '星期六', position: 6}, {name: '星期日', position: 7}]; //$scope.days = [{name: 'monday', position: 1}, {name: 'tuesday', position: 2}, {name: 'wednesday', position: 3}, {name: 'thursday', position: 4}, {name: 'friday', position: 5}, {name: 'saturday', position: 6}, {name: 'sunday', position: 7}]; $scope.weekdays = [1,2,3,4,5,6,7]; var klass = 'active'; var startCell = null; var isDragging = false; var selected = []; var isStartSelected = false; if ($scope.options.selected) { $timeout(function(){ repopulate($scope.options.selected); }, 100); } /** * When user stop clicking make the callback with selected elements */ function mouseUp() { if (!isDragging) { return; } isDragging = false; onChangeCallback(); } /** * Call 'onChange' function from passed options */ function onChangeCallback () { if ($scope.options && $scope.options.onChange) { // Sort by day name and time var sortedSelected = []; selected.forEach(function(item){ var el = item.split('-'); var o = {year: el[0], time: parseInt(el[1])}; sortedSelected.push(o); }); sortedSelected = _.sortBy(sortedSelected, function(item){ return item.time; }); selected = sortedSelected.map(function(item){ return item.year + '-' + item.time; }) $scope.options.onChange(selected); } } /** * User start to click * @param {jQuery DOM element} */ function mouseDown(el) { isDragging = true; setStartCell(el); setEndCell(el); } /** * User enter in a cell still triggering click * @param {jQuery DOM element} */ function mouseEnter(el) { if (!isDragging) { return; } setEndCell(el); } /** * Get the first cell clicked * @param {jQuery DOM element} */ function setStartCell(el) { startCell = el; isStartSelected = _.contains(selected, el.data('time')); } /** * Get the last cell * @param {jQuery DOM element} */ function setEndCell(el) { cellsBetween(startCell, el).each(function() { var el = angular.element(this); if (!isStartSelected) { if (!_.contains(selected, el.data('time'))) { _addCell($(el)); } } else { _removeCell(el); } }); } /** * Get all the cells between first and last * @param {jQuery DOM element} start cell * @param {jQuery DOM element} end cell * @return {jQuery DOM elements} cells between start and end */ function cellsBetween(start, end) { var coordsStart = getCoords(start); var coordsEnd = getCoords(end); var topLeft = { column: $window.Math.min(coordsStart.column, coordsEnd.column), row: $window.Math.min(coordsStart.row, coordsEnd.row), }; var bottomRight = { column: $window.Math.max(coordsStart.column, coordsEnd.column), row: $window.Math.max(coordsStart.row, coordsEnd.row), }; return $element.find('div.weekday').filter(function() { var el = angular.element(this); var coords = getCoords(el); return coords.column >= topLeft.column && coords.column <= bottomRight.column && coords.row >= topLeft.row && coords.row <= bottomRight.row; }); } /** * Get the coordinates of a given cell * @param {jQuery DOM element} * @return {object} */ function getCoords(cell) { //var row = cell.parents('layout-row'); // return { // column: cell[0].cellIndex, // row: cell.parent()[0].rowIndex // }; return { column: cell.data("cellindex")+0, row: 0 }; } /** * Passing 'selected' property will make repopulate table */ function repopulate () { selected = _.clone($scope.options.selected); $element.find('div.weekday').each(function(i, el){ if (_.contains(selected, $(el).data('time'))) { $(el).addClass(klass); } }); } /** * Clicking on a day will select all hours * @param {object} day.name, day.position */ $scope.selectDay = function(day) { var numSelectedHours = selected.filter(function(item){ return item.split('-')[0] === day.name; }).length; $element.find('table tr:eq(' + day.position + ') td:not(:last-child)').each(function(i, el) { if (numSelectedHours === 24) { _removeCell($(el)); } else if (!_.contains(selected, $(el).data('time'))) { _addCell($(el)); } }); onChangeCallback(); }; /** * Clicking on a hour will select all days at that hour * @param {int} */ $scope.selectHour = function(hour) { var hour = hour - 1; // previous selected hour var numSelectedDays = $scope.days.filter(function(item){ return _.contains(selected, item.name + '-' + hour); }).length; $scope.days.forEach(function(day, i){ $element.find('table tr:eq(' + (i + 1) + ') td:eq(' + hour + ')').each(function(i, el) { if (numSelectedDays === 7) { _removeCell($(el)); } else if (!_.contains(selected, $(el).data('time'))) { _addCell($(el)); } }); }); onChangeCallback(); }; /** * Remove all selected hours */ $scope.reset = function () { selected = []; $element.find('td').each(function(i, el){ $(el).removeClass(klass); }); onChangeCallback(); }; /** * Remove css class from table and element from selected array * @param {jQuery DOM element} cell */ function _removeCell (el) { el.removeClass(klass); selected = _.without(selected, el.data('time')); } /** * Add css class to table and element to selected array * @param {jQuery DOM element} cell */ function _addCell (el) { el.addClass(klass); selected.push(el.data('time')); } function wrap(fn) { return function() { var el = angular.element(this); $scope.$apply(function() { fn(el); }); } } /** * Mouse events */ $element.delegate('div.weekday', 'mousedown', wrap(mouseDown)); //$element.delegate('div.weekday', 'mouseenter', wrap(mouseEnter)); $document.delegate('body', 'mouseup', wrap(mouseUp)); }] } }]); app.run(['$templateCache', function($templateCache) { $templateCache.put('template.html', '\n' + '\n' + '\n' + '
\n' + ' |