Use awesomplete as autocomplete lib and remove jQuery - shaarli/Shaarli#148
* Add awesomplete dependancy (source + min + CSS) * Remove jQuery and jQuery-UI dependancy * Few CSS ajustements * Use tags complete list as RainTPL var (and display it as HTML) * Remove "disable jQuery" feature * Remove tag list web service
This commit is contained in:
parent
3a10fa0e3f
commit
bdd1715b24
8
COPYING
8
COPYING
|
@ -46,10 +46,6 @@ Files: images/logo.png
|
|||
License: zlib/libpng
|
||||
Copyright: (c) 2011-2014 idleman idleman@idleman.fr
|
||||
|
||||
Files: Files: inc/jquery*.js, inc/jquery-ui*.js
|
||||
License: MIT License (http://opensource.org/licenses/MIT)
|
||||
Copyright: (C) jQuery Foundation and other contributors,https://jquery.com/download/
|
||||
|
||||
Files: inc/blazy*.js
|
||||
License: MIT License (http://opensource.org/licenses/MIT)
|
||||
Copyright: (C) Bjoern Klinggaard - @bklinggaard - http://dinbror.dk/blazy
|
||||
|
@ -63,6 +59,10 @@ Copyright: 2011-2012, Federico Ulfo <rainelemental@gmail.com>
|
|||
2011-2012, The Rain Team <hello@raintm.com>
|
||||
License: LGPL-3+ (https://www.gnu.org/licenses/lgpl-3.0.txt)
|
||||
|
||||
Files: inc/awesomplete*
|
||||
License: MIT License (http://opensource.org/licenses/MIT)
|
||||
Copyright: (C) 2015 Lea Verou - https://github.com/LeaVerou/awesomplete
|
||||
|
||||
----------------------------------------------------
|
||||
ZLIB/LIBPNG LICENSE
|
||||
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
[hidden] { display: none; }
|
||||
|
||||
.visually-hidden {
|
||||
position: absolute;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
div.awesomplete {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.awesomplete > input {
|
||||
display: block;
|
||||
}
|
||||
|
||||
div.awesomplete > ul {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
min-width: 100%;
|
||||
box-sizing: border-box;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
border-radius: .3em;
|
||||
margin: .2em 0 0;
|
||||
background: #FFF;
|
||||
border: 1px solid rgba(0,0,0,.3);
|
||||
box-shadow: .05em .2em .6em rgba(0,0,0,.2);
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
div.awesomplete > ul[hidden],
|
||||
div.awesomplete > ul:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@supports (transform: scale(0)) {
|
||||
div.awesomplete > ul {
|
||||
transition: .3s cubic-bezier(.4,.2,.5,1.4);
|
||||
transform-origin: 1.43em -.43em;
|
||||
}
|
||||
|
||||
div.awesomplete > ul[hidden],
|
||||
div.awesomplete > ul:empty {
|
||||
opacity: 0;
|
||||
transform: scale(0);
|
||||
display: block;
|
||||
transition-timing-function: ease;
|
||||
}
|
||||
}
|
||||
|
||||
/* Pointer */
|
||||
div.awesomplete > ul:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -.43em;
|
||||
left: 1em;
|
||||
width: 0; height: 0;
|
||||
padding: .4em;
|
||||
background: white;
|
||||
border: inherit;
|
||||
border-right: 0;
|
||||
border-bottom: 0;
|
||||
-webkit-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
div.awesomplete > ul > li {
|
||||
position: relative;
|
||||
padding: .2em .5em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.awesomplete > ul > li:hover {
|
||||
background: hsl(200, 40%, 80%);
|
||||
color: black;
|
||||
}
|
||||
|
||||
div.awesomplete > ul > li[aria-selected="true"] {
|
||||
background: hsl(205, 40%, 40%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
div.awesomplete mark {
|
||||
background: hsl(65, 100%, 50%);
|
||||
}
|
||||
|
||||
div.awesomplete li:hover mark {
|
||||
background: hsl(68, 101%, 41%);
|
||||
}
|
||||
|
||||
div.awesomplete li[aria-selected="true"] mark {
|
||||
background: hsl(86, 102%, 21%);
|
||||
color: inherit;
|
||||
}
|
|
@ -0,0 +1,388 @@
|
|||
/**
|
||||
* Simple, lightweight, usable local autocomplete library for modern browsers
|
||||
* Because there weren’t enough autocomplete scripts in the world? Because I’m completely insane and have NIH syndrome? Probably both. :P
|
||||
* @author Lea Verou http://leaverou.github.io/awesomplete
|
||||
* MIT license
|
||||
*/
|
||||
|
||||
(function () {
|
||||
|
||||
var _ = function (input, o) {
|
||||
var me = this;
|
||||
|
||||
// Setup
|
||||
|
||||
this.input = $(input);
|
||||
this.input.setAttribute("aria-autocomplete", "list");
|
||||
|
||||
o = o || {};
|
||||
|
||||
configure.call(this, {
|
||||
minChars: 2,
|
||||
maxItems: 10,
|
||||
autoFirst: false,
|
||||
filter: _.FILTER_CONTAINS,
|
||||
sort: _.SORT_BYLENGTH,
|
||||
item: function (text, input) {
|
||||
return $.create("li", {
|
||||
innerHTML: text.replace(RegExp($.regExpEscape(input.trim()), "gi"), "<mark>$&</mark>"),
|
||||
"aria-selected": "false"
|
||||
});
|
||||
},
|
||||
replace: function (text) {
|
||||
this.input.value = text;
|
||||
}
|
||||
}, o);
|
||||
|
||||
this.index = -1;
|
||||
|
||||
// Create necessary elements
|
||||
|
||||
this.container = $.create("div", {
|
||||
className: "awesomplete",
|
||||
around: input
|
||||
});
|
||||
|
||||
this.ul = $.create("ul", {
|
||||
hidden: "",
|
||||
inside: this.container
|
||||
});
|
||||
|
||||
this.status = $.create("span", {
|
||||
className: "visually-hidden",
|
||||
role: "status",
|
||||
"aria-live": "assertive",
|
||||
"aria-relevant": "additions",
|
||||
inside: this.container
|
||||
});
|
||||
|
||||
// Bind events
|
||||
|
||||
$.bind(this.input, {
|
||||
"input": this.evaluate.bind(this),
|
||||
"blur": this.close.bind(this),
|
||||
"keydown": function(evt) {
|
||||
var c = evt.keyCode;
|
||||
|
||||
// If the dropdown `ul` is in view, then act on keydown for the following keys:
|
||||
// Enter / Esc / Up / Down
|
||||
if(me.opened) {
|
||||
if (c === 13 && me.selected) { // Enter
|
||||
evt.preventDefault();
|
||||
me.select();
|
||||
}
|
||||
else if (c === 27) { // Esc
|
||||
me.close();
|
||||
}
|
||||
else if (c === 38 || c === 40) { // Down/Up arrow
|
||||
evt.preventDefault();
|
||||
me[c === 38? "previous" : "next"]();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$.bind(this.input.form, {"submit": this.close.bind(this)});
|
||||
|
||||
$.bind(this.ul, {"mousedown": function(evt) {
|
||||
var li = evt.target;
|
||||
|
||||
if (li !== this) {
|
||||
|
||||
while (li && !/li/i.test(li.nodeName)) {
|
||||
li = li.parentNode;
|
||||
}
|
||||
|
||||
if (li) {
|
||||
me.select(li);
|
||||
}
|
||||
}
|
||||
}});
|
||||
|
||||
if (this.input.hasAttribute("list")) {
|
||||
this.list = "#" + input.getAttribute("list");
|
||||
input.removeAttribute("list");
|
||||
}
|
||||
else {
|
||||
this.list = this.input.getAttribute("data-list") || o.list || [];
|
||||
}
|
||||
|
||||
_.all.push(this);
|
||||
};
|
||||
|
||||
_.prototype = {
|
||||
set list(list) {
|
||||
if (Array.isArray(list)) {
|
||||
this._list = list;
|
||||
}
|
||||
else if (typeof list === "string" && list.indexOf(",") > -1) {
|
||||
this._list = list.split(/\s*,\s*/);
|
||||
}
|
||||
else { // Element or CSS selector
|
||||
list = $(list);
|
||||
|
||||
if (list && list.children) {
|
||||
this._list = slice.apply(list.children).map(function (el) {
|
||||
return el.innerHTML.trim();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (document.activeElement === this.input) {
|
||||
this.evaluate();
|
||||
}
|
||||
},
|
||||
|
||||
get selected() {
|
||||
return this.index > -1;
|
||||
},
|
||||
|
||||
get opened() {
|
||||
return this.ul && this.ul.getAttribute("hidden") == null;
|
||||
},
|
||||
|
||||
close: function () {
|
||||
this.ul.setAttribute("hidden", "");
|
||||
this.index = -1;
|
||||
|
||||
$.fire(this.input, "awesomplete-close");
|
||||
},
|
||||
|
||||
open: function () {
|
||||
this.ul.removeAttribute("hidden");
|
||||
|
||||
if (this.autoFirst && this.index === -1) {
|
||||
this.goto(0);
|
||||
}
|
||||
|
||||
$.fire(this.input, "awesomplete-open");
|
||||
},
|
||||
|
||||
next: function () {
|
||||
var count = this.ul.children.length;
|
||||
|
||||
this.goto(this.index < count - 1? this.index + 1 : -1);
|
||||
},
|
||||
|
||||
previous: function () {
|
||||
var count = this.ul.children.length;
|
||||
|
||||
this.goto(this.selected? this.index - 1 : count - 1);
|
||||
},
|
||||
|
||||
// Should not be used, highlights specific item without any checks!
|
||||
goto: function (i) {
|
||||
var lis = this.ul.children;
|
||||
|
||||
if (this.selected) {
|
||||
lis[this.index].setAttribute("aria-selected", "false");
|
||||
}
|
||||
|
||||
this.index = i;
|
||||
|
||||
if (i > -1 && lis.length > 0) {
|
||||
lis[i].setAttribute("aria-selected", "true");
|
||||
this.status.textContent = lis[i].textContent;
|
||||
}
|
||||
|
||||
$.fire(this.input, "awesomplete-highlight");
|
||||
},
|
||||
|
||||
select: function (selected) {
|
||||
selected = selected || this.ul.children[this.index];
|
||||
|
||||
if (selected) {
|
||||
var prevented;
|
||||
|
||||
$.fire(this.input, "awesomplete-select", {
|
||||
text: selected.textContent,
|
||||
preventDefault: function () {
|
||||
prevented = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!prevented) {
|
||||
this.replace(selected.textContent);
|
||||
this.close();
|
||||
$.fire(this.input, "awesomplete-selectcomplete");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
evaluate: function() {
|
||||
var me = this;
|
||||
var value = this.input.value;
|
||||
|
||||
if (value.length >= this.minChars && this._list.length > 0) {
|
||||
this.index = -1;
|
||||
// Populate list with options that match
|
||||
this.ul.innerHTML = "";
|
||||
|
||||
this._list
|
||||
.filter(function(item) {
|
||||
return me.filter(item, value);
|
||||
})
|
||||
.sort(this.sort)
|
||||
.every(function(text, i) {
|
||||
me.ul.appendChild(me.item(text, value));
|
||||
|
||||
return i < me.maxItems - 1;
|
||||
});
|
||||
|
||||
if (this.ul.children.length === 0) {
|
||||
this.close();
|
||||
} else {
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Static methods/properties
|
||||
|
||||
_.all = [];
|
||||
|
||||
_.FILTER_CONTAINS = function (text, input) {
|
||||
return RegExp($.regExpEscape(input.trim()), "i").test(text);
|
||||
};
|
||||
|
||||
_.FILTER_STARTSWITH = function (text, input) {
|
||||
return RegExp("^" + $.regExpEscape(input.trim()), "i").test(text);
|
||||
};
|
||||
|
||||
_.SORT_BYLENGTH = function (a, b) {
|
||||
if (a.length !== b.length) {
|
||||
return a.length - b.length;
|
||||
}
|
||||
|
||||
return a < b? -1 : 1;
|
||||
};
|
||||
|
||||
// Private functions
|
||||
|
||||
function configure(properties, o) {
|
||||
for (var i in properties) {
|
||||
var initial = properties[i],
|
||||
attrValue = this.input.getAttribute("data-" + i.toLowerCase());
|
||||
|
||||
if (typeof initial === "number") {
|
||||
this[i] = +attrValue;
|
||||
}
|
||||
else if (initial === false) { // Boolean options must be false by default anyway
|
||||
this[i] = attrValue !== null;
|
||||
}
|
||||
else if (initial instanceof Function) {
|
||||
this[i] = null;
|
||||
}
|
||||
else {
|
||||
this[i] = attrValue;
|
||||
}
|
||||
|
||||
this[i] = this[i] || o[i] || initial;
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers
|
||||
|
||||
var slice = Array.prototype.slice;
|
||||
|
||||
function $(expr, con) {
|
||||
return typeof expr === "string"? (con || document).querySelector(expr) : expr || null;
|
||||
}
|
||||
|
||||
function $$(expr, con) {
|
||||
return slice.call((con || document).querySelectorAll(expr));
|
||||
}
|
||||
|
||||
$.create = function(tag, o) {
|
||||
var element = document.createElement(tag);
|
||||
|
||||
for (var i in o) {
|
||||
var val = o[i];
|
||||
|
||||
if (i === "inside") {
|
||||
$(val).appendChild(element);
|
||||
}
|
||||
else if (i === "around") {
|
||||
var ref = $(val);
|
||||
ref.parentNode.insertBefore(element, ref);
|
||||
element.appendChild(ref);
|
||||
}
|
||||
else if (i in element) {
|
||||
element[i] = val;
|
||||
}
|
||||
else {
|
||||
element.setAttribute(i, val);
|
||||
}
|
||||
}
|
||||
|
||||
return element;
|
||||
};
|
||||
|
||||
$.bind = function(element, o) {
|
||||
if (element) {
|
||||
for (var event in o) {
|
||||
var callback = o[event];
|
||||
|
||||
event.split(/\s+/).forEach(function (event) {
|
||||
element.addEventListener(event, callback);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.fire = function(target, type, properties) {
|
||||
var evt = document.createEvent("HTMLEvents");
|
||||
|
||||
evt.initEvent(type, true, true );
|
||||
|
||||
for (var j in properties) {
|
||||
evt[j] = properties[j];
|
||||
}
|
||||
|
||||
target.dispatchEvent(evt);
|
||||
};
|
||||
|
||||
$.regExpEscape = function (s) {
|
||||
return s.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&");
|
||||
}
|
||||
|
||||
// Initialization
|
||||
|
||||
function init() {
|
||||
$$("input.awesomplete").forEach(function (input) {
|
||||
new Awesomplete(input);
|
||||
});
|
||||
}
|
||||
|
||||
// Are we in a browser? Check for Document constructor
|
||||
if (typeof Document !== 'undefined') {
|
||||
// DOM already loaded?
|
||||
if (document.readyState !== "loading") {
|
||||
init();
|
||||
}
|
||||
else {
|
||||
// Wait for it
|
||||
document.addEventListener("DOMContentLoaded", init);
|
||||
}
|
||||
}
|
||||
|
||||
_.$ = $;
|
||||
_.$$ = $$;
|
||||
|
||||
// Make sure to export Awesomplete on self when in a browser
|
||||
if (typeof self !== 'undefined') {
|
||||
self.Awesomplete = _;
|
||||
}
|
||||
|
||||
// Expose Awesomplete as a CJS module
|
||||
if (typeof exports === 'object') {
|
||||
module.exports = _;
|
||||
}
|
||||
|
||||
return _;
|
||||
|
||||
}());
|
|
@ -0,0 +1,10 @@
|
|||
// Awesomplete - Lea Verou - MIT license
|
||||
(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",
|
||||
"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",
|
||||
"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=
|
||||
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<
|
||||
this.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=
|
||||
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;
|
||||
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,
|
||||
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,
|
||||
!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})();
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -339,12 +339,15 @@ h1 {
|
|||
|
||||
#editlinkform {
|
||||
height: 100%;
|
||||
color: #ffffff;
|
||||
padding: 5px 5px 5px 15px;
|
||||
width: 80%;
|
||||
clear: left;
|
||||
}
|
||||
|
||||
#editlinkform label {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
#editlinkform textarea, #editlinkform .lf_input {
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -599,6 +602,17 @@ a.qrcode img {
|
|||
margin-left: 40px;
|
||||
}
|
||||
|
||||
#changetag div {
|
||||
float:left;
|
||||
}
|
||||
|
||||
#changetag label {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
#changetag li {
|
||||
color: #000;
|
||||
}
|
||||
#configform td {
|
||||
color: #ccc;
|
||||
font-size: 10pt;
|
||||
|
@ -691,17 +705,6 @@ a.qrcode img {
|
|||
text-shadow: 2px 2px 1px #000000;
|
||||
}
|
||||
|
||||
/* Minimal customisation for jQuery widgets */
|
||||
.ui-autocomplete {
|
||||
background-color: #fff;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.ui-state-hover {
|
||||
background-color: #604dff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#linklist li.publicLinkHightLight {
|
||||
background: #ffffff;
|
||||
}
|
||||
|
@ -856,6 +859,10 @@ div.dailyNoEntry {
|
|||
text-align: right;
|
||||
}
|
||||
|
||||
.white {
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* For lazy images loading in picture wall.
|
||||
Using http://www.appelsiini.net/projects/lazyload
|
||||
*/
|
||||
|
|
43
index.php
43
index.php
|
@ -1491,6 +1491,7 @@ function renderPage()
|
|||
$PAGE = new pageBuilder;
|
||||
$PAGE->assign('linkcount',count($LINKSDB));
|
||||
$PAGE->assign('token',getToken());
|
||||
$PAGE->assign('tags', $LINKSDB->allTags());
|
||||
$PAGE->renderPage('changetag');
|
||||
exit;
|
||||
}
|
||||
|
@ -1634,6 +1635,7 @@ function renderPage()
|
|||
$PAGE->assign('link_is_new',false);
|
||||
$PAGE->assign('token',getToken()); // XSRF protection.
|
||||
$PAGE->assign('http_referer',(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''));
|
||||
$PAGE->assign('tags', $LINKSDB->allTags());
|
||||
$PAGE->renderPage('editlink');
|
||||
exit;
|
||||
}
|
||||
|
@ -1705,6 +1707,7 @@ function renderPage()
|
|||
$PAGE->assign('link_is_new',$link_is_new);
|
||||
$PAGE->assign('token',getToken()); // XSRF protection.
|
||||
$PAGE->assign('http_referer',(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''));
|
||||
$PAGE->assign('tags', $LINKSDB->allTags());
|
||||
$PAGE->renderPage('editlink');
|
||||
exit;
|
||||
}
|
||||
|
@ -2309,45 +2312,6 @@ if (!function_exists('json_encode')) {
|
|||
}
|
||||
}
|
||||
|
||||
// Webservices (for use with jQuery/jQueryUI)
|
||||
// e.g. index.php?ws=tags&term=minecr
|
||||
function processWS()
|
||||
{
|
||||
if (empty($_GET['ws']) || empty($_GET['term'])) return;
|
||||
$term = $_GET['term'];
|
||||
$LINKSDB=new linkdb(isLoggedIn() || $GLOBALS['config']['OPEN_SHAARLI']); // Read links from database (and filter private links if used it not logged in).
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
// Search in tags (case insensitive, cumulative search)
|
||||
if ($_GET['ws']=='tags')
|
||||
{
|
||||
$tags=explode(' ',str_replace(',',' ',$term)); $last = array_pop($tags); // Get the last term ("a b c d" ==> "a b c", "d")
|
||||
$addtags=''; if ($tags) $addtags=implode(' ',$tags).' '; // We will pre-pend previous tags
|
||||
$suggested=array();
|
||||
/* To speed up things, we store list of tags in session */
|
||||
if (empty($_SESSION['tags'])) $_SESSION['tags'] = $LINKSDB->allTags();
|
||||
foreach($_SESSION['tags'] as $key=>$value)
|
||||
{
|
||||
if (startsWith($key,$last,$case=false) && !in_array($key,$tags)) $suggested[$addtags.$key.' ']=0;
|
||||
}
|
||||
echo json_encode(array_keys($suggested));
|
||||
exit;
|
||||
}
|
||||
|
||||
// Search a single tag (case sensitive, single tag search)
|
||||
if ($_GET['ws']=='singletag')
|
||||
{
|
||||
/* To speed up things, we store list of tags in session */
|
||||
if (empty($_SESSION['tags'])) $_SESSION['tags'] = $LINKSDB->allTags();
|
||||
foreach($_SESSION['tags'] as $key=>$value)
|
||||
{
|
||||
if (startsWith($key,$term,$case=true)) $suggested[$key]=0;
|
||||
}
|
||||
echo json_encode(array_keys($suggested));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Re-write configuration file according to globals.
|
||||
// Requires some $GLOBALS to be set (login,hash,salt,title).
|
||||
// If the config file cannot be saved, an error message is displayed and the user is redirected to "Tools" menu.
|
||||
|
@ -2604,7 +2568,6 @@ if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=r
|
|||
if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=atom')) { showATOM(); exit; }
|
||||
if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=dailyrss')) { showDailyRSS(); exit; }
|
||||
if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=daily')) { showDaily(); exit; }
|
||||
if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'ws=')) { processWS(); exit; } // Webservices (for jQuery/jQueryUI)
|
||||
if (!isset($_SESSION['LINKS_PER_PAGE'])) $_SESSION['LINKS_PER_PAGE']=$GLOBALS['config']['LINKS_PER_PAGE'];
|
||||
renderPage();
|
||||
?>
|
||||
|
|
|
@ -1,27 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>{include="includes"}
|
||||
{if="empty($GLOBALS['disablejquery'])"}<script src="inc/jquery.min.js#"></script><script src="inc/jquery-ui.min.js#"></script>{/if}
|
||||
<link type="text/css" rel="stylesheet" href="../inc/awesomplete.css" />
|
||||
<script src="inc/awesomplete.min.js#"></script>
|
||||
</head>
|
||||
<body onload="document.changetag.fromtag.focus();">
|
||||
<div id="pageheader">
|
||||
{include="page.header"}
|
||||
<form method="POST" action="" name="changetag" id="changetag">
|
||||
<input type="hidden" name="token" value="{$token}">
|
||||
Tag: <input type="text" name="fromtag" id="fromtag">
|
||||
<input type="text" name="totag" id="totag">
|
||||
<input type="submit" name="renametag" value="Rename tag" class="bigbutton">
|
||||
or <input type="submit" name="deletetag" value="Delete tag" class="bigbutton" onClick="return confirmDeleteTag();"><br>(Case sensitive)</form>
|
||||
<input type="hidden" name="token" value="{$token}">
|
||||
<div>
|
||||
<label for="fromtag">Tag:</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" name="fromtag" id="fromtag" list="tagsList" autocomplete="off" class="awesomplete" data-minChars="1" />
|
||||
<datalist id="tagsList">
|
||||
{loop="$tags"}<option>{$key}</option>{/loop}
|
||||
</datalist>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<input type="text" name="totag" id="totag">
|
||||
<input type="submit" name="renametag" value="Rename tag" class="bigbutton">
|
||||
or <input type="submit" name="deletetag" value="Delete tag" class="bigbutton" onClick="return confirmDeleteTag();">
|
||||
</div>
|
||||
</form>
|
||||
<div class="clear white">(Case sensitive)</div>
|
||||
</div>
|
||||
<script>function confirmDeleteTag() { var agree=confirm("Are you sure you want to delete this tag from all links ?"); if (agree) return true ; else return false ; }</script>
|
||||
</div>
|
||||
{include="page.footer"}
|
||||
{if="($GLOBALS['config']['OPEN_SHAARLI'] || isLoggedIn()) && empty($GLOBALS['disablejquery'])"}
|
||||
<script>
|
||||
$(document).ready(function()
|
||||
{
|
||||
$('#fromtag').autocomplete({source:'{$source}?ws=singletag',minLength:1});
|
||||
});
|
||||
</script>
|
||||
{/if}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -18,9 +18,6 @@
|
|||
|
||||
<tr><td><b>Security:</b></td><td><input type="checkbox" name="disablesessionprotection" id="disablesessionprotection" {if="!empty($GLOBALS['disablesessionprotection'])"}checked{/if}><label for="disablesessionprotection"> Disable session cookie hijacking protection (Check this if you get disconnected often or if your IP address changes often.)</label></td></tr>
|
||||
|
||||
<tr><td><b>Features:</b></td><td>
|
||||
<input type="checkbox" name="disablejquery" id="disablejquery" {if="!empty($GLOBALS['disablejquery'])"}checked{/if}><label for="disablejquery"> Disable jQuery and all heavy JavaScript (for example: Autocomplete in tags. Useful for slow computers.)</label>
|
||||
</td></tr>
|
||||
<tr><td valign="top"><b>New link:</b></td><td>
|
||||
<input type="checkbox" name="privateLinkByDefault" id="privateLinkByDefault" {if="!empty($GLOBALS['privateLinkByDefault'])"}checked{/if}/><label for="privateLinkByDefault"> All new links are private by default</label></td>
|
||||
</tr>
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>{include="includes"}
|
||||
{if="empty($GLOBALS['disablejquery'])"}<script src="inc/jquery-1.11.2.min.js#"></script><script src="inc/jquery-ui-1.11.2.min.js#"></script>{/if}
|
||||
<link type="text/css" rel="stylesheet" href="../inc/awesomplete.css" />
|
||||
<script src="inc/awesomplete.min.js#"></script>
|
||||
</head>
|
||||
<body
|
||||
{if="$link.title==''"}onload="document.linkform.lf_title.focus();"
|
||||
|
@ -12,10 +13,12 @@
|
|||
<div id="editlinkform">
|
||||
<form method="post" name="linkform">
|
||||
<input type="hidden" name="lf_linkdate" value="{$link.linkdate}">
|
||||
<i>URL</i><br><input type="text" name="lf_url" value="{$link.url|htmlspecialchars}" class="lf_input"><br>
|
||||
<i>Title</i><br><input type="text" name="lf_title" value="{$link.title|htmlspecialchars}" class="lf_input"><br>
|
||||
<i>Description</i><br><textarea name="lf_description" rows="4" cols="25">{$link.description|htmlspecialchars}</textarea><br>
|
||||
<i>Tags</i><br><input type="text" id="lf_tags" name="lf_tags" value="{$link.tags|htmlspecialchars}" class="lf_input"><br>
|
||||
<label for="lf_url"><i>URL</i></label><br><input type="text" name="lf_url" id="lf_url" value="{$link.url|htmlspecialchars}" class="lf_input"><br>
|
||||
<label for="lf_title"><i>Title</i></label><br><input type="text" name="lf_title" id="lf_title" value="{$link.title|htmlspecialchars}" class="lf_input"><br>
|
||||
<label for="lf_description"><i>Description</i></label><br><textarea name="lf_description" id="lf_description" rows="4" cols="25">{$link.description|htmlspecialchars}</textarea><br>
|
||||
<label for="lf_tags"><i>Tags</i></label><br>
|
||||
<input type="text" id="lf_tags" name="lf_tags" id="lf_tags" value="{$link.tags|htmlspecialchars}" class="lf_input"
|
||||
data-list="{loop="$tags"}{$key}, {/loop}" data-multiple autocomplete="off" ><br>
|
||||
{if="($link_is_new && $GLOBALS['privateLinkByDefault']==true) || $link.private == true"}
|
||||
<input type="checkbox" checked="checked" name="lf_private" id="lf_private">
|
||||
<label for="lf_private"><i>Private</i></label><br>
|
||||
|
@ -32,12 +35,19 @@
|
|||
</div>
|
||||
</div>
|
||||
{include="page.footer"}
|
||||
{if="($GLOBALS['config']['OPEN_SHAARLI'] || isLoggedIn()) && empty($GLOBALS['disablejquery'])"}
|
||||
{if="($GLOBALS['config']['OPEN_SHAARLI'] || isLoggedIn())"}
|
||||
<script>
|
||||
$(document).ready(function()
|
||||
{
|
||||
$('#lf_tags').autocomplete({source:'{$source}?ws=tags',minLength:1});
|
||||
});
|
||||
$ = Awesomplete.$;
|
||||
new Awesomplete($('input[data-multiple]'), {
|
||||
filter: function(text, input) {
|
||||
return Awesomplete.FILTER_CONTAINS(text, input.match(/[^ ]*$/)[0]);
|
||||
},
|
||||
replace: function(text) {
|
||||
var before = this.input.value.match(/^.+ \s*|/)[0];
|
||||
this.input.value = before + text + " ";
|
||||
},
|
||||
minChars: 1
|
||||
});
|
||||
</script>
|
||||
{/if}
|
||||
</body>
|
||||
|
|
Loading…
Reference in New Issue