blob: 6e02793d1219d58f20ffc3c68c27b8105bb9681a [file] [log] [blame]
Nils Diewald0e6992a2015-04-14 20:13:52 +00001// Input field for queries
Akron308db382016-05-30 22:34:07 +02002/*
3 * TODO: Support allert for query problems.
4 */
5
Nils Diewald0e6992a2015-04-14 20:13:52 +00006define({
Nils Diewald7148c6f2015-05-04 15:07:53 +00007
8 /**
9 * Create a new input field.
10 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000011 create : function (element) {
12 return Object.create(this)._init(element);
13 },
Nils Diewald0e6992a2015-04-14 20:13:52 +000014
Nils Diewald0e6992a2015-04-14 20:13:52 +000015
Nils Diewald7148c6f2015-05-04 15:07:53 +000016 /**
17 * Get the mirrored input field.
18 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000019 mirror : function () {
20 return this._mirror;
21 },
22
Nils Diewald7148c6f2015-05-04 15:07:53 +000023
24 /**
25 * Get the container element.
Akron308db382016-05-30 22:34:07 +020026 * This contains the hint helper / menus
27 * and probably an
28 * error message.
Nils Diewald7148c6f2015-05-04 15:07:53 +000029 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000030 container : function () {
31 return this._container;
32 },
33
Nils Diewald7148c6f2015-05-04 15:07:53 +000034
35 /**
36 * Get the input element the
37 * hint helper is attached to.
38 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000039 element : function () {
40 return this._element;
41 },
42
Akron308db382016-05-30 22:34:07 +020043
Nils Diewald7148c6f2015-05-04 15:07:53 +000044 /**
45 * Get the value of the input field
46 * the hint helper is attached to.
47 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000048 value : function () {
49 return this._element.value;
50 },
51
Nils Diewald7148c6f2015-05-04 15:07:53 +000052
53 /**
54 * Update the mirror content.
55 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000056 update : function () {
Nils Diewald7148c6f2015-05-04 15:07:53 +000057 this._mirror.firstChild.textContent = this._split()[0];
58 this._container.style.left = this._rightPos() + 'px';
Akron308db382016-05-30 22:34:07 +020059 return this;
Nils Diewald0e6992a2015-04-14 20:13:52 +000060 },
61
Akron308db382016-05-30 22:34:07 +020062
Nils Diewald7148c6f2015-05-04 15:07:53 +000063 /**
64 * Insert text into the mirror.
65 * This is a prefix of the input field's
66 * value.
67 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000068 insert : function (text) {
Nils Diewald7148c6f2015-05-04 15:07:53 +000069 var splittedText = this._split();
Nils Diewald0e6992a2015-04-14 20:13:52 +000070 var s = this._element;
71 s.value = splittedText[0] + text + splittedText[1];
72 s.selectionStart = (splittedText[0] + text).length;
73 s.selectionEnd = s.selectionStart;
Akron308db382016-05-30 22:34:07 +020074
75 // Maybe update?
Nils Diewald0e6992a2015-04-14 20:13:52 +000076 this._mirror.firstChild.textContent = splittedText[0] + text;
Akron308db382016-05-30 22:34:07 +020077 return this;
Nils Diewald0e6992a2015-04-14 20:13:52 +000078 },
Akron308db382016-05-30 22:34:07 +020079
80 /**
81 * Move hinthelper to given character position
82 */
83 moveto : function (charpos) {
84 this._element.selectionStart = charpos;
85 this._element.selectionEnd = charpos;
86 this._element.focus();
87 return this.update();
88 },
Nils Diewald0e6992a2015-04-14 20:13:52 +000089
Nils Diewald7148c6f2015-05-04 15:07:53 +000090 /**
91 * Reposition the input mirror directly
92 * below the input box.
93 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000094 reposition : function () {
95 var inputClientRect = this._element.getBoundingClientRect();
96 var inputStyle = window.getComputedStyle(this._element, null);
97
98 var bodyClientRect =
99 document.getElementsByTagName('body')[0].getBoundingClientRect();
100
101 // Reset position
102 var mirrorStyle = this._mirror.style;
103 mirrorStyle.left = inputClientRect.left + "px";
104 mirrorStyle.top = (inputClientRect.bottom - bodyClientRect.top) + "px";
105 mirrorStyle.width = inputStyle.getPropertyValue("width");
106
107 // These may be relevant in case of media depending css
108 mirrorStyle.paddingLeft = inputStyle.getPropertyValue("padding-left");
109 mirrorStyle.marginLeft = inputStyle.getPropertyValue("margin-left");
110 mirrorStyle.borderLeftWidth = inputStyle.getPropertyValue("border-left-width");
111 mirrorStyle.borderLeftStyle = inputStyle.getPropertyValue("border-left-style");
112 mirrorStyle.fontSize = inputStyle.getPropertyValue("font-size");
113 mirrorStyle.fontFamily = inputStyle.getPropertyValue("font-family");
114 },
Nils Diewald7148c6f2015-05-04 15:07:53 +0000115
Akron308db382016-05-30 22:34:07 +0200116
Nils Diewald7148c6f2015-05-04 15:07:53 +0000117 /**
118 * Get the context, which is the input
119 * field's value bounded to the
120 * cursor position.
121 */
Nils Diewald0e6992a2015-04-14 20:13:52 +0000122 context : function () {
Nils Diewald7148c6f2015-05-04 15:07:53 +0000123 return this._split()[0];
124 },
125
Akron308db382016-05-30 22:34:07 +0200126
127 // Initialize new input field
128 _init : function (element) {
129 this._element = element;
130
131 // Create mirror for searchField
132 // This is important for positioning
133 if ((this._mirror = document.getElementById("searchMirror")) === null) {
134 this._mirror = document.createElement("div");
135 this._mirror.setAttribute("id", "searchMirror");
136 this._mirror.appendChild(document.createElement("span"));
137 this._container = this._mirror.appendChild(document.createElement("div"));
138 this._mirror.style.height = "0px";
139 document.getElementsByTagName("body")[0].appendChild(this._mirror);
140 };
141
142 // Update position of the mirror
143 window.addEventListener('resize', this.reposition.bind(this));
144 this._element.addEventListener('onfocus', this.reposition.bind(this));
145 this.reposition();
146 return this;
147 },
148
149 // Get the right position
150 _rightPos : function () {
151 var box = this._mirror.firstChild.getBoundingClientRect();
152 return box.right - box.left;
153 },
154
155
Nils Diewald7148c6f2015-05-04 15:07:53 +0000156 /*
157 * Return two substrings,
Akron308db382016-05-30 22:34:07 +0200158 * splitted at a given position
159 * or at the current cursor position.
Nils Diewald7148c6f2015-05-04 15:07:53 +0000160 */
Akron308db382016-05-30 22:34:07 +0200161 _split : function (start) {
Nils Diewald7148c6f2015-05-04 15:07:53 +0000162 var s = this._element;
163 var value = s.value;
Akron308db382016-05-30 22:34:07 +0200164
165 // Get start from cursor position
166 if (arguments.length === 0)
167 start = s.selectionStart;
168
Nils Diewald7148c6f2015-05-04 15:07:53 +0000169 return new Array(
170 value.substring(0, start),
171 value.substring(start, value.length)
172 );
Nils Diewald0e6992a2015-04-14 20:13:52 +0000173 }
174});