Fixes: U4-4503 Tags datatype does not autocomplete

This commit is contained in:
Shannon
2014-05-06 14:44:24 +10:00
parent 6827def8ba
commit 683f0c5725
5 changed files with 128 additions and 36 deletions

View File

@@ -34,7 +34,7 @@ module.exports = function (grunt) {
var bower = require('bower');
var done = this.async();
bower.commands.install(undefined, { offline: true }, { interactive: false, offline: true })
bower.commands.install(undefined, { }, { interactive: false })
.on('log', function (data) {
grunt.log.write(data.message + "\n");
})

View File

@@ -82,4 +82,5 @@
//used for property editors
@import "property-editors.less";
@import "typeahead.less";
@import "hacks.less";

View File

@@ -0,0 +1,65 @@
.typeahead,
.tt-query,
.tt-hint {
z-index: auto !important;
margin-top:-4px !important;
width: 396px;
height: 30px;
padding: 8px 12px;
font-size: 24px;
line-height: 30px;
border: 2px solid @grayLight;
-webkit-border-radius: 2px !important;
-moz-border-radius: 2px !important;
border-radius: 2px !important;
outline: none;
}
.typeahead {
background-color: #fff;
}
.typeahead:focus {
/*border: 2px solid @blue;*/
}
.tt-query {
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
}
.tt-hint {
color: @grayLight !important;
}
.tt-dropdown-menu {
width: 422px;
margin-top: 12px;
padding: 8px 0;
background-color: #fff;
border: 1px solid @grayLight;
border: 1px solid rgba(0, 0, 0, 0.2);
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
-webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
-moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
box-shadow: 0 5px 10px rgba(0,0,0,.2);
}
.tt-suggestion {
padding: 3px 20px;
font-size: @baseFontSize;
line-height: @baseLineHeight;
cursor:pointer;
}
.tt-suggestion.tt-cursor {
color: #fff;
background-color: @blue;
}
.tt-suggestion p {
margin: 0;
}

View File

@@ -1,31 +1,40 @@
angular.module("umbraco")
.controller("Umbraco.PropertyEditors.TagsController",
function ($rootScope, $scope, $log, assetsService, umbRequestHelper) {
function ($rootScope, $scope, $log, assetsService, umbRequestHelper, angularHelper, $timeout) {
//load current value
$scope.currentTags = [];
if ($scope.model.value) {
$scope.currentTags = $scope.model.value.split(",");
}
//Helper method to add a tag on enter or on typeahead select
function addTag(tagToAdd) {
if (tagToAdd.length > 0) {
if ($scope.currentTags.indexOf(tagToAdd) < 0) {
$scope.currentTags.push(tagToAdd);
}
}
}
$scope.addTag = function (e) {
var code = e.keyCode || e.which;
if (code == 13) { //Enter keycode
//this is required, otherwise the html form will attempt to submit.
e.preventDefault();
if ($scope.currentTags.indexOf($scope.tagToAdd) < 0) {
$scope.currentTags.push($scope.tagToAdd);
if ($('#tags-Tags').parent().find(".tt-dropdown-menu .tt-cursor").length === 0) {
//this is required, otherwise the html form will attempt to submit.
e.preventDefault();
addTag($scope.tagToAdd);
$scope.tagToAdd = "";
}
$scope.tagToAdd = "";
}
};
$scope.removeTag = function (tag) {
var i = $scope.currentTags.indexOf(tag);
if (i >= 0) {
$scope.currentTags.splice(i, 1);
$scope.currentTags.splice(i, 1);
}
};
@@ -42,55 +51,71 @@ angular.module("umbraco")
};
assetsService.loadJs("lib/typeahead/typeahead.bundle.min.js").then(function () {
//configure the tags data source
//TODO: We'd like to be able to filter the shown list items to not show the tags that are currently
// selected but that is difficult, i've tried a number of things and also this link suggests we cannot do
// it currently without a lot of hacking:
// http://stackoverflow.com/questions/21044906/twitter-typeahead-js-remove-datum-upon-selection
//helper method to format the data for bloodhound
function dataTransform(list) {
//transform the result to what bloodhound wants
return _.map(list, function (i) {
return { value: i.text };
});
}
var tagsHound = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace("value"),
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
dupDetector : function(remoteMatch, localMatch) {
return (remoteMatch["value"] == localMatch["value"]);
},
//pre-fetch the tags for this category
prefetch: {
url: umbRequestHelper.getApiUrl("tagsDataBaseUrl", "GetTags", [{ tagGroup: $scope.model.config.group }]),
//TTL = 5 minutes
ttl: 300000,
filter: function (list) {
return _.map(list, function (i) {
return { value: i.text };
});
}
filter: dataTransform
},
//dynamically get the tags for this category
//dynamically get the tags for this category (they may have changed on the server)
remote: {
url: umbRequestHelper.getApiUrl("tagsDataBaseUrl", "GetTags", [{ tagGroup: $scope.model.config.group }]),
filter: function (list) {
return _.map(list, function (i) {
return { value: i.text };
});
}
filter: dataTransform
}
});
tagsHound.initialize();
//configure the type ahead
$('#tags-' + $scope.model.alias).typeahead(
$timeout(function() {
$('#tags-' + $scope.model.alias).typeahead(
//use the default options
null, {
//see: https://github.com/twitter/typeahead.js/blob/master/doc/jquery_typeahead.md#options
// name = the data set name, we'll make this the tag group name
name: $scope.model.config.group,
// apparently thsi should be the same as the value above in the call to Bloodhound.tokenizers.obj.whitespace
// this isn't very clear in the docs but you can see that it's consistent with this statement here:
// http://twitter.github.io/typeahead.js/examples/
displayKey: "value",
source: tagsHound.ttAdapter()
//see: https://github.com/twitter/typeahead.js/blob/master/doc/jquery_typeahead.md#options
// name = the data set name, we'll make this the tag group name
name: $scope.model.config.group,
displayKey: "value",
source: tagsHound.ttAdapter(),
highlight: true,
hint: true
}).bind("typeahead:selected", function (obj, datum, name) {
angularHelper.safeApply($scope, function () {
addTag(datum["value"]);
$scope.tagToAdd = "";
});
});
});
$scope.$on('$destroy', function () {
$('#tags-' + $scope.model.alias).typeahead('destroy');
delete tagsHound;
});
});
//on destroy:
// $('.typeahead').typeahead('destroy');
}
);

View File

@@ -4,6 +4,7 @@
<input type="text"
id="tags-{{model.alias}}"
class="typeahead"
ng-keydown="addTag($event)"
placeholder="Type to add tags.."
ng-model="tagToAdd" />