This repository has been archived on 2020-03-24. You can view files and clone it, but cannot push or open issues or pull requests.
quay/static/js/directives/ui/dropdown-select.js
Joseph Schorr 6479f8ddc9 Work In Progress!
Get the full activation and deactivation cycle working for bitbucket.
2015-04-28 18:15:12 -04:00

175 lines
5 KiB
JavaScript

/**
* An element which displays a dropdown select box which is (optionally) editable. This box
* is displayed with an <input> and a menu on the right.
*/
angular.module('quay').directive('dropdownSelect', function ($compile) {
var directiveDefinitionObject = {
priority: 0,
templateUrl: '/static/directives/dropdown-select.html',
replace: true,
transclude: true,
restrict: 'C',
scope: {
'selectedItem': '=selectedItem',
'placeholder': '=placeholder',
'lookaheadItems': '=lookaheadItems',
'hideDropdown': '=hideDropdown',
'allowCustomInput': '@allowCustomInput',
'handleItemSelected': '&handleItemSelected',
'handleInput': '&handleInput',
'clearValue': '=clearValue'
},
controller: function($scope, $element, $rootScope) {
if (!$rootScope.__dropdownSelectCounter) {
$rootScope.__dropdownSelectCounter = 1;
}
$scope.placeholder = $scope.placeholder || '';
$scope.internalItem = null;
// Setup lookahead.
var input = $($element).find('.lookahead-input');
$scope.$watch('clearValue', function(cv) {
if (cv) {
$scope.selectedItem = null;
$(input).val('');
}
});
$scope.$watch('selectedItem', function(item) {
if ($scope.selectedItem == $scope.internalItem) {
// The item has already been set due to an internal action.
return;
}
if ($scope.selectedItem != null) {
$(input).val(item.toString());
} else {
$(input).val('');
}
});
$scope.$watch('lookaheadItems', function(items) {
$(input).off();
if (!items) {
return;
}
var formattedItems = [];
for (var i = 0; i < items.length; ++i) {
var formattedItem = items[i];
if (typeof formattedItem == 'string') {
formattedItem = {
'value': formattedItem
};
}
formattedItems.push(formattedItem);
}
var dropdownHound = new Bloodhound({
name: 'dropdown-items-' + $rootScope.__dropdownSelectCounter,
local: formattedItems,
datumTokenizer: function(d) {
return Bloodhound.tokenizers.whitespace(d.val || d.value || '');
},
queryTokenizer: Bloodhound.tokenizers.whitespace
});
dropdownHound.initialize();
$(input).typeahead({}, {
source: dropdownHound.ttAdapter(),
templates: {
'suggestion': function (datum) {
template = datum['template'] ? datum['template'](datum) : datum['value'];
return template;
}
}
});
$(input).on('input', function(e) {
$scope.$apply(function() {
$scope.internalItem = null;
$scope.selectedItem = null;
if ($scope.handleInput) {
$scope.handleInput({'input': $(input).val()});
}
});
});
$(input).on('typeahead:selected', function(e, datum) {
$scope.$apply(function() {
$scope.internalItem = datum['item'] || datum['value'];
$scope.selectedItem = datum['item'] || datum['value'];
if ($scope.handleItemSelected) {
$scope.handleItemSelected({'datum': datum});
}
});
});
$rootScope.__dropdownSelectCounter++;
});
},
link: function(scope, element, attrs) {
var transcludedBlock = element.find('div.transcluded');
var transcludedElements = transcludedBlock.children();
var iconContainer = element.find('div.dropdown-select-icon-transclude');
var menuContainer = element.find('div.dropdown-select-menu-transclude');
angular.forEach(transcludedElements, function(elem) {
if (angular.element(elem).hasClass('dropdown-select-icon')) {
iconContainer.append(elem);
} else if (angular.element(elem).hasClass('dropdown-select-menu')) {
menuContainer.replaceWith(elem);
}
});
transcludedBlock.remove();
}
};
return directiveDefinitionObject;
});
/**
* An icon in the dropdown select. Only one icon will be displayed at a time.
*/
angular.module('quay').directive('dropdownSelectIcon', function () {
var directiveDefinitionObject = {
priority: 1,
require: '^dropdownSelect',
templateUrl: '/static/directives/dropdown-select-icon.html',
replace: false,
transclude: false,
restrict: 'C',
scope: {
},
controller: function($scope, $element) {
}
};
return directiveDefinitionObject;
});
/**
* The menu for the dropdown select.
*/
angular.module('quay').directive('dropdownSelectMenu', function () {
var directiveDefinitionObject = {
priority: 1,
require: '^dropdownSelect',
templateUrl: '/static/directives/dropdown-select-menu.html',
replace: true,
transclude: true,
restrict: 'C',
scope: {
},
controller: function($scope, $element) {
}
};
return directiveDefinitionObject;
});