-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathslideInput.js
More file actions
157 lines (137 loc) · 6.08 KB
/
Copy pathslideInput.js
File metadata and controls
157 lines (137 loc) · 6.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
(function() {
"use strict";
//handles negative value correctly
Math.mod = function(value, modder){
if(value < 0){
var loops = (-value)/modder;
return (value + parseInt(loops+1)*modder) % modder;
} else return value % modder;
};
angular.module("slideInput", ['ngSanitize'])
.directive('slideInput', SlideInputDirective)
.service('SlideInputFormatter', SlideInputFormatter);
SlideInputDirective.$inject = ['$timeout'];
function SlideInputDirective($timeout){
return {
/* for some odd reason angular doesn't like type="email" */
restrict: 'E',
template: "<div class='slideInput' ng-class='{focus:focus, hasValue:model.length > 0}'>" +
"<div class='slideInput-box'>" +
"<input type='text' class='slideInput-input suggest' placeholder='{{suggested}}' disabled />" +
"<input type='text' class='slideInput-input' placeholder='{{placeholder}}' ng-model='model' ng-focus='focus=true' ng-blur='focus=false' ng-keyup='_keyup($event)' ng-keydown='_keydown($event)' ng-change='_change()'/>" +
"<button class='slideInput-button' ng-show='button' ng-click='_click()'>{{button}}</button>" +
"</div>" +
"<div class='slideInput-typeahead'>" +
"<div class='slideInput-typeaheadItem' ng-class='{\"slideInput-typeaheadItem-active\":typeaheadHoverIndex == ($index+1)}' ng-repeat='item in typeaheadData track by (item.id || $id(item))' ng-bind-html='typeaheadFormat({item:item, query:model})' ng-click='_typeaheadClick(item)' ng-mouseover='_mouseover(item)' ng-mouseleave='_mouseleave(item)'></div>" +
"</div>" +
"<div class='slideInput-emptyTypeahead' ng-show='empty && (typeaheadData == null || typeaheadData.length == 0) && model.length > 1'><div class='slideInput-emptyTypeaheadText'>{{empty}}</div></div>" +
"</div>",
require: 'ngModel',
scope: {
button: "@",
placeholder: "@",
model: '=ngModel',
change: '&',
click: '&',
focus: '=?',
typeaheadData: '=?',
typeaheadFormat: '&',
typeaheadHoverItem: '&',
typeaheadActiveItem:'&',
suggestedFormat: '&',
empty:'@'
},
link: function($scope, element, attrs, ctrl) {
$scope.typeaheadHoverIndex = 0;
$scope.$watch("focus", function(value){
if(value === true) {
element.find('input')[1].focus();
}
});
$scope.updateSuggested = function(){
if($scope.typeaheadHoverIndex > 0 && $scope.typeaheadData && $scope.typeaheadHoverIndex - 1 < $scope.typeaheadData.length){
var item = $scope.typeaheadData[$scope.typeaheadHoverIndex - 1];
$scope.suggested = $scope.suggestedFormat({item: item, query:$scope.model});
$scope.typeaheadActiveItem({item: item});
} else {
$scope.suggested = null;
$scope.typeaheadActiveItem({item: null});
}
};
$scope._keydown = function($event){
if($event.keyCode == 13 || $event.keyCode == 40 || $event.keyCode == 38) {
$event.preventDefault();
return false;
}
};
$scope._click = function($event) {
var item = null;
if($scope.typeaheadHoverIndex > 0 && $scope.typeaheadData && $scope.typeaheadHoverIndex - 1 < $scope.typeaheadData.length){
item = $scope.typeaheadData[$scope.typeaheadHoverIndex - 1];
}
$scope.click({item:item, value:$scope.model});
};
$scope._typeaheadClick = function(item){
$scope.click({item:item, value:$scope.model});
};
$scope._keyup = function($event) {
if($event.keyCode == 13) { //enter
$scope._click();
$event.preventDefault();
return false;
} else if($event.keyCode == 40) { //down
var length = 1;
if($scope.typeaheadData && $scope.typeaheadData.length > 0) length = $scope.typeaheadData.length + 1;
$scope.typeaheadHoverIndex = Math.mod($scope.typeaheadHoverIndex + 1, length);
$scope.updateSuggested();
$event.preventDefault();
return false;
} else if($event.keyCode == 38) { //up
var length = 1;
if($scope.typeaheadData && $scope.typeaheadData.length > 0) length = $scope.typeaheadData.length + 1;
$scope.typeaheadHoverIndex = Math.mod($scope.typeaheadHoverIndex - 1, length);
$scope.updateSuggested();
$event.preventDefault();
return false;
}
};
$scope._change = function(){
$scope.typeaheadHoverIndex = 0;
$scope.change({model:$scope.model});
$scope.updateSuggested();
$scope.typeaheadHoverItem({item: null});
};
$scope._mouseover = function(item){
$scope.typeaheadHoverItem({item: item});
};
$scope._mouseleave = function(item){
$scope.typeaheadHoverItem({item: null});
}
}
}
}
function SlideInputFormatter(){
//(value:String, query:String, tag:String) -> :Html
this.injectBold = function(value, query, tag){
if(tag == null) tag = "b";
var splitValue = value.toLowerCase().split(query.toLowerCase());
var withBold = [];
var startingIndex = 0;
for(var i=0; i<splitValue.length; i++){
var originalValue = value.slice(startingIndex, startingIndex + splitValue[i].length);
var queryValueAtLocation = value.slice(startingIndex + splitValue[i].length, startingIndex + splitValue[i].length + query.length);
startingIndex += splitValue[i].length + query.length;
withBold.push(originalValue);
if(i < splitValue.length - 1){
withBold.push("<"+tag+">" + queryValueAtLocation + "</"+tag+">");
}
}
return withBold.join("");
};
//(value:String, query:String) -> :String
this.afterFirstOccurence = function(value, query) {
var index = value.toLowerCase().indexOf(query.toLowerCase());
return query + value.slice(index + query.length, value.length);
}
}
})();