Commit d6214e5f authored by Dominik Hebeler's avatar Dominik Hebeler
Browse files

Merge branch '1105-remove-jquery' into 'development'

Resolve "Remove Jquery"

Closes #1105

See merge request !1822
parents ec190fde 7e53f9bb
$(document).ready(function () {
$(".amount-custom").click(function () {
setTimeout(function () {
$("#custom-amount").focus();
}, 100)
document.addEventListener("DOMContentLoaded", (event) => {
document.querySelectorAll(".amount-custom").forEach(element => {
element.onclick = (e) => {
setTimeout(() => {
document.querySelector("#custom-amount").focus();
}, 100);
}
});
});
\ No newline at end of file
......@@ -2,27 +2,27 @@
* Flag ctrlInfo is used for initial display of the navigation box
*/
var ctrlInfo = false;
$(document).ready(function () {
document.addEventListener("DOMContentLoaded", (event) => {
// Add entry point for tabbing to the first result
$('.result, .ad').first().attr("id", "results-entry");
document.querySelectorAll('.result, .ad')[0].setAttribute("id", "results-entry");
// Initially focus the searchbar
});
/**
* Simulate a click on enter keypress when focused on labels
*/
$('label').on('keydown', function (e) {
if (e.keyCode == '13') {
$(this).click();
$('a', this)
document.querySelectorAll('label').forEach((element) => {
element.onkeydown = (e) => {
if (e.keyCode == '13') {
e.srcElement.click();
}
}
});
/**
* Handles tab keypress and escape keypress
*/
$(document).on('keydown', function (e) {
document.onkeydown = (e) => {
e = e || window.event;
// On first tab keypress there is special behaviour and the ctrlInfo flag is set
if (!ctrlInfo && e.keyCode == '9') {
......@@ -32,14 +32,15 @@ $(document).on('keydown', function (e) {
} else if (e.keyCode == '27') {
escKeyPressed();
}
});
};
/**
* Shows the navigation box and focuses the first <a> tag
*/
function focusNavBox() {
$('#keyboard-nav-info').show();
$('#keyboard-nav-info a').first().focus();
document.querySelector("#keyboard-nav-info").style.display = "inherit";
document.querySelectorAll("#keyboard-nav-info a")[0].focus();
}
/**
......@@ -47,34 +48,36 @@ function focusNavBox() {
*/
function escKeyPressed() {
focusNavBox();
$('input[type="checkbox"]').removeAttr('checked');
document.querySelectorAll('input[type="checkbox"]').forEach((element) => {
element.checked = false;
});
}
/**
* Focuses the first <a> tag of the first result
*/
function focusResults() {
$('#results-entry .result-title a').focus();
document.querySelector('#results-entry .result-title a').focus();
}
/**
* Focuses the first <a> tag of the focus options
*/
function focusFoki() {
$('#foki a').first().focus();
document.querySelector("#foki a").focus();
}
/**
* Focuses the search settings
*/
function focusSettings() {
$('#settings a').focus();
document.querySelector('#settings a').focus();
}
/**
* Focuses the first <tag> of the sidebar
*/
function focusNavigation() {
$('#sidebarToggle').prop('checked', true);
$('.sidebar-list a').first().focus();
document.querySelector("#sidebarToggle").checked = true;
document.querySelector(".sidebar-list a").focus();
}
\ No newline at end of file
if (typeof NodeList !== "undefined" && NodeList.prototype && !NodeList.prototype.forEach) {
// Yes, there's really no need for `Object.defineProperty` here
NodeList.prototype.forEach = Array.prototype.forEach;
}
/**
* All results are stored in the global object 'results'
*/
*/
results = new Results();
$(document).ready(function () {
document.addEventListener("DOMContentLoaded", (event) => {
if(document.readyState == 'complete'){
initResultSaver();
}else{
document.addEventListener("readystatechange", e => {
if (document.readyState === 'complete') {
initResultSaver();
}
});
}
});
function initResultSaver() {
// Add all saved results
results.loadAllResults();
// Sort all results
results.sortResults();
// Update the visualization
results.updateResultPageInterface();
});
}
/**
* Load all saved results and sort them
......@@ -99,7 +116,7 @@ Results.prototype.deleteAllResults = function () {
}
}
// Remove all keys saved in the keys array from localstorage
$.each(keys, function (index, value) {
keys.forEach(value => {
localStorage.removeItem(value);
});
};
......@@ -110,22 +127,25 @@ Results.prototype.deleteAllResults = function () {
Results.prototype.updateResultPageInterface = function () {
if (this.results.length === 0) {
// If there are no saved-results left, remove the savedFoki element
$('#savedFoki').remove();
document.querySelectorAll('#savedFoki').forEach(element => {
element.remove();
});
return;
}
if ($('#savedFoki').length === 0) {
if (document.querySelector('#savedFoki') == null || document.querySelector('#savedFoki').length === 0) {
// If there is no savedFoki element yet, create it
var tabPanel = $('\
<div id="savedFoki">\
<h1>' + t('result-saver.title') + '</h1>\
</div>\
');
$('#additions-container').prepend(tabPanel);
var template = document.createElement("div");
template.innerHTML = '<div id="savedFoki">\
<h1>' + t('result-saver.title') + '</h1>\
</div>';
var tabPanel = template.firstChild;
document.querySelector('#additions-container').prepend(tabPanel);
} else {
// If there already is a savedFoki element, get it
$('#savedFoki').html('');
var tabPanel = $('#savedFoki');
var tabPanel = document.querySelector("#savedFoki");
tabPanel.innerHTML = "";
}
// Add the full savedFoki element to the tabPanel
this.addToContainer(tabPanel);
};
......@@ -138,49 +158,50 @@ Results.prototype.updateResultPageInterface = function () {
Results.prototype.addToContainer = function (container) {
// Create the saver-options element, which is a bar containing
// options for filtering, sorting and deleting all results
var options = $('\
<div id="saver-options">\
<div class="saver-option saver-option-filter">\
<input style="font-family: \'Font Awesome 5 Free\', sans-serif;" class="form-control" type="text" placeholder="&#xf0b0 ' + t('result-saver.filter') + '">\
</div>\
<div class="saver-option saver-option-sort">\
<select class="form-control" style="font-family: \'Font Awesome 5 Free\', sans-serif;">\
<option value="chronological" style="font-family: \'Font Awesome 5 Free\', sans-serif;">&#xf017 ' + t('result-saver.sort.chronological') + '</option>\
<option value="rank" style="font-family: \'Font Awesome 5 Free\', sans-serif;">&#xf162 ' + t('result-saver.sort.ranking') + '</option>\
<option value="alphabetical" style="font-family: \'Font Awesome 5 Free\', sans-serif;">&#xf15d ' + t('result-saver.sort.alphabetical') + '</option>\
</select>\
</div>\
<div class="saver-option saver-option-delete">\
<button class="btn btn-danger btn-md" id="saver-options-delete-btn">\
<i class="fa fa-trash-o" aria-hidden="true"></i>\
' + t('result-saver.deleteAll') + '\
</button>\
</div>\
var template = document.createElement("div");
template.innerHTML = '<div id="saver-options">\
<div class="saver-option saver-option-filter">\
<input style="font-family: \'Font Awesome 5 Free\', sans-serif;" class="form-control" type="text" placeholder="&#xf0b0 ' + t('result-saver.filter') + '">\
</div>\
<div class="saver-option saver-option-sort">\
<select class="form-control" style="font-family: \'Font Awesome 5 Free\', sans-serif;">\
<option value="chronological" style="font-family: \'Font Awesome 5 Free\', sans-serif;">&#xf017 ' + t('result-saver.sort.chronological') + '</option>\
<option value="rank" style="font-family: \'Font Awesome 5 Free\', sans-serif;">&#xf162 ' + t('result-saver.sort.ranking') + '</option>\
<option value="alphabetical" style="font-family: \'Font Awesome 5 Free\', sans-serif;">&#xf15d ' + t('result-saver.sort.alphabetical') + '</option>\
</select>\
</div>\
<div class="saver-option saver-option-delete">\
<button class="btn btn-danger btn-md" id="saver-options-delete-btn">\
<i class="fa fa-trash-o" aria-hidden="true"></i>\
' + t('result-saver.deleteAll') + '\
</button>\
</div>\
');
</div>';
var options = template.firstChild;
// Set the initial value for the sorting select, based on this.sort
$(options).find('select').val(this.sort);
options.querySelector("select").value = this.sort;
// Add the saver-options element to the given container
$(container).append(options);
container.append(options);
/* ~~~ Filter ~~~ */
// When the user is done typing into the filter input field,
// Filter all results, only showing ones that contain the filer
$(options).find('input').keyup(function () {
options.querySelectorAll("input").forEach(element => {
// Get the entered filter
var search = $(this).val();
var search = element.value;
// Hide all results that do not contain the entered filter
$('#savedFoki .saved-result-content').each(function (index, value) {
document.querySelectorAll('#savedFoki .saved-result-content').forEach(value => {
// check for filter in all of the elements html-content
var html = $(this).html();
var html = value.innerHTML;
if (html.toLowerCase().indexOf(search.toLowerCase()) === -1) {
// hide entire result block
$(value).parent().addClass('hidden');
value.parentNode.classList.add('hidden');
} else {
// show entire result block
$(value).parent().removeClass('hidden');
value.parentNode.classList.remove("hidden");
}
});
});
......@@ -188,23 +209,27 @@ Results.prototype.addToContainer = function (container) {
/* ~~~ Sort ~~~ */
// When the sorting select value is changed,
// Sort all results with the selected sorting function and update their appearance
$(options).find('select').change(function () {
var sort = $(this).val();
results.sort = sort;
results.sortResults(sort).updateResultPageInterface();
options.querySelectorAll("select").forEach(element => {
element.onchange = (e) => {
var sort = element.value;
results.sort = sort;
results.sortResults(sort).updateResultPageInterface();
};
});
/* ~~~ Delete ~~~ */
// When the delete button is clicked,
// Delete all results and update their appearance
$(options).find('#saver-options-delete-btn').click(function (event) {
results.deleteAllResults();
results.updateResultPageInterface();
options.querySelectorAll('#saver-options-delete-btn').forEach(element => {
element.onclick = (e) => {
results.deleteAllResults();
results.updateResultPageInterface();
}
});
// Append all results available
$.each(this.results, function (index, result) {
$(container).append(result.toHtml());
this.results.forEach(result => {
container.append(result.toHtml());
});
};
......@@ -272,7 +297,7 @@ Result.prototype.load = function () {
this.anonym = result.anonym;
this.description = result.description;
this.added = result.added;
this.index = -result.index;
this.index = result.index;
this.rank = result.rank;
return true;
......@@ -351,46 +376,51 @@ Result.prototype.remove = function () {
*/
Result.prototype.toHtml = function () {
// Create the saved-result element
var result = $('\
<div class="saved-result result" data-count="' + this.index + '">\
<div class="saved-result-remover remover" title="' + t('result-saver.delete') + '">\
<i class="fa fa-trash"></i>\
</div>\
<div class="saved-result-content">\
<div class="result-header">\
<div class="result-headline">\
<h2 class="result-title">\
<a href="' + this.link + '" target="_blank" data-count="1" rel="noopener">\
' + this.title + '\
</a>\
</h2>\
<a class="result-hoster" href="' + this.hosterLink + '" target="_blank" data-count="1" rel="noopener">\
' + this.hosterName + '\
var template = document.createElement("div");
template.innerHTML = '<div class="saved-result result" data-count="' + this.index + '">\
<div class="saved-result-remover remover" title="' + t('result-saver.delete') + '">\
<i class="fa fa-trash"></i>\
</div>\
<div class="saved-result-content">\
<div class="result-header">\
<div class="result-headline">\
<h2 class="result-title">\
<a href="' + this.link + '" target="_blank" data-count="1" rel="noopener">\
' + this.title + '\
</a>\
</div>\
<a class="result-link" href="' + this.link + '" target="_blank" rel="noopener">\
' + this.anzeigeLink + '\
</a>\
<div class="result-body">\
<div class="description">' + this.description + '</div>\
</div>\
<div class="result-footer">\
<a class="result-open" href="' + this.link + '" target="_self" rel="noopener">\
' + t('result-saver.save.this') + '\
</a>\
<a class="result-open" href="' + this.link + '" target="_blank" rel="noopener">\
' + t('result-saver.save.newtab') + '\
</a>\
<a class="result-open-proxy" onmouseover="$(this).popover(\'show\');" onmouseout="$(this).popover(\'hide\');" data-toggle="popover" data-placement="auto right" data-container="body" data-content="Der Link wird anonymisiert geöffnet. Ihre Daten werden nicht zum Zielserver übertragen. Möglicherweise funktionieren manche Webseiten nicht wie gewohnt." href="' + this.anonym + '" target="_blank" rel="noopener" data-original-title="" title="">\
' + t('result-saver.save.anonymous') + '\
</h2>\
<a class="result-hoster" href="' + this.hosterLink + '" target="_blank" data-count="1" rel="noopener">\
' + this.hosterName + '\
</a>\
</div>\
<a class="result-link" href="' + this.link + '" target="_blank" rel="noopener">\
' + this.anzeigeLink + '\
</a>\
<div class="result-body">\
<div class="description">' + this.description + '</div>\
</div>\
<div class="result-footer">\
<a class="result-open" href="' + this.link + '" target="_self" rel="noopener">\
' + t('result-saver.save.this') + '\
</a>\
<a class="result-open" href="' + this.link + '" target="_blank" rel="noopener">\
' + t('result-saver.save.newtab') + '\
</a>\
<a class="result-open-proxy" href="' + this.anonym + '" target="_blank" rel="noopener" title="Der Link wird anonymisiert geöffnet. Ihre Daten werden nicht zum Zielserver übertragen. Möglicherweise funktionieren manche Webseiten nicht wie gewohnt.">\
' + t('result-saver.save.anonymous') + '\
</a>\
</div>\
</div>');
</div>\
</div>';
var result = template.firstChild;
// Add a click listener to the remover, that removes the result on click
$(result).find('.remover').click({ caller: this }, function (event) {
event.data.caller.remove();
var caller = this;
result.querySelectorAll(".remover").forEach(element => {
element.onclick = (e) => {
caller.remove();
};
});
return result;
......@@ -402,17 +432,17 @@ Result.prototype.toHtml = function () {
*/
function resultSaver(index) {
// Remember the original result element
var original = $('.result[data-count=' + index + ']');
var original = document.querySelector('.result[data-count="' + index + '"]');
// Read the necessary data from the result html
var title = $('.result[data-count=' + index + '] .result-title a').html().trim();
var link = $('.result[data-count=' + index + '] .result-title a').attr('href').trim();
var hosterName = $('.result[data-count=' + index + '] .result-hoster').html().trim();
var hosterLink = $('.result[data-count=' + index + '] .result-hoster').attr('href');
hosterLink = hosterLink?hosterLink.trim():"#";
var anzeigeLink = $('.result[data-count=' + index + '] .result-link').html().trim();
var description = $('.result[data-count=' + index + '] .result-description').html().trim();
var anonym = $('.result[data-count=' + index + '] .result-open-proxy').attr('href').trim();
var title = document.querySelector('.result[data-count="' + index + '"] .result-title a').innerHTML.trim();
var link = document.querySelector('.result[data-count="' + index + '"] .result-title a').href.trim();
var hosterName = document.querySelector('.result[data-count="' + index + '"] .result-subheadline > a').title.trim();
var hosterLink = document.querySelector('.result[data-count="' + index + '"] .result-hoster').href;
hosterLink = hosterLink ? hosterLink.trim() : "#";
var anzeigeLink = document.querySelector('.result[data-count="' + index + '"] .result-link').innerHTML.trim();
var description = document.querySelector('.result[data-count="' + index + '"] .result-description').innerHTML.trim();
var anonym = document.querySelector('.result[data-count="' + index + '"] .result-open-proxy').href.trim();
// Create the result object
var result = new Result(title, link, hosterName, hosterLink, anzeigeLink, description, anonym, index, null);
......@@ -427,8 +457,8 @@ function resultSaver(index) {
results.updateResultPageInterface();
// Animate the result transfer to the saved results
var transferTarget = $('.saved-result[data-count=' + index + ']');
if (original.length > 0 && transferTarget.length > 0) {
$(original).transfer({ to: transferTarget, duration: 1000 });
}
// var transferTarget = $('.saved-result[data-count=' + index + ']');
// if (original.length > 0 && transferTarget.length > 0) {
// $(original).transfer({ to: transferTarget, duration: 1000 });
// }
}
$(document).ready(function () {
document.addEventListener("DOMContentLoaded", (event) => {
if(document.readyState == 'complete'){
initialize();
}else{
document.addEventListener("readystatechange", e => {
if (document.readyState == 'complete') {
initialize();
}
});
}
});
function initialize(){
botProtection();
enableFormResetter();
loadMoreResults();
});
}
let link, newtab, top;
function botProtection() {
$('.result').find('a').click(function (e) {
var link = $(this).attr('href');
var newtab = false;
var top = false;
if ($(this).attr('target') == '_blank' || e.ctrlKey || e.metaKey) {
newtab = true;
} else if ($(this).attr('target') == "_top") {
top = true;
}
document.querySelectorAll(".result a").forEach((element) => {
element.onclick = e => {
link = element.href;
newtab = false;
top = false;
if (element.target == '_blank' || e.ctrlKey || e.metaKey) {
newtab = true;
} else if (element.target == "_top") {
top = true;
}
$.ajax({
url: '/img/cat.jpg',
type: 'post',
data: {
mm: $('meta[name=mm]').attr('content')
},
timeout: 2000
})
.always(function () {
if (!newtab) {
if (top) {
window.top.location.href = link;
} else {
document.location.href = link;
fetch("/img/cat.png", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: "mm=" + document.querySelector('meta[name="mm"]').content
})
.then(response => {
if (!newtab) {
if (top) {
window.top.location.href = link;
} else {
document.location.href = link;
}
}
}
});
return newtab;
});
return newtab;
};
});
}
function enableFormResetter() {
var deleteButton = $("#search-delete-btn");
var deleteButton = document.querySelector("#search-delete-btn");
var timeout = null;
$(deleteButton).click(function () {
deleteButton.onclick = (e) => {
if (timeout != null) {
clearTimeout(timeout);
timeout = null;
}
$("input[name=eingabe]").val("");
$("input[name=eingabe]").focus();
});
$("input[name=eingabe]").focusin(function () {
$(deleteButton).css("display", "initial");
document.querySelector("input[name=\"eingabe\"]").value = "";
document.querySelector("input[name=\"eingabe\"]").focus();
};
document.querySelector("input[name=\"eingabe\"]").addEventListener("focusin", (e) => {
deleteButton.style.display = "initial";
});
$("input[name=eingabe]").focusout(function () {
document.querySelector("input[name=\"eingabe\"]").addEventListener("focusout", (e) => {
timeout = window.setTimeout(function () {
$(deleteButton).css("display", "none");
deleteButton.style.display = "none";
timeout = null;
}, 500);
});
}
function loadMoreResults() {
var searchKey = $("meta[name=searchkey]").attr("content");
var searchKey = document.querySelector("meta[name=searchkey]").content
var updateUrl = document.location.href;
updateUrl += "&loadMore=loader_" + searchKey + "&script=yes";
......@@ -75,61 +94,80 @@ function loadMoreResults() {
clearInterval(resultLoader);
}
currentlyLoading = true;
$.getJSON(updateUrl, function (data) {
// Check if we can clear the interval (once every searchengine has answered)
if (!data || data.finished) {
clearInterval(resultLoader);
}
// If there are new results we can add them
if (typeof data.newResults != "undefined") {
for (var key in data.newResults) {