aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorArthurHoaro <arthur@hoa.ro>2016-06-07 16:12:12 +0200
committerArthurHoaro <arthur@hoa.ro>2016-08-07 12:17:36 +0200
commitf791ba634e733811b3e10bb662e30cd5ba0b29e3 (patch)
tree7e76730965d3544bac2dcca460ea729273df8d7b
parent09d6e7e0503535f64f374f570037b0dbff09be7b (diff)
downloadShaarli-f791ba634e733811b3e10bb662e30cd5ba0b29e3.tar.gz
Shaarli-f791ba634e733811b3e10bb662e30cd5ba0b29e3.tar.zst
Shaarli-f791ba634e733811b3e10bb662e30cd5ba0b29e3.zip
Edit link WIP + upgrade awesomplete
-rw-r--r--inc/awesomplete-multiple-tags.js21
-rw-r--r--inc/awesomplete.js759
-rw-r--r--inc/awesomplete.min.js20
-rw-r--r--plugins/markdown/markdown.css4
-rw-r--r--tpl/default/editlink.html82
5 files changed, 510 insertions, 376 deletions
diff --git a/inc/awesomplete-multiple-tags.js b/inc/awesomplete-multiple-tags.js
index 4cc8429f..faecb417 100644
--- a/inc/awesomplete-multiple-tags.js
+++ b/inc/awesomplete-multiple-tags.js
@@ -1,13 +1,16 @@
1var awp = Awesomplete.$; 1var awp = Awesomplete.$;
2awesomplete = new Awesomplete(awp('input[data-multiple]'), { 2var autocompleteFields = document.querySelectorAll('input[data-multiple]');
3 filter: function(text, input) { 3[].forEach.call(autocompleteFields, function(autocompleteField) {
4 return Awesomplete.FILTER_CONTAINS(text, input.match(/[^ ]*$/)[0]); 4 awesomplete = new Awesomplete(awp(autocompleteField), {
5 }, 5 filter: function (text, input) {
6 replace: function(text) { 6 return Awesomplete.FILTER_CONTAINS(text, input.match(/[^ ]*$/)[0]);
7 var before = this.input.value.match(/^.+ \s*|/)[0]; 7 },
8 this.input.value = before + text + " "; 8 replace: function (text) {
9 }, 9 var before = this.input.value.match(/^.+ \s*|/)[0];
10 minChars: 1 10 this.input.value = before + text + " ";
11 },
12 minChars: 1
13 })
11}); 14});
12 15
13/** 16/**
diff --git a/inc/awesomplete.js b/inc/awesomplete.js
index fae550e2..7303652a 100644
--- a/inc/awesomplete.js
+++ b/inc/awesomplete.js
@@ -7,382 +7,433 @@
7 7
8(function () { 8(function () {
9 9
10 var _ = function (input, o) { 10var _ = function (input, o) {
11 var me = this; 11 var me = this;
12 12
13 // Setup 13 // Setup
14 14
15 this.input = $(input); 15 this.input = $(input);
16 this.input.setAttribute("aria-autocomplete", "list"); 16 this.input.setAttribute("autocomplete", "off");
17 17 this.input.setAttribute("aria-autocomplete", "list");
18 o = o || {}; 18
19 19 o = o || {};
20 configure.call(this, { 20
21 minChars: 2, 21 configure(this, {
22 maxItems: 10, 22 minChars: 2,
23 autoFirst: false, 23 maxItems: 10,
24 filter: _.FILTER_CONTAINS, 24 autoFirst: false,
25 sort: _.SORT_BYLENGTH, 25 data: _.DATA,
26 item: function (text, input) { 26 filter: _.FILTER_CONTAINS,
27 return $.create("li", { 27 sort: _.SORT_BYLENGTH,
28 innerHTML: text.replace(RegExp($.regExpEscape(input.trim()), "gi"), "<mark>$&</mark>"), 28 item: _.ITEM,
29 "aria-selected": "false" 29 replace: _.REPLACE
30 }); 30 }, o);
31 }, 31
32 replace: function (text) { 32 this.index = -1;
33 this.input.value = text; 33
34 } 34 // Create necessary elements
35 }, o); 35
36 36 this.container = $.create("div", {
37 this.index = -1; 37 className: "awesomplete",
38 38 around: input
39 // Create necessary elements 39 });
40 40
41 this.container = $.create("div", { 41 this.ul = $.create("ul", {
42 className: "awesomplete", 42 hidden: "hidden",
43 around: input 43 inside: this.container
44 }); 44 });
45 45
46 this.ul = $.create("ul", { 46 this.status = $.create("span", {
47 hidden: "", 47 className: "visually-hidden",
48 inside: this.container 48 role: "status",
49 }); 49 "aria-live": "assertive",
50 50 "aria-relevant": "additions",
51 this.status = $.create("span", { 51 inside: this.container
52 className: "visually-hidden", 52 });
53 role: "status", 53
54 "aria-live": "assertive", 54 // Bind events
55 "aria-relevant": "additions", 55
56 inside: this.container 56 $.bind(this.input, {
57 }); 57 "input": this.evaluate.bind(this),
58 58 "blur": this.close.bind(this),
59 // Bind events 59 "keydown": function(evt) {
60 60 var c = evt.keyCode;
61 $.bind(this.input, { 61
62 "input": this.evaluate.bind(this), 62 // If the dropdown `ul` is in view, then act on keydown for the following keys:
63 "blur": this.close.bind(this), 63 // Enter / Esc / Up / Down
64 "keydown": function(evt) { 64 if(me.opened) {
65 var c = evt.keyCode; 65 if (c === 13 && me.selected) { // Enter
66 66 evt.preventDefault();
67 // If the dropdown `ul` is in view, then act on keydown for the following keys: 67 me.select();
68 // Enter / Esc / Up / Down 68 }
69 if(me.opened) { 69 else if (c === 27) { // Esc
70 if (c === 13 && me.selected) { // Enter 70 me.close();
71 evt.preventDefault(); 71 }
72 me.select(); 72 else if (c === 38 || c === 40) { // Down/Up arrow
73 } 73 evt.preventDefault();
74 else if (c === 27) { // Esc 74 me[c === 38? "previous" : "next"]();
75 me.close(); 75 }
76 } 76 }
77 else if (c === 38 || c === 40) { // Down/Up arrow 77 }
78 evt.preventDefault(); 78 });
79 me[c === 38? "previous" : "next"](); 79
80 } 80 $.bind(this.input.form, {"submit": this.close.bind(this)});
81 } 81
82 } 82 $.bind(this.ul, {"mousedown": function(evt) {
83 }); 83 var li = evt.target;
84 84
85 $.bind(this.input.form, {"submit": this.close.bind(this)}); 85 if (li !== this) {
86 86
87 $.bind(this.ul, {"mousedown": function(evt) { 87 while (li && !/li/i.test(li.nodeName)) {
88 var li = evt.target; 88 li = li.parentNode;
89 89 }
90 if (li !== this) { 90
91 91 if (li && evt.button === 0) { // Only select on left click
92 while (li && !/li/i.test(li.nodeName)) { 92 evt.preventDefault();
93 li = li.parentNode; 93 me.select(li, evt.target);
94 } 94 }
95 95 }
96 if (li) { 96 }});
97 me.select(li); 97
98 } 98 if (this.input.hasAttribute("list")) {
99 } 99 this.list = "#" + this.input.getAttribute("list");
100 }}); 100 this.input.removeAttribute("list");
101 101 }
102 if (this.input.hasAttribute("list")) { 102 else {
103 this.list = "#" + input.getAttribute("list"); 103 this.list = this.input.getAttribute("data-list") || o.list || [];
104 input.removeAttribute("list"); 104 }
105 } 105
106 else { 106 _.all.push(this);
107 this.list = this.input.getAttribute("data-list") || o.list || []; 107};
108 } 108
109 109_.prototype = {
110 _.all.push(this); 110 set list(list) {
111 }; 111 if (Array.isArray(list)) {
112 112 this._list = list;
113 _.prototype = { 113 }
114 set list(list) { 114 else if (typeof list === "string" && list.indexOf(",") > -1) {
115 if (Array.isArray(list)) { 115 this._list = list.split(/\s*,\s*/);
116 this._list = list; 116 }
117 } 117 else { // Element or CSS selector
118 else if (typeof list === "string" && list.indexOf(",") > -1) { 118 list = $(list);
119 this._list = list.split(/\s*,\s*/); 119
120 } 120 if (list && list.children) {
121 else { // Element or CSS selector 121 var items = [];
122 list = $(list); 122 slice.apply(list.children).forEach(function (el) {
123 123 if (!el.disabled) {
124 if (list && list.children) { 124 var text = el.textContent.trim();
125 this._list = slice.apply(list.children).map(function (el) { 125 var value = el.value || text;
126 return el.innerHTML.trim(); 126 var label = el.label || text;
127 }); 127 if (value !== "") {
128 } 128 items.push({ label: label, value: value });
129 } 129 }
130 130 }
131 if (document.activeElement === this.input) { 131 });
132 this.evaluate(); 132 this._list = items;
133 } 133 }
134 }, 134 }
135 135
136 get selected() { 136 if (document.activeElement === this.input) {
137 return this.index > -1; 137 this.evaluate();
138 }, 138 }
139 139 },
140 get opened() { 140
141 return this.ul && this.ul.getAttribute("hidden") == null; 141 get selected() {
142 }, 142 return this.index > -1;
143 143 },
144 close: function () { 144
145 this.ul.setAttribute("hidden", ""); 145 get opened() {
146 this.index = -1; 146 return !this.ul.hasAttribute("hidden");
147 147 },
148 $.fire(this.input, "awesomplete-close"); 148
149 }, 149 close: function () {
150 150 this.ul.setAttribute("hidden", "");
151 open: function () { 151 this.index = -1;
152 this.ul.removeAttribute("hidden"); 152
153 153 $.fire(this.input, "awesomplete-close");
154 if (this.autoFirst && this.index === -1) { 154 },
155 this.goto(0); 155
156 } 156 open: function () {
157 157 this.ul.removeAttribute("hidden");
158 $.fire(this.input, "awesomplete-open"); 158
159 }, 159 if (this.autoFirst && this.index === -1) {
160 160 this.goto(0);
161 next: function () { 161 }
162 var count = this.ul.children.length; 162
163 163 $.fire(this.input, "awesomplete-open");
164 this.goto(this.index < count - 1? this.index + 1 : -1); 164 },
165 }, 165
166 166 next: function () {
167 previous: function () { 167 var count = this.ul.children.length;
168 var count = this.ul.children.length; 168
169 169 this.goto(this.index < count - 1? this.index + 1 : -1);
170 this.goto(this.selected? this.index - 1 : count - 1); 170 },
171 }, 171
172 172 previous: function () {
173 // Should not be used, highlights specific item without any checks! 173 var count = this.ul.children.length;
174 goto: function (i) { 174
175 var lis = this.ul.children; 175 this.goto(this.selected? this.index - 1 : count - 1);
176 176 },
177 if (this.selected) { 177
178 lis[this.index].setAttribute("aria-selected", "false"); 178 // Should not be used, highlights specific item without any checks!
179 } 179 goto: function (i) {
180 180 var lis = this.ul.children;
181 this.index = i; 181
182 182 if (this.selected) {
183 if (i > -1 && lis.length > 0) { 183 lis[this.index].setAttribute("aria-selected", "false");
184 lis[i].setAttribute("aria-selected", "true"); 184 }
185 this.status.textContent = lis[i].textContent; 185
186 } 186 this.index = i;
187 187
188 $.fire(this.input, "awesomplete-highlight"); 188 if (i > -1 && lis.length > 0) {
189 }, 189 lis[i].setAttribute("aria-selected", "true");
190 190 this.status.textContent = lis[i].textContent;
191 select: function (selected) { 191
192 selected = selected || this.ul.children[this.index]; 192 $.fire(this.input, "awesomplete-highlight", {
193 193 text: this.suggestions[this.index]
194 if (selected) { 194 });
195 var prevented; 195 }
196 196 },
197 $.fire(this.input, "awesomplete-select", { 197
198 text: selected.textContent, 198 select: function (selected, origin) {
199 preventDefault: function () { 199 if (selected) {
200 prevented = true; 200 this.index = $.siblingIndex(selected);
201 } 201 } else {
202 }); 202 selected = this.ul.children[this.index];
203 203 }
204 if (!prevented) { 204
205 this.replace(selected.textContent); 205 if (selected) {
206 this.close(); 206 var suggestion = this.suggestions[this.index];
207 $.fire(this.input, "awesomplete-selectcomplete"); 207
208 } 208 var allowed = $.fire(this.input, "awesomplete-select", {
209 } 209 text: suggestion,
210 }, 210 origin: origin || selected
211 211 });
212 evaluate: function() { 212
213 var me = this; 213 if (allowed) {
214 var value = this.input.value; 214 this.replace(suggestion);
215 215 this.close();
216 if (value.length >= this.minChars && this._list.length > 0) { 216 $.fire(this.input, "awesomplete-selectcomplete", {
217 this.index = -1; 217 text: suggestion
218 // Populate list with options that match 218 });
219 this.ul.innerHTML = ""; 219 }
220 220 }
221 this._list 221 },
222 .filter(function(item) { 222
223 return me.filter(item, value); 223 evaluate: function() {
224 }) 224 var me = this;
225 .sort(this.sort) 225 var value = this.input.value;
226 .every(function(text, i) { 226
227 me.ul.appendChild(me.item(text, value)); 227 if (value.length >= this.minChars && this._list.length > 0) {
228 228 this.index = -1;
229 return i < me.maxItems - 1; 229 // Populate list with options that match
230 }); 230 this.ul.innerHTML = "";
231 231
232 if (this.ul.children.length === 0) { 232 this.suggestions = this._list
233 this.close(); 233 .map(function(item) {
234 } else { 234 return new Suggestion(me.data(item, value));
235 this.open(); 235 })
236 } 236 .filter(function(item) {
237 } 237 return me.filter(item, value);
238 else { 238 })
239 this.close(); 239 .sort(this.sort)
240 } 240 .slice(0, this.maxItems);
241 } 241
242 }; 242 this.suggestions.forEach(function(text) {
243 me.ul.appendChild(me.item(text, value));
244 });
245
246 if (this.ul.children.length === 0) {
247 this.close();
248 } else {
249 this.open();
250 }
251 }
252 else {
253 this.close();
254 }
255 }
256};
243 257
244// Static methods/properties 258// Static methods/properties
245 259
246 _.all = []; 260_.all = [];
247 261
248 _.FILTER_CONTAINS = function (text, input) { 262_.FILTER_CONTAINS = function (text, input) {
249 return RegExp($.regExpEscape(input.trim()), "i").test(text); 263 return RegExp($.regExpEscape(input.trim()), "i").test(text);
250 }; 264};
251 265
252 _.FILTER_STARTSWITH = function (text, input) { 266_.FILTER_STARTSWITH = function (text, input) {
253 return RegExp("^" + $.regExpEscape(input.trim()), "i").test(text); 267 return RegExp("^" + $.regExpEscape(input.trim()), "i").test(text);
254 }; 268};
255 269
256 _.SORT_BYLENGTH = function (a, b) { 270_.SORT_BYLENGTH = function (a, b) {
257 if (a.length !== b.length) { 271 if (a.length !== b.length) {
258 return a.length - b.length; 272 return a.length - b.length;
259 } 273 }
260 274
261 return a < b? -1 : 1; 275 return a < b? -1 : 1;
262 }; 276};
277
278_.ITEM = function (text, input) {
279 var html = input === '' ? text : text.replace(RegExp($.regExpEscape(input.trim()), "gi"), "<mark>$&</mark>");
280 return $.create("li", {
281 innerHTML: html,
282 "aria-selected": "false"
283 });
284};
285
286_.REPLACE = function (text) {
287 this.input.value = text.value;
288};
289
290_.DATA = function (item/*, input*/) { return item; };
263 291
264// Private functions 292// Private functions
265 293
266 function configure(properties, o) { 294function Suggestion(data) {
267 for (var i in properties) { 295 var o = Array.isArray(data)
268 var initial = properties[i], 296 ? { label: data[0], value: data[1] }
269 attrValue = this.input.getAttribute("data-" + i.toLowerCase()); 297 : typeof data === "object" && "label" in data && "value" in data ? data : { label: data, value: data };
270 298
271 if (typeof initial === "number") { 299 this.label = o.label || o.value;
272 this[i] = +attrValue; 300 this.value = o.value;
273 } 301}
274 else if (initial === false) { // Boolean options must be false by default anyway 302Object.defineProperty(Suggestion.prototype = Object.create(String.prototype), "length", {
275 this[i] = attrValue !== null; 303 get: function() { return this.label.length; }
276 } 304});
277 else if (initial instanceof Function) { 305Suggestion.prototype.toString = Suggestion.prototype.valueOf = function () {
278 this[i] = null; 306 return "" + this.label;
279 } 307};
280 else { 308
281 this[i] = attrValue; 309function configure(instance, properties, o) {
282 } 310 for (var i in properties) {
283 311 var initial = properties[i],
284 this[i] = this[i] || o[i] || initial; 312 attrValue = instance.input.getAttribute("data-" + i.toLowerCase());
285 } 313
286 } 314 if (typeof initial === "number") {
315 instance[i] = parseInt(attrValue);
316 }
317 else if (initial === false) { // Boolean options must be false by default anyway
318 instance[i] = attrValue !== null;
319 }
320 else if (initial instanceof Function) {
321 instance[i] = null;
322 }
323 else {
324 instance[i] = attrValue;
325 }
326
327 if (!instance[i] && instance[i] !== 0) {
328 instance[i] = (i in o)? o[i] : initial;
329 }
330 }
331}
287 332
288// Helpers 333// Helpers
289 334
290 var slice = Array.prototype.slice; 335var slice = Array.prototype.slice;
291 336
292 function $(expr, con) { 337function $(expr, con) {
293 return typeof expr === "string"? (con || document).querySelector(expr) : expr || null; 338 return typeof expr === "string"? (con || document).querySelector(expr) : expr || null;
294 } 339}
295 340
296 function $$(expr, con) { 341function $$(expr, con) {
297 return slice.call((con || document).querySelectorAll(expr)); 342 return slice.call((con || document).querySelectorAll(expr));
298 } 343}
299 344
300 $.create = function(tag, o) { 345$.create = function(tag, o) {
301 var element = document.createElement(tag); 346 var element = document.createElement(tag);
302 347
303 for (var i in o) { 348 for (var i in o) {
304 var val = o[i]; 349 var val = o[i];
305 350
306 if (i === "inside") { 351 if (i === "inside") {
307 $(val).appendChild(element); 352 $(val).appendChild(element);
308 } 353 }
309 else if (i === "around") { 354 else if (i === "around") {
310 var ref = $(val); 355 var ref = $(val);
311 ref.parentNode.insertBefore(element, ref); 356 ref.parentNode.insertBefore(element, ref);
312 element.appendChild(ref); 357 element.appendChild(ref);
313 } 358 }
314 else if (i in element) { 359 else if (i in element) {
315 element[i] = val; 360 element[i] = val;
316 } 361 }
317 else { 362 else {
318 element.setAttribute(i, val); 363 element.setAttribute(i, val);
319 } 364 }
320 } 365 }
321 366
322 return element; 367 return element;
323 }; 368};
324 369
325 $.bind = function(element, o) { 370$.bind = function(element, o) {
326 if (element) { 371 if (element) {
327 for (var event in o) { 372 for (var event in o) {
328 var callback = o[event]; 373 var callback = o[event];
329 374
330 event.split(/\s+/).forEach(function (event) { 375 event.split(/\s+/).forEach(function (event) {
331 element.addEventListener(event, callback); 376 element.addEventListener(event, callback);
332 }); 377 });
333 } 378 }
334 } 379 }
335 }; 380};
336 381
337 $.fire = function(target, type, properties) { 382$.fire = function(target, type, properties) {
338 var evt = document.createEvent("HTMLEvents"); 383 var evt = document.createEvent("HTMLEvents");
339 384
340 evt.initEvent(type, true, true ); 385 evt.initEvent(type, true, true );
341 386
342 for (var j in properties) { 387 for (var j in properties) {
343 evt[j] = properties[j]; 388 evt[j] = properties[j];
344 } 389 }
345 390
346 target.dispatchEvent(evt); 391 return target.dispatchEvent(evt);
347 }; 392};
348 393
349 $.regExpEscape = function (s) { 394$.regExpEscape = function (s) {
350 return s.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&"); 395 return s.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&");
351 } 396};
397
398$.siblingIndex = function (el) {
399 /* eslint-disable no-cond-assign */
400 for (var i = 0; el = el.previousElementSibling; i++);
401 return i;
402};
352 403
353// Initialization 404// Initialization
354 405
355 function init() { 406function init() {
356 $$("input.awesomplete").forEach(function (input) { 407 $$("input.awesomplete").forEach(function (input) {
357 new Awesomplete(input); 408 new _(input);
358 }); 409 });
359 } 410}
360 411
361// Are we in a browser? Check for Document constructor 412// Are we in a browser? Check for Document constructor
362 if (typeof Document !== 'undefined') { 413if (typeof Document !== "undefined") {
363 // DOM already loaded? 414 // DOM already loaded?
364 if (document.readyState !== "loading") { 415 if (document.readyState !== "loading") {
365 init(); 416 init();
366 } 417 }
367 else { 418 else {
368 // Wait for it 419 // Wait for it
369 document.addEventListener("DOMContentLoaded", init); 420 document.addEventListener("DOMContentLoaded", init);
370 } 421 }
371 } 422}
372 423
373 _.$ = $; 424_.$ = $;
374 _.$$ = $$; 425_.$$ = $$;
375 426
376// Make sure to export Awesomplete on self when in a browser 427// Make sure to export Awesomplete on self when in a browser
377 if (typeof self !== 'undefined') { 428if (typeof self !== "undefined") {
378 self.Awesomplete = _; 429 self.Awesomplete = _;
379 } 430}
380 431
381// Expose Awesomplete as a CJS module 432// Expose Awesomplete as a CJS module
382 if (typeof exports === 'object') { 433if (typeof module === "object" && module.exports) {
383 module.exports = _; 434 module.exports = _;
384 } 435}
385 436
386 return _; 437return _;
387 438
388}()); 439}());
diff --git a/inc/awesomplete.min.js b/inc/awesomplete.min.js
index 3bfb05e8..bd750c83 100644
--- a/inc/awesomplete.min.js
+++ b/inc/awesomplete.min.js
@@ -1,10 +1,12 @@
1// Awesomplete - Lea Verou - MIT license 1// Awesomplete - Lea Verou - MIT license
2(function(){function m(a,b){for(var c in a){var f=a[c],e=this.input.getAttribute("data-"+c.toLowerCase());this[c]="number"===typeof f?+e:!1===f?null!==e:f instanceof Function?null:e;this[c]=this[c]||b[c]||f}}function d(a,b){return"string"===typeof a?(b||document).querySelector(a):a||null}function h(a,b){return k.call((b||document).querySelectorAll(a))}function l(){h("input.awesomplete").forEach(function(a){new Awesomplete(a)})}var g=self.Awesomplete=function(a,b){var c=this;this.input=d(a);this.input.setAttribute("aria-autocomplete", 2(function(){function h(a){a=Array.isArray(a)?{label:a[0],value:a[1]}:"object"===typeof a&&"label"in a&&"value"in a?a:{label:a,value:a};this.label=a.label||a.value;this.value=a.value}function n(a,b,d){for(var g in b){var f=b[g],c=a.input.getAttribute("data-"+g.toLowerCase());a[g]="number"===typeof f?parseInt(c):!1===f?null!==c:f instanceof Function?null:c;a[g]||0===a[g]||(a[g]=g in d?d[g]:f)}}function c(a,b){return"string"===typeof a?(b||document).querySelector(a):a||null}function k(a,b){return l.call((b||
3 "list");b=b||{};m.call(this,{minChars:2,maxItems:10,autoFirst:!1,filter:g.FILTER_CONTAINS,sort:g.SORT_BYLENGTH,item:function(a,b){return d.create("li",{innerHTML:a.replace(RegExp(d.regExpEscape(b.trim()),"gi"),"<mark>$&</mark>"),"aria-selected":"false"})},replace:function(a){this.input.value=a}},b);this.index=-1;this.container=d.create("div",{className:"awesomplete",around:a});this.ul=d.create("ul",{hidden:"",inside:this.container});this.status=d.create("span",{className:"visually-hidden",role:"status", 3document).querySelectorAll(a))}function m(){k("input.awesomplete").forEach(function(a){new e(a)})}var e=function(a,b){var d=this;this.input=c(a);this.input.setAttribute("autocomplete","off");this.input.setAttribute("aria-autocomplete","list");b=b||{};n(this,{minChars:2,maxItems:10,autoFirst:!1,data:e.DATA,filter:e.FILTER_CONTAINS,sort:e.SORT_BYLENGTH,item:e.ITEM,replace:e.REPLACE},b);this.index=-1;this.container=c.create("div",{className:"awesomplete",around:a});this.ul=c.create("ul",{hidden:"hidden",
4 "aria-live":"assertive","aria-relevant":"additions",inside:this.container});d.bind(this.input,{input:this.evaluate.bind(this),blur:this.close.bind(this),keydown:function(a){var b=a.keyCode;if(c.opened)if(13===b&&c.selected)a.preventDefault(),c.select();else if(27===b)c.close();else if(38===b||40===b)a.preventDefault(),c[38===b?"previous":"next"]()}});d.bind(this.input.form,{submit:this.close.bind(this)});d.bind(this.ul,{mousedown:function(a){a=a.target;if(a!==this){for(;a&&!/li/i.test(a.nodeName);)a= 4inside:this.container});this.status=c.create("span",{className:"visually-hidden",role:"status","aria-live":"assertive","aria-relevant":"additions",inside:this.container});c.bind(this.input,{input:this.evaluate.bind(this),blur:this.close.bind(this),keydown:function(a){var b=a.keyCode;if(d.opened)if(13===b&&d.selected)a.preventDefault(),d.select();else if(27===b)d.close();else if(38===b||40===b)a.preventDefault(),d[38===b?"previous":"next"]()}});c.bind(this.input.form,{submit:this.close.bind(this)});
5 a.parentNode;a&&c.select(a)}}});this.input.hasAttribute("list")?(this.list="#"+a.getAttribute("list"),a.removeAttribute("list")):this.list=this.input.getAttribute("data-list")||b.list||[];g.all.push(this)};g.prototype={set list(a){Array.isArray(a)?this._list=a:"string"===typeof a&&-1<a.indexOf(",")?this._list=a.split(/\s*,\s*/):(a=d(a))&&a.children&&(this._list=k.apply(a.children).map(function(a){return a.innerHTML.trim()}));document.activeElement===this.input&&this.evaluate()},get selected(){return-1< 5c.bind(this.ul,{mousedown:function(a){var b=a.target;if(b!==this){for(;b&&!/li/i.test(b.nodeName);)b=b.parentNode;b&&0===a.button&&(a.preventDefault(),d.select(b,a.target))}}});this.input.hasAttribute("list")?(this.list="#"+this.input.getAttribute("list"),this.input.removeAttribute("list")):this.list=this.input.getAttribute("data-list")||b.list||[];e.all.push(this)};e.prototype={set list(a){if(Array.isArray(a))this._list=a;else if("string"===typeof a&&-1<a.indexOf(","))this._list=a.split(/\s*,\s*/);
6this.index},get opened(){return this.ul&&null==this.ul.getAttribute("hidden")},close:function(){this.ul.setAttribute("hidden","");this.index=-1;d.fire(this.input,"awesomplete-close")},open:function(){this.ul.removeAttribute("hidden");this.autoFirst&&-1===this.index&&this.goto(0);d.fire(this.input,"awesomplete-open")},next:function(){this.goto(this.index<this.ul.children.length-1?this.index+1:-1)},previous:function(){var a=this.ul.children.length;this.goto(this.selected?this.index-1:a-1)},goto:function(a){var b= 6else if((a=c(a))&&a.children){var b=[];l.apply(a.children).forEach(function(a){if(!a.disabled){var c=a.textContent.trim(),f=a.value||c;a=a.label||c;""!==f&&b.push({label:a,value:f})}});this._list=b}document.activeElement===this.input&&this.evaluate()},get selected(){return-1<this.index},get opened(){return!this.ul.hasAttribute("hidden")},close:function(){this.ul.setAttribute("hidden","");this.index=-1;c.fire(this.input,"awesomplete-close")},open:function(){this.ul.removeAttribute("hidden");this.autoFirst&&
7 this.ul.children;this.selected&&b[this.index].setAttribute("aria-selected","false");this.index=a;-1<a&&0<b.length&&(b[a].setAttribute("aria-selected","true"),this.status.textContent=b[a].textContent)},select:function(a){if(a=a||this.ul.children[this.index]){var b;d.fire(this.input,"awesomplete-select",{text:a.textContent,preventDefault:function(){b=!0}});b||(this.replace(a.textContent),this.close(),d.fire(this.input,"awesomplete-selectcomplete"))}},evaluate:function(){var a=this,b=this.input.value; 7-1===this.index&&this["goto"](0);c.fire(this.input,"awesomplete-open")},next:function(){this["goto"](this.index<this.ul.children.length-1?this.index+1:-1)},previous:function(){var a=this.ul.children.length;this["goto"](this.selected?this.index-1:a-1)},"goto":function(a){var b=this.ul.children;this.selected&&b[this.index].setAttribute("aria-selected","false");this.index=a;-1<a&&0<b.length&&(b[a].setAttribute("aria-selected","true"),this.status.textContent=b[a].textContent,c.fire(this.input,"awesomplete-highlight",
8 b.length>=this.minChars&&0<this._list.length?(this.index=-1,this.ul.innerHTML="",this._list.filter(function(c){return a.filter(c,b)}).sort(this.sort).every(function(c,d){a.ul.appendChild(a.item(c,b));return d<a.maxItems-1}),0===this.ul.children.length?this.close():this.open()):this.close()}};g.all=[];g.FILTER_CONTAINS=function(a,b){return RegExp(d.regExpEscape(b.trim()),"i").test(a)};g.FILTER_STARTSWITH=function(a,b){return RegExp("^"+d.regExpEscape(b.trim()),"i").test(a)};g.SORT_BYLENGTH=function(a, 8{text:this.suggestions[this.index]}))},select:function(a,b){a?this.index=c.siblingIndex(a):a=this.ul.children[this.index];if(a){var d=this.suggestions[this.index];c.fire(this.input,"awesomplete-select",{text:d,origin:b||a})&&(this.replace(d),this.close(),c.fire(this.input,"awesomplete-selectcomplete",{text:d}))}},evaluate:function(){var a=this,b=this.input.value;b.length>=this.minChars&&0<this._list.length?(this.index=-1,this.ul.innerHTML="",this.suggestions=this._list.map(function(d){return new h(a.data(d,
9 b){return a.length!==b.length?a.length-b.length:a<b?-1:1};var k=Array.prototype.slice;d.create=function(a,b){var c=document.createElement(a),f;for(f in b){var e=b[f];"inside"===f?d(e).appendChild(c):"around"===f?(e=d(e),e.parentNode.insertBefore(c,e),c.appendChild(e)):f in c?c[f]=e:c.setAttribute(f,e)}return c};d.bind=function(a,b){if(a)for(var c in b){var d=b[c];c.split(/\s+/).forEach(function(b){a.addEventListener(b,d)})}};d.fire=function(a,b,c){var d=document.createEvent("HTMLEvents");d.initEvent(b, 9b))}).filter(function(d){return a.filter(d,b)}).sort(this.sort).slice(0,this.maxItems),this.suggestions.forEach(function(d){a.ul.appendChild(a.item(d,b))}),0===this.ul.children.length?this.close():this.open()):this.close()}};e.all=[];e.FILTER_CONTAINS=function(a,b){return RegExp(c.regExpEscape(b.trim()),"i").test(a)};e.FILTER_STARTSWITH=function(a,b){return RegExp("^"+c.regExpEscape(b.trim()),"i").test(a)};e.SORT_BYLENGTH=function(a,b){return a.length!==b.length?a.length-b.length:a<b?-1:1};e.ITEM=
10 !0,!0);for(var e in c)d[e]=c[e];a.dispatchEvent(d)};d.regExpEscape=function(a){return a.replace(/[-\\^$*+?.()|[\]{}]/g,"\\$&")};"loading"!==document.readyState?l():document.addEventListener("DOMContentLoaded",l);g.$=d;g.$$=h})(); 10function(a,b){var d=""===b?a:a.replace(RegExp(c.regExpEscape(b.trim()),"gi"),"<mark>$&</mark>");return c.create("li",{innerHTML:d,"aria-selected":"false"})};e.REPLACE=function(a){this.input.value=a.value};e.DATA=function(a){return a};Object.defineProperty(h.prototype=Object.create(String.prototype),"length",{get:function(){return this.label.length}});h.prototype.toString=h.prototype.valueOf=function(){return""+this.label};var l=Array.prototype.slice;c.create=function(a,b){var d=document.createElement(a),
11g;for(g in b){var f=b[g];"inside"===g?c(f).appendChild(d):"around"===g?(f=c(f),f.parentNode.insertBefore(d,f),d.appendChild(f)):g in d?d[g]=f:d.setAttribute(g,f)}return d};c.bind=function(a,b){if(a)for(var d in b){var c=b[d];d.split(/\s+/).forEach(function(b){a.addEventListener(b,c)})}};c.fire=function(a,b,c){var e=document.createEvent("HTMLEvents");e.initEvent(b,!0,!0);for(var f in c)e[f]=c[f];return a.dispatchEvent(e)};c.regExpEscape=function(a){return a.replace(/[-\\^$*+?.()|[\]{}]/g,"\\$&")};
12c.siblingIndex=function(a){for(var b=0;a=a.previousElementSibling;b++);return b};"undefined"!==typeof Document&&("loading"!==document.readyState?m():document.addEventListener("DOMContentLoaded",m));e.$=c;e.$$=k;"undefined"!==typeof self&&(self.Awesomplete=e);"object"===typeof module&&module.exports&&(module.exports=e);return e})(); \ No newline at end of file
diff --git a/plugins/markdown/markdown.css b/plugins/markdown/markdown.css
index 8f2c0051..33702564 100644
--- a/plugins/markdown/markdown.css
+++ b/plugins/markdown/markdown.css
@@ -150,10 +150,6 @@
150 box-shadow: 0 -1px 0 #e5e5e5,0 0 1px rgba(0,0,0,0.12),0 1px 1px rgba(0,0,0,0.24); 150 box-shadow: 0 -1px 0 #e5e5e5,0 0 1px rgba(0,0,0,0.12),0 1px 1px rgba(0,0,0,0.24);
151} 151}
152 152
153.md_help {
154 color: white;
155}
156
157/* 153/*
158 Remove header links style 154 Remove header links style
159 */ 155 */
diff --git a/tpl/default/editlink.html b/tpl/default/editlink.html
new file mode 100644
index 00000000..f831655c
--- /dev/null
+++ b/tpl/default/editlink.html
@@ -0,0 +1,82 @@
1<!DOCTYPE html>
2<html>
3<head>
4 {include="includes"}
5</head>
6<body>
7 {if="$source !== 'firefoxsocialapi'"}
8 {include="page.header"}
9 {/if}
10 <div id="editlinkform" class="pure-g">
11 <div class="pure-u-lg-1-5 pure-u-1-8"></div>
12 <form method="post" name="linkform" class="page-form pure-u-lg-3-5 pure-u-3-4" >
13 <h2>Shaare</h2>
14 <input type="hidden" name="lf_linkdate" value="{$link.linkdate}">
15 <div>
16 <label for="lf_url">URL</label>
17 </div>
18 <div>
19 <input type="text" name="lf_url" id="lf_url" value="{$link.url}" class="lf_input">
20 </div>
21 <div>
22 <label for="lf_title">Title</label>
23 </div>
24 <div>
25 <input type="text" name="lf_title" id="lf_title" value="{$link.title}" class="lf_input">
26 </div>
27 <div>
28 <label for="lf_description">Description</label>
29 </div>
30 <div>
31 <textarea name="lf_description" id="lf_description">{$link.description}</textarea>
32 </div>
33 <div>
34 <label for="lf_tags">Tags</label>
35 </div>
36 <div>
37 <input type="text" name="lf_tags" id="lf_tags" value="{$link.tags}" class="lf_input"
38 data-list="{loop="$tags"}{$key}, {/loop}" data-multiple autocomplete="off" >
39 </div>
40
41 <div>
42 <input type="checkbox" name="lf_private" id="lf_private"
43 {if="($link_is_new && $GLOBALS['privateLinkByDefault']==true) || $link.private == true"}
44 checked="checked"
45 {/if}>
46 &nbsp;<label for="lf_private">Private</label>
47 </div>
48
49 <div id="editlink-plugins">
50 {loop="$edit_link_plugin"}
51 {$value}
52 {/loop}
53 </div>
54
55 <div>
56 <input type="submit" value="Save" name="save_edit">
57 {if="!$link_is_new"}
58 <input type="submit" value="Delete" name="delete_link" class="delete-link">
59 {/if}
60 </div>
61
62 <input type="hidden" name="token" value="{$token}">
63 {if="$http_referer"}
64 <input type="hidden" name="returnurl" value="{$http_referer}">
65 {/if}
66 </form>
67 </div>
68 {if="$source !== 'firefoxsocialapi'"}
69 {include="page.footer"}
70 {/if}
71<script>
72 awesompleteUniqueTag('#lf_tags');
73 if (!'{$link.title}') {
74 document.linkform.lf_title.focus();
75 } else if (!'{$link.description}') {
76 document.linkform.lf_description.focus();
77 } else {
78 document.linkform.lf_tags.focus();
79 }
80</script>
81</body>
82</html>