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 - i A - Z \u00C0 - \u02A0 0 - 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+ } ;
0 commit comments