diff --git a/css/lexiconga.css b/css/lexiconga.css
index acefd87..167eb5c 100644
--- a/css/lexiconga.css
+++ b/css/lexiconga.css
@@ -114,7 +114,7 @@ input, textarea, select, option, button {
}
#loginLink, #logoutLink,
-#descriptionToggle, #settingsButton,
+#descriptionToggle, #searchFilterToggle, #settingsButton,
.deleteCancelButton, .deleteConfirmButton,
#settingsScreenCloseButton, #infoScreenCloseButton,
.helperlink {
diff --git a/css/styles.css b/css/styles.css
index 2ca510d..42eebf9 100644
--- a/css/styles.css
+++ b/css/styles.css
@@ -187,7 +187,9 @@ input[type=checkbox] {
cursor: pointer;
}
-#descriptionToggle {
+#descriptionToggle, #searchFilterToggle {
+ display: inline-block;
+ margin: 8px;
font-weight: bold;
font-size: 12px;
cursor: pointer;
diff --git a/index.php b/index.php
index 4da2989..1f54aa4 100644
--- a/index.php
+++ b/index.php
@@ -159,25 +159,31 @@ elseif (isset($_GET['loggedout']) && $current_user <= 0) {
Show Description
-
@@ -284,7 +290,7 @@ elseif (isset($_GET['loggedout']) && $current_user <= 0) {
-
+
diff --git a/js/defiant-js/defiant-latest.js b/js/defiant-js/defiant-latest.js
new file mode 100644
index 0000000..c739d6e
--- /dev/null
+++ b/js/defiant-js/defiant-latest.js
@@ -0,0 +1,687 @@
+/*
+ * Defiant.js v1.2.5
+ * Serch JSON structures plus smart templating with XSLT and XPath.
+ * http://defiantjs.com
+ *
+ * Copyright (c) 2013-2015, Hakan Bilgin
+ * Licensed under the MIT License
+ *
+ * NOTE:
+ * Robbie Antenesse edited line 165's RegExp to search global and case-insensitive in case of multiple contains() groups.
+ */
+
+if (typeof module === "undefined") {
+ var module = { exports: undefined };
+} else {
+ // Node env adaptation goes here...
+}
+
+module.exports = Defiant = (function(window, undefined) {
+ 'use strict';
+
+ var Defiant = {
+ is_ie : /msie/i.test(navigator.userAgent),
+ is_safari : /safari/i.test(navigator.userAgent),
+ env : 'production',
+ xml_decl : '',
+ namespace : 'xmlns:d="defiant-namespace"',
+ tabsize : 4,
+ render: function(template, data) {
+ var processor = new XSLTProcessor(),
+ span = document.createElement('span'),
+ opt = {match: '/'},
+ tmpltXpath,
+ scripts,
+ temp,
+ sorter;
+ // handle arguments
+ switch (typeof(template)) {
+ case 'object':
+ this.extend(opt, template);
+ if (!opt.data) opt.data = data;
+ break;
+ case 'string':
+ opt.template = template;
+ opt.data = data;
+ break;
+ default:
+ throw 'error';
+ }
+ opt.data = JSON.toXML(opt.data);
+ tmpltXpath = '//xsl:template[@name="'+ opt.template +'"]';
+
+ if (!this.xsl_template) this.gatherTemplates();
+
+ if (opt.sorter) {
+ sorter = this.node.selectSingleNode(this.xsl_template, tmpltXpath +'//xsl:for-each//xsl:sort');
+ if (sorter) {
+ if (opt.sorter.order) sorter.setAttribute('order', opt.sorter.order);
+ if (opt.sorter.select) sorter.setAttribute('select', opt.sorter.select);
+ sorter.setAttribute('data-type', opt.sorter.type || 'text');
+ }
+ }
+
+ temp = this.node.selectSingleNode(this.xsl_template, tmpltXpath);
+ temp.setAttribute('match', opt.match);
+ processor.importStylesheet(this.xsl_template);
+ span.appendChild(processor.transformToFragment(opt.data, document));
+ temp.removeAttribute('match');
+
+ if (this.is_safari) {
+ scripts = span.getElementsByTagName('script');
+ for (var i=0, il=scripts.length; i'+ str.replace(/defiant:(\w+)/g, '$1') +'');
+ },
+ getSnapshot: function(data) {
+ return JSON.toXML(data, true);
+ },
+ xmlFromString: function(str) {
+ var parser,
+ doc;
+ str = str.replace(/>\s{1,}<');
+ if (str.trim().match(/<\?xml/) === null) {
+ str = this.xml_decl + str;
+ }
+ if (this.is_ie) {
+ doc = new ActiveXObject('Msxml2.DOMDocument');
+ doc.loadXML(str);
+ if (str.indexOf('xsl:stylesheet') === -1) {
+ doc.setProperty('SelectionLanguage', 'XPath');
+ }
+ } else {
+ parser = new DOMParser();
+ doc = parser.parseFromString(str, 'text/xml');
+ }
+ return doc;
+ },
+ extend: function(src, dest) {
+ for (var content in dest) {
+ if (!src[content] || typeof(dest[content]) !== 'object') {
+ src[content] = dest[content];
+ } else {
+ this.extend(src[content], dest[content]);
+ }
+ }
+ return src;
+ },
+ node: {}
+ };
+
+ return Defiant;
+
+})(this);
+
+
+if (typeof(XSLTProcessor) === 'undefined') {
+
+ // emulating XSLT Processor (enough to be used in defiant)
+ var XSLTProcessor = function() {};
+ XSLTProcessor.prototype = {
+ importStylesheet: function(xsldoc) {
+ this.xsldoc = xsldoc;
+ },
+ transformToFragment: function(data, doc) {
+ var str = data.transformNode(this.xsldoc),
+ span = document.createElement('span');
+ span.innerHTML = str;
+ return span;
+ }
+ };
+
+}
+
+
+// extending STRING
+if (!String.prototype.fill) {
+ String.prototype.fill = function(i,c) {
+ var str = this;
+ c = c || ' ';
+ for (; str.length/,
+ rx_constructor : /<(.+?)( d:contr=".*?")>/,
+ rx_namespace : / xmlns\:d="defiant\-namespace"/,
+ rx_data : /(<.+?>)(.*?)(<\/d:data>)/i,
+ rx_function : /function (\w+)/i,
+ to_xml: function(tree) {
+ var str = this.hash_to_xml(null, tree);
+ return Defiant.xmlFromString(str);
+ },
+ hash_to_xml: function(name, tree, array_child) {
+ var is_array = tree.constructor === Array,
+ elem = [],
+ attr = [],
+ key,
+ val,
+ val_is_array,
+ type,
+ is_attr,
+ cname,
+ constr,
+ cnName,
+ i;
+
+ for (key in tree) {
+ val = tree[key];
+ if (val === null || val === undefined || val.toString() === 'NaN') val = null;
+
+ is_attr = key.slice(0,1) === '@';
+ cname = array_child ? name : key;
+ if (cname == +cname && tree.constructor !== Object) cname = 'd:item';
+ if (val === null) {
+ constr = null;
+ cnName = false;
+ } else {
+ constr = val.constructor;
+ cnName = constr.toString().match(this.rx_function)[1];
+ }
+
+ if (is_attr) {
+ attr.push( cname.slice(1) +'="'+ this.escape_xml(val) +'"' );
+ if (cnName !== 'String') attr.push( 'd:'+ cname.slice(1) +'="'+ cnName +'"' );
+ } else if (val === null) {
+ elem.push( this.scalar_to_xml( cname, val ) );
+ } else {
+ switch (constr) {
+ case Function:
+ // if constructor is function, then it's not a JSON structure
+ // throw ERROR ?
+ break;
+ case Object:
+ elem.push( this.hash_to_xml( cname, val ) );
+ break;
+ case Array:
+ if (key === cname) {
+ val_is_array = val.constructor === Array;
+ if (val_is_array) {
+ i = val.length;
+ while (i--) {
+ if (val[i].constructor === Array) val_is_array = true;
+ if (!val_is_array && val[i].constructor === Object) val_is_array = true;
+ }
+ }
+ elem.push( this.scalar_to_xml( cname, val, val_is_array ) );
+ break;
+ }
+ /* falls through */
+ case String:
+ if (typeof(val) === 'string') {
+ val = val.toString().replace(/\&/g, '&')
+ .replace(/\r|\n/g, '
');
+ }
+ if (cname === '#text') {
+ // prepare map
+ this.map.push(tree);
+ attr.push('d:mi="'+ this.map.length +'"');
+ attr.push('d:constr="'+ cnName +'"');
+ elem.push( this.escape_xml(val) );
+ break;
+ }
+ /* falls through */
+ case Number:
+ case Boolean:
+ if (cname === '#text' && cnName !== 'String') {
+ // prepare map
+ this.map.push(tree);
+ attr.push('d:mi="'+ this.map.length +'"');
+ attr.push('d:constr="'+ cnName +'"');
+ elem.push( this.escape_xml(val) );
+ break;
+ }
+ elem.push( this.scalar_to_xml( cname, val ) );
+ break;
+ }
+ }
+ }
+ if (!name) {
+ name = 'd:data';
+ attr.push(Defiant.namespace);
+ if (is_array) attr.push('d:constr="Array"');
+ }
+ if (name.match(this.rx_validate_name) === null) {
+ attr.push( 'd:name="'+ name +'"' );
+ name = 'd:name';
+ }
+ if (array_child) return elem.join('');
+ // prepare map
+ this.map.push(tree);
+ attr.push('d:mi="'+ this.map.length +'"');
+
+ return '<'+ name + (attr.length ? ' '+ attr.join(' ') : '') + (elem.length ? '>'+ elem.join('') +''+ name +'>' : '/>' );
+ },
+ scalar_to_xml: function(name, val, override) {
+ var attr = '',
+ text,
+ constr,
+ cnName;
+
+ // check whether the nodename is valid
+ if (name.match(this.rx_validate_name) === null) {
+ attr += ' d:name="'+ name +'"';
+ name = 'd:name';
+ override = false;
+ }
+ if (val === null || val.toString() === 'NaN') val = null;
+ if (val === null) return '<'+ name +' d:constr="null"/>';
+ if (val.length === 1 && val[0].constructor === Object) {
+
+ text = this.hash_to_xml(false, val[0]);
+
+ var a1 = text.match(this.rx_node),
+ a2 = text.match(this.rx_constructor);
+ a1 = (a1 !== null)? a1[2]
+ .replace(this.rx_namespace, '')
+ .replace(/>/, '')
+ .replace(/"\/$/, '"') : '';
+ a2 = (a2 !== null)? a2[2] : '';
+
+ text = text.match(this.rx_data);
+ text = (text !== null)? text[2] : '';
+
+ return '<'+ name + a1 +' '+ a2 +' d:type="ArrayItem">'+ text +''+ name +'>';
+ } else if (val.length === 0 && val.constructor === Array) {
+ return '<'+ name +' d:constr="Array"/>';
+ }
+ // else
+ if (override) {
+ return this.hash_to_xml( name, val, true );
+ }
+
+ constr = val.constructor;
+ cnName = constr.toString().match(this.rx_function)[1];
+ text = (constr === Array) ? this.hash_to_xml( 'd:item', val, true )
+ : this.escape_xml(val);
+
+ attr += ' d:constr="'+ cnName +'"';
+ // prepare map
+ this.map.push(val);
+ attr += ' d:mi="'+ this.map.length +'"';
+
+ return (name === '#text') ? this.escape_xml(val) : '<'+ name + attr +'>'+ text +''+ name +'>';
+ },
+ escape_xml: function(text) {
+ return String(text) .replace(//g, '>')
+ .replace(/"/g, '"')
+ .replace(/ /g, ' ');
+ }
+ },
+ doc = interpreter.to_xml.call(interpreter, tree);
+
+ // snapshot distinctly improves performance
+ if (snapshot) {
+ return {
+ doc: doc,
+ src: tree,
+ map: interpreter.map
+ };
+ }
+
+ this.search.map = interpreter.map;
+ return doc;
+ };
+}
+
+if (!JSON.search) {
+ JSON.search = function(tree, xpath, single) {
+ 'use strict';
+
+ var isSnapshot = tree.doc && tree.doc.nodeType,
+ doc = isSnapshot ? tree.doc : JSON.toXML(tree),
+ map = isSnapshot ? tree.map : this.search.map,
+ src = isSnapshot ? tree.src : tree,
+ xres = Defiant.node[ single ? 'selectSingleNode' : 'selectNodes' ](doc, xpath.xTransform()),
+ ret = [],
+ mapIndex,
+ i;
+
+ if (single) xres = [xres];
+ i = xres.length;
+
+ while (i--) {
+ switch(xres[i].nodeType) {
+ case 2:
+ case 3:
+ ret.unshift( xres[i].nodeValue );
+ break;
+ default:
+ mapIndex = +xres[i].getAttribute('d:mi');
+ if (map[mapIndex-1]) ret.unshift( map[mapIndex-1] );
+ }
+ }
+
+ // if environment = development, add search tracing
+ if (Defiant.env === 'development') {
+ this.trace = JSON.mtrace(src, ret, xres);
+ }
+
+ return ret;
+ };
+}
+
+if (!JSON.mtrace) {
+ JSON.mtrace = function(root, hits, xres) {
+ 'use strict';
+
+ var win = window,
+ stringify = JSON.stringify,
+ sroot = stringify( root, null, '\t' ).replace(/\t/g, ''),
+ trace = [],
+ i = 0,
+ il = xres.length,
+ od = il ? xres[i].ownerDocument.documentElement : false,
+ map = this.search.map,
+ hstr,
+ cConstr,
+ fIndex = 0,
+ mIndex,
+ lStart,
+ lEnd;
+
+ for (; i 0)? xI[0] : null;
+ } else {
+ return XNode.selectSingleNode(XPath);
+ }
+};
+
+
+Defiant.node.prettyPrint = function(node) {
+ var root = Defiant,
+ tabs = root.tabsize,
+ decl = root.xml_decl.toLowerCase(),
+ ser,
+ xstr;
+ if (root.is_ie) {
+ xstr = node.xml;
+ } else {
+ ser = new XMLSerializer();
+ xstr = ser.serializeToString(node);
+ }
+ if (root.env !== 'development') {
+ // if environment is not development, remove defiant related info
+ xstr = xstr.replace(/ \w+\:d=".*?"| d\:\w+=".*?"/g, '');
+ }
+ var str = xstr.trim().replace(/(>)\s*(<)(\/*)/g, '$1\n$2$3'),
+ lines = str.split('\n'),
+ indent = -1,
+ i = 0,
+ il = lines.length,
+ start,
+ end;
+ for (; i/g) !== null;
+ //start = lines[i].match(/<[^\/]+>/g) !== null;
+ end = lines[i].match(/<\/[\w\:]+>/g) !== null;
+ if (lines[i].match(/<.*?\/>/g) !== null) start = end = true;
+ if (start) indent++;
+ lines[i] = String().fill(indent, '\t') + lines[i];
+ if (start && end) indent--;
+ if (!start && end) indent--;
+ }
+ return lines.join('\n').replace(/\t/g, String().fill(tabs, ' '));
+};
+
+
+Defiant.node.toJSON = function(xnode, stringify) {
+ 'use strict';
+
+ var interpret = function(leaf) {
+ var obj = {},
+ win = window,
+ attr,
+ type,
+ item,
+ cname,
+ cConstr,
+ cval,
+ text,
+ i, il, a;
+
+ switch (leaf.nodeType) {
+ case 1:
+ cConstr = leaf.getAttribute('d:constr');
+ if (cConstr === 'Array') obj = [];
+ else if (cConstr === 'String' && leaf.textContent === '') obj = '';
+
+ attr = leaf.attributes;
+ i = 0;
+ il = attr.length;
+ for (; i 0) {
for (var i = 0; i < currentDictionary.words.length; i++) {
if (filter == "" || (filter != "" && currentDictionary.words[i].partOfSpeech == filter)) {
- if (search == "" || (search != "" && searchResults.indexOf(htmlEntities(currentDictionary.words[i].name)) >= 0)) {
+ if (search == "" || (search != "" && (searchByWord || searchBySimple || searchByLong) && searchResults.indexOf(currentDictionary.words[i].wordId) >= 0)) {
if (!currentDictionary.words[i].hasOwnProperty("pronunciation")) {
currentDictionary.words[i].pronunciation = ""; //Account for new property
}
@@ -228,27 +243,61 @@ function ShowDictionary() {
function DictionaryEntry(itemIndex) {
var entryText = "🔗";
- var searchTerm = htmlEntities(document.getElementById("searchBox").value);
- var searchRegEx = new RegExp(searchTerm, "gi");
+ var searchTerm = document.getElementById("searchBox").value;
+ var searchByWord = document.getElementById("searchOptionWord").checked;
+ var searchBySimple = document.getElementById("searchOptionSimple").checked;
+ var searchByLong = document.getElementById("searchOptionLong").checked;
+ var searchIgnoreCase = !document.getElementById("searchCaseSensitive").checked; //It's easier to negate case here instead of negating it every use since ignore case is default.
+ var searchIgnoreDiacritics = document.getElementById("searchIgnoreDiacritics").checked;
+
+ var searchRegEx = new RegExp("(" + ((searchIgnoreDiacritics) ? removeDiacritics(searchTerm) + "|" + searchTerm : searchTerm) + ")", "g" + ((searchIgnoreCase) ? "i" : ""));
- entryText += "" + ((searchTerm != "" && document.getElementById("searchOptionWord").checked) ? currentDictionary.words[itemIndex].name.replace(searchRegEx, "" + searchTerm + "") : currentDictionary.words[itemIndex].name) + "";
+ entryText += "";
+
+ if (searchTerm != "" && searchByWord) {
+ entryText += htmlEntitiesParse(currentDictionary.words[itemIndex].name).replace(searchRegEx, "$1");
+ } else {
+ entryText += currentDictionary.words[itemIndex].name;
+ }
+
+ entryText += "";
if (currentDictionary.words[itemIndex].pronunciation != "") {
- entryText += "" + marked(htmlEntitiesParse(currentDictionary.words[itemIndex].pronunciation)).replace("","").replace("
","") + "";
+ entryText += "";
+ entryText += marked(htmlEntitiesParse(currentDictionary.words[itemIndex].pronunciation)).replace("","").replace("
","");
+ entryText += "";
}
if (currentDictionary.words[itemIndex].partOfSpeech != "") {
- entryText += "" + currentDictionary.words[itemIndex].partOfSpeech + "";
+ entryText += "";
+ entryText += currentDictionary.words[itemIndex].partOfSpeech;
+ entryText += "";
}
entryText += "
";
if (currentDictionary.words[itemIndex].simpleDefinition != "") {
- entryText += "" + ((searchTerm != "" && document.getElementById("searchOptionSimple").checked) ? currentDictionary.words[itemIndex].simpleDefinition.replace(searchRegEx, "" + searchTerm + "") : currentDictionary.words[itemIndex].simpleDefinition) + "";
+ entryText += "";
+
+ if (searchTerm != "" && searchBySimple) {
+ entryText += htmlEntitiesParse(currentDictionary.words[itemIndex].simpleDefinition).replace(searchRegEx, "$1");
+ } else {
+ entryText += currentDictionary.words[itemIndex].simpleDefinition;
+ }
+
+ entryText += "";
}
if (currentDictionary.words[itemIndex].longDefinition != "") {
- entryText += "" + ((searchTerm != "" && document.getElementById("searchOptionLong").checked) ? marked(htmlEntitiesParse(currentDictionary.words[itemIndex].longDefinition)).replace(searchRegEx, "" + searchTerm + "") : marked(htmlEntitiesParse(currentDictionary.words[itemIndex].longDefinition))) + "";
+ entryText += "";
+
+ if (searchTerm != "" && searchByLong) {
+ entryText += marked(htmlEntitiesParse(currentDictionary.words[itemIndex].longDefinition).replace(searchRegEx, "$1"));
+ } else {
+ entryText += marked(htmlEntitiesParse(currentDictionary.words[itemIndex].longDefinition));
+ }
+
+ entryText += "";
}
if (!currentDictionary.settings.isComplete) {
@@ -619,6 +668,14 @@ function stripHtmlEntities(string) {
return String(string).replace(/&/g, '').replace(/</g, '').replace(/>/g, '').replace(/"/g, '').replace(/'/g, "").replace(/
/g, '');
}
+function htmlEntitiesParseForSearchEntry(string) {
+ return String(string).replace(/"/g, '%%').replace(/'/g, "``");
+}
+
+function htmlEntitiesParseForSearch(string) {
+ return String(string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '%%').replace(/'/g, "``");
+}
+
function dynamicSort(property) {
/* Retrieved from http://stackoverflow.com/a/4760279
Usage: theArray.sort(dynamicSort("objectProperty"));*/
diff --git a/js/ui.js b/js/ui.js
index c786481..326d812 100644
--- a/js/ui.js
+++ b/js/ui.js
@@ -155,6 +155,19 @@ function ToggleDescription() {
}
}
+function ToggleSearchFilter() {
+ var searchFilterToggle = document.getElementById("searchFilterToggle");
+ var searchFilterArea = document.getElementById("searchFilterArea");
+
+ if (searchFilterArea.style.display == "none") {
+ searchFilterArea.style.display = "block";
+ searchFilterToggle.innerHTML = "Hide Search/Filter Options";
+ } else {
+ searchFilterArea.style.display = "none";
+ searchFilterToggle.innerHTML = "Search/Filter Options";
+ }
+}
+
function ShowInfo(text) {
if (text == "terms") {
document.getElementById("infoText").innerHTML = termsText;