Skip to content

Commit 3a87b2e

Browse files
committed
Initial commit
0 parents  commit 3a87b2e

8 files changed

Lines changed: 682 additions & 0 deletions

File tree

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
NasExt/SuggestionInput
2+
===========================
3+
4+
SuggestionInput for Nette Framework.
5+
6+
Requirements
7+
------------
8+
9+
NasExt/SuggestionInput requires PHP 5.3.2 or higher.
10+
11+
- [Nette Framework 2.0.x](https://github.com/nette/nette)
12+
13+
Installation
14+
------------
15+
16+
The best way to install NasExt/SuggestionInput is using [Composer](http://getcomposer.org/):
17+
18+
```sh
19+
$ composer require nasext/suggestion-input
20+
```
21+
22+
-----
23+
24+
Repository [http://github.com/nasext/suggestioninput](http://github.com/nasext/suggestioninput).

client-side/suggestionInput.css

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
.suggestion-input{
2+
display: inline-block;
3+
position: relative;
4+
}
5+
6+
.typeahead li{
7+
padding: 0 5px 0 5px;
8+
}
9+
10+
.suggestion-input .active{
11+
color: #ffffff;
12+
text-decoration: none;
13+
background-color: #57544D; /*#0088cc, #0077b3*/
14+
background-image: -moz-linear-gradient(top, #57544D, #57544D);
15+
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#57544D), to(#57544D));
16+
background-image: -webkit-linear-gradient(top, #57544D, #57544D);
17+
background-image: -o-linear-gradient(top, #57544D, #57544D);
18+
background-image: linear-gradient(to bottom, #57544D, #57544D);
19+
background-repeat: repeat-x;
20+
outline: 0;
21+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#57544D', endColorstr='#57544D', GradientType=0);
22+
cursor: pointer;
23+
}

client-side/suggestionInput.js

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
/**
2+
* suggestionInput
3+
* @package suggestionInput
4+
* @copyright Copyright (c) 2012 Dusan Hudak
5+
*/
6+
7+
/**
8+
* Keyboard
9+
*/
10+
function Keyboard() {
11+
this.remove = function (e) {
12+
return e.keyCode == 8;
13+
};
14+
this.enter = function (e) {
15+
return e.keyCode == 13;
16+
};
17+
this.escape = function (e) {
18+
return e.keyCode == 27;
19+
};
20+
this.up = function (e) {
21+
return e.keyCode == 38;
22+
};
23+
this.down = function (e) {
24+
return e.keyCode == 40;
25+
};
26+
this.control = function (e) {
27+
return $.inArray(e.keyCode, [13, 16, 18, 35, 36, 37, 38, 39, 40, 46, 91, 92]) !== -1;
28+
};
29+
this.input = function (e) {
30+
var letter = /^[a-iA-Z\u00C0-\u02A00-9-]+$/; // a-i numpad 1-9, A-Z letters, accented letters, numbers, hyphen
31+
return $.inArray(e.keyCode, [96, 32, 189, 190]) !== -1 // numpad zero, hyphen, point
32+
|| letter.test(this.keyToChar(e.keyCode));
33+
};
34+
this.keyToChar = function (key) {
35+
return String.fromCharCode(key);
36+
};
37+
}
38+
var kb = new Keyboard;
39+
40+
/**
41+
* SuggestionInputControl
42+
*/
43+
function SuggestionInputControl() {
44+
var i = this;
45+
46+
this.options = {
47+
startSuggest: 3,
48+
suggestTimeout: 250,
49+
suggestListClass: 'typeahead dropdown-menu',
50+
suggestListActiveClass: 'active'
51+
};
52+
this.name = undefined;
53+
this.control = undefined;
54+
this.suggestionInputContainer = undefined;
55+
this.suggest = undefined;
56+
this.timeout = null;
57+
58+
59+
/**
60+
* Create link to signal
61+
* @returns string Link to signal
62+
*/
63+
this.getSignalLink = function () {
64+
if (!i.control.data('suggestion-input')) {
65+
return false;
66+
}
67+
return i.control.data('suggestion-input').replace('%25filter%25', i.control.val());
68+
};
69+
70+
71+
/**
72+
* Get suggestion input container
73+
* @returns {XML|parent|*|parent|parent|parent}
74+
*/
75+
this.getSuggestionInputContainer = function () {
76+
return i.control.parent();
77+
};
78+
79+
80+
/**
81+
* Get input form
82+
* @returns {*|parents|parents}
83+
*/
84+
this.getForm = function () {
85+
return i.control.parents('form');
86+
};
87+
88+
89+
/**
90+
* @returns {boolean}
91+
*/
92+
this.onChange = function () {
93+
return false;
94+
};
95+
96+
97+
/**
98+
* @param e
99+
*/
100+
this.onBlur = function (e) {
101+
setTimeout(function () {
102+
i.suggest.hide();
103+
}, 200);
104+
};
105+
106+
107+
/**
108+
* Action suggest
109+
* @param e
110+
*/
111+
this.onSuggest = function (e) {
112+
113+
// reset timeout
114+
if (this.timeout) clearTimeout(this.timeout);
115+
116+
this.timeout = setTimeout(function () {
117+
118+
// If not signal link or press kb.control key then stop suggest
119+
if (!i.getSignalLink() || kb.control(e)) {
120+
return false;
121+
}
122+
123+
// Start suggest only when the value is longer than i.options.startSuggest
124+
// and hide suggestList
125+
if (i.control.val().length < i.options.startSuggest) {
126+
i.suggest.hide();
127+
return false;
128+
}
129+
130+
// Send ajax request
131+
$.ajax(i.getSignalLink(), {
132+
success: function (payload) {
133+
i.suggest.data('init', true);
134+
i.suggest.children().remove();
135+
136+
var showData = payload.use;
137+
if (payload.show) {
138+
showData = payload.show;
139+
}
140+
141+
if (payload.use) {
142+
$.each(payload.use, function (x, v) {
143+
var item = $('<li/>').html(showData[x]);
144+
item.attr('data-value', v);
145+
item.mouseover(function () {
146+
i.suggest.children().removeClass(i.options.suggestListActiveClass);
147+
$(this).addClass(i.options.suggestListActiveClass);
148+
});
149+
item.click(function () {
150+
i.control.val(item.data('value'));
151+
i.suggest.hide();
152+
});
153+
i.suggest.append(item);
154+
});
155+
if (payload.use.length > 0) {
156+
i.suggest.show();
157+
}
158+
}
159+
}
160+
});
161+
162+
}, i.options.suggestTimeout);
163+
};
164+
165+
166+
/**
167+
*
168+
* @param e
169+
* @returns {boolean}
170+
*/
171+
this.onKeyDown = function (e) {
172+
if (kb.input(e)) {
173+
// if write
174+
}
175+
else if (kb.enter(e) && i.suggest.is(':visible') && i.suggest.children('.' + i.options.suggestListActiveClass).text().length > 0) {
176+
var selected = i.suggest.children('.' + i.options.suggestListActiveClass);
177+
selected.click();
178+
return false;
179+
}
180+
else if (kb.down(e) && i.suggest.is(':visible')) {
181+
var selected = i.suggest.children('.' + i.options.suggestListActiveClass);
182+
if (!selected.length) {
183+
var item = i.suggest.children(':first-child').addClass(i.options.suggestListActiveClass);
184+
i.control.val(item.data('value'));
185+
} else if (selected.next().length) {
186+
selected.removeClass(i.options.suggestListActiveClass);
187+
var item = selected.next().addClass(i.options.suggestListActiveClass);
188+
i.control.val(item.data('value'));
189+
}
190+
return false;
191+
} else if (kb.up(e) && i.suggest.is(':visible')) {
192+
var selected = i.suggest.children('.' + i.options.suggestListActiveClass);
193+
if (selected.prev().length) {
194+
selected.removeClass(i.options.suggestListActiveClass);
195+
var item = selected.prev().addClass(i.options.suggestListActiveClass);
196+
i.control.val(item.data('value'));
197+
} else {
198+
i.suggest.hide();
199+
}
200+
return false;
201+
}
202+
else if (kb.down(e) && !i.suggest.is(':visible')) {
203+
if (i.suggest.children().length > 0) {
204+
i.suggest.show();
205+
}
206+
return false;
207+
}
208+
else if (kb.escape(e)) {
209+
i.control.val('');
210+
i.suggest.hide();
211+
i.suggest.children().remove();
212+
return false;
213+
}
214+
else if (kb.remove(e)) {
215+
// if delete
216+
}
217+
else if (!kb.control(e)) {
218+
// if kb is not in control
219+
}
220+
};
221+
}
222+
223+
224+
/**
225+
* SuggestionInput
226+
*/
227+
var SuggestionInput = SuggestionInput || {
228+
inputs: []
229+
};
230+
231+
/**
232+
*
233+
* @param {string} controlId
234+
* @param {object} options
235+
*/
236+
SuggestionInput.create = function (controlId, options) {
237+
var input = new SuggestionInputControl;
238+
239+
input.options = $.extend({}, input.options, options);
240+
input.name = controlId;
241+
input.control = $('#' + input.name);
242+
input.suggestionInputContainer = input.getSuggestionInputContainer();
243+
244+
if (input.getSignalLink()) {
245+
input.suggest = $('<ul/>').addClass(input.options.suggestListClass);
246+
247+
var width = input.control.innerWidth();
248+
input.suggest.css({
249+
minWidth: width + "px"
250+
});
251+
input.control.css({
252+
marginBottom: "0px"
253+
});
254+
255+
input.suggestionInputContainer.append(input.suggest);
256+
input.suggest.hide();
257+
}
258+
259+
input.control.keydown(input.onKeyDown);
260+
input.control.keyup(input.onSuggest);
261+
input.control.bind('cut change', input.onChange);
262+
input.control.blur(input.onBlur);
263+
264+
this.inputs.push(input);
265+
};

composer.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "nasext/suggestion-input",
3+
"type": "library",
4+
"description": "SuggestionInput for Nette Framework",
5+
"keywords": ["nette", "nasext", "SuggestionInput"],
6+
"license": ["MIT"],
7+
"authors": [
8+
{
9+
"name": "Dusan Hudak"
10+
}
11+
],
12+
"require": {
13+
"php": ">=5.3.0",
14+
"nette/nette": "@dev"
15+
},
16+
"autoload": {
17+
"psr-0": {
18+
"NasExt\\Forms\\Controls\\": "src/"
19+
}
20+
}
21+
}

0 commit comments

Comments
 (0)