Mike Tzou
6 years ago
committed by
GitHub
11 changed files with 1377 additions and 62 deletions
@ -0,0 +1,69 @@
@@ -0,0 +1,69 @@
|
||||
<style type="text/css"> |
||||
#installSearchPluginContainer { |
||||
margin: 10px; |
||||
} |
||||
|
||||
#installSearchPluginContainer button { |
||||
padding: 3px 20px; |
||||
} |
||||
|
||||
#newPluginPath { |
||||
width: 100%; |
||||
line-height: 2em; |
||||
} |
||||
</style> |
||||
|
||||
<div id="installSearchPluginContainer"> |
||||
<h2>QBT_TR(Plugin path:)QBT_TR[CONTEXT=PluginSourceDlg]</h2> |
||||
|
||||
<div> |
||||
<input type="text" id="newPluginPath" placeholder="QBT_TR(URL or local directory)QBT_TR[CONTEXT=PluginSourceDlg]" autocorrect="off" autocapitalize="none" /> |
||||
<div style="margin-top: 10px; text-align: center;"> |
||||
<button id="newPluginCancel" onclick="closeSearchWindow('installSearchPlugin');">QBT_TR(Cancel)QBT_TR[CONTEXT=PluginSourceDlg]</button> |
||||
<button id="newPluginOk" onclick="newPluginOk();">QBT_TR(Ok)QBT_TR[CONTEXT=PluginSourceDlg]</button></div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<script> |
||||
'use strict'; |
||||
|
||||
var initInstallSearchPlugin = function() { |
||||
var installSearchPluginKeyboardEvents = new Keyboard({ |
||||
defaultEventType: 'keydown', |
||||
events: { |
||||
'enter': function (e) { |
||||
// accept enter key as a click |
||||
new Event(e).stop(); |
||||
|
||||
var elem = e.event.srcElement; |
||||
if ((elem.id === "newPluginPath") || (elem.id === "newPluginOk")) |
||||
newPluginOk(); |
||||
else if (elem.id === "newPluginCancel") |
||||
closeSearchWindow('installSearchPlugin'); |
||||
} |
||||
} |
||||
}); |
||||
installSearchPluginKeyboardEvents.activate(); |
||||
|
||||
$('newPluginPath').select(); |
||||
}; |
||||
|
||||
var newPluginOk = function() { |
||||
var path = $("newPluginPath").get("value").trim(); |
||||
if (path) |
||||
new Request({ |
||||
url: 'api/v2/search/installPlugin', |
||||
noCache: true, |
||||
method: 'post', |
||||
data: { |
||||
sources: path, |
||||
}, |
||||
onRequest: function(){ |
||||
closeSearchWindow('installSearchPlugin'); |
||||
} |
||||
}).send(); |
||||
}; |
||||
|
||||
initInstallSearchPlugin(); |
||||
</script> |
@ -0,0 +1,644 @@
@@ -0,0 +1,644 @@
|
||||
<style type="text/css"> |
||||
#searchPattern { |
||||
width: 500px; |
||||
line-height: 2em; |
||||
padding: 1px 5px 1px 2em; |
||||
background-image: url("../images/qbt-theme/edit-find.svg"); |
||||
background-repeat: no-repeat; |
||||
background-size: 1.5em; |
||||
background-position: left; |
||||
} |
||||
|
||||
#categorySelect { |
||||
width: 150px; |
||||
height: 20px; |
||||
} |
||||
|
||||
#pluginsSelect { |
||||
width: 150px; |
||||
height: 20px; |
||||
} |
||||
|
||||
#startSearchButton { |
||||
width: 90px; |
||||
height: 20px; |
||||
} |
||||
|
||||
#searchResultsNoPlugins { |
||||
height: calc(100% - 110px); |
||||
} |
||||
|
||||
#searchResultsNoPlugins table { |
||||
height: 100%; |
||||
width: 100%; |
||||
text-align: center; |
||||
} |
||||
|
||||
#searchResultsFilters { |
||||
height: 30px; |
||||
overflow: auto; |
||||
} |
||||
|
||||
#searchInNameFilter { |
||||
width: 150px; |
||||
margin-right: 20px; |
||||
} |
||||
|
||||
#searchMinSeedsFilter, #searchMaxSeedsFilter, #searchMinSizeFilter, #searchMaxSizeFilter { |
||||
width: 4em; |
||||
} |
||||
|
||||
#downloadSearchTorrent, #openSearchTorrentDescription, #copyDescriptionPageUrl { |
||||
line-height: 1.5em; |
||||
} |
||||
|
||||
#manageSearchPlugins { |
||||
line-height: 1.5em; |
||||
float: right; |
||||
} |
||||
</style> |
||||
|
||||
<div id="searchResults"> |
||||
<div style="overflow: hidden; height: 70px;"> |
||||
<div style="margin: 20px 0; height: 30px;"> |
||||
<input type="text" id="searchPattern" class="searchInputField" placeholder="QBT_TR(Search)QBT_TR[CONTEXT=SearchEngineWidget]" autocorrect="off" autocapitalize="none" /> |
||||
<select id="categorySelect" class="searchInputField" onchange="categorySelected()"></select> |
||||
<select id="pluginsSelect" class="searchInputField" onchange="pluginSelected()"></select> |
||||
<button id="startSearchButton" class="searchInputField" onclick="startStopSearch()">QBT_TR(Search)QBT_TR[CONTEXT=SearchEngineWidget]</button> |
||||
</div> |
||||
</div> |
||||
|
||||
<div id="searchResultsNoPlugins"> |
||||
<table> |
||||
<tbody> |
||||
<tr> |
||||
<td> |
||||
There aren't any search plugins installed.<br/>Click the "Search plugins..." button at the bottom right of the window to install some. |
||||
</td> |
||||
</tr> |
||||
</tbody> |
||||
</table> |
||||
<span></span> |
||||
</div> |
||||
|
||||
<div id="searchResultsFilters"> |
||||
<input type="text" id="searchInNameFilter" placeholder="QBT_TR(Filter)QBT_TR[CONTEXT=SearchEngineWidget]" autocorrect="off" autocapitalize="none" /> |
||||
|
||||
<span>QBT_TR(Results (showing)QBT_TR[CONTEXT=SearchEngineWidget] <span id="numSearchResultsVisible" class="numSearchResults">0</span> QBT_TR(out of)QBT_TR[CONTEXT=SearchEngineWidget] <span id="numSearchResultsTotal" class="numSearchResults">0</span>):</span> |
||||
|
||||
<div style="display: inline-block; float: right;"> |
||||
<label for="searchInTorrentName" style="margin-left: 15px;">QBT_TR(Search in:)QBT_TR[CONTEXT=SearchEngineWidget]</label> |
||||
<select id="searchInTorrentName" onchange="searchInTorrentName()"> |
||||
<option value="names">QBT_TR(Torrent names only)QBT_TR[CONTEXT=SearchEngineWidget]</option> |
||||
<option value="everywhere">QBT_TR(Everywhere)QBT_TR[CONTEXT=SearchEngineWidget]</option> |
||||
</select> |
||||
|
||||
<span style="margin-left: 15px;">QBT_TR(Seeds:)QBT_TR[CONTEXT=SearchEngineWidget]</span> |
||||
<input type="number" min="0" max="1000" id="searchMinSeedsFilter" value="0" onchange="searchSeedsFilterChanged()"> |
||||
<span>to</span> |
||||
<input type="number" min="0" max="1000" id="searchMaxSeedsFilter" value="0" onchange="searchSeedsFilterChanged()"> |
||||
|
||||
<span style="margin-left: 15px;">QBT_TR(Size:)QBT_TR[CONTEXT=SearchEngineWidget]</span> |
||||
<input type="number" min="0" max="1000" step=".01" value="0.00" id="searchMinSizeFilter" onchange="searchSizeFilterChanged()"> |
||||
<select id="searchMinSizePrefix" onchange="searchSizeFilterPrefixChanged()"> |
||||
<option value="0">QBT_TR(B)QBT_TR[CONTEXT=misc]</option> |
||||
<option value="1">QBT_TR(KiB)QBT_TR[CONTEXT=misc]</option> |
||||
<option value="2" selected>QBT_TR(MiB)QBT_TR[CONTEXT=misc]</option> |
||||
<option value="3">QBT_TR(GiB)QBT_TR[CONTEXT=misc]</option> |
||||
<option value="4">QBT_TR(TiB)QBT_TR[CONTEXT=misc]</option> |
||||
<option value="5">QBT_TR(PiB)QBT_TR[CONTEXT=misc]</option> |
||||
<option value="6">QBT_TR(EiB)QBT_TR[CONTEXT=misc]</option> |
||||
</select> |
||||
<span>to</span> |
||||
<input type="number" min="0" max="1000" step=".01" value="0.00" id="searchMaxSizeFilter" onchange="searchSizeFilterChanged()"> |
||||
<select id="searchMaxSizePrefix" onchange="searchSizeFilterPrefixChanged()"> |
||||
<option value="0">QBT_TR(B)QBT_TR[CONTEXT=misc]</option> |
||||
<option value="1">QBT_TR(KiB)QBT_TR[CONTEXT=misc]</option> |
||||
<option value="2" selected>QBT_TR(MiB)QBT_TR[CONTEXT=misc]</option> |
||||
<option value="3">QBT_TR(GiB)QBT_TR[CONTEXT=misc]</option> |
||||
<option value="4">QBT_TR(TiB)QBT_TR[CONTEXT=misc]</option> |
||||
<option value="5">QBT_TR(PiB)QBT_TR[CONTEXT=misc]</option> |
||||
<option value="6">QBT_TR(EiB)QBT_TR[CONTEXT=misc]</option> |
||||
</select> |
||||
</div> |
||||
</div> |
||||
|
||||
<div id="searchResultsTableContainer"> |
||||
<div id="searchResultsTableFixedHeaderDiv" class="dynamicTableFixedHeaderDiv"> |
||||
<table class="dynamicTable unselectable" style="position:relative;"> |
||||
<thead> |
||||
<tr class="dynamicTableHeader"></tr> |
||||
</thead> |
||||
</table> |
||||
</div> |
||||
<div id="searchResultsTableDiv" class="dynamicTableDiv"> |
||||
<table class="dynamicTable unselectable"> |
||||
<thead> |
||||
<tr class="dynamicTableHeader"></tr> |
||||
</thead> |
||||
<tbody></tbody> |
||||
</table> |
||||
</div> |
||||
</div> |
||||
|
||||
<div style="height: 30px; padding-top: 10px;"> |
||||
<button id="downloadSearchTorrent" onclick="downloadSearchTorrent()">QBT_TR(Download)QBT_TR[CONTEXT=SearchEngineWidget]</button> |
||||
<button id="openSearchTorrentDescription" onclick="openSearchTorrentDescription()">QBT_TR(Go to description page)QBT_TR[CONTEXT=SearchEngineWidget]</button> |
||||
<button class="copyToClipboard" id="copyDescriptionPageUrl">QBT_TR(Copy description page URL)QBT_TR[CONTEXT=SearchEngineWidget]</button> |
||||
<button id="manageSearchPlugins" onclick="manageSearchPlugins()">QBT_TR(Search plugins...)QBT_TR[CONTEXT=SearchEngineWidget]</button> |
||||
</div> |
||||
</div> |
||||
|
||||
<script> |
||||
'use strict'; |
||||
|
||||
var loadSearchResultsTimer; |
||||
var loadSearchPluginsTimer; |
||||
var searchResultsRowId = 0; |
||||
var searchRunning = false; |
||||
var requestCount = 0; |
||||
var searchPlugins = []; |
||||
var prevSearchPluginsResponse; |
||||
var searchPattern = ""; |
||||
var searchFilterPattern = ""; |
||||
var searchSeedsFilter = { |
||||
min: 0, |
||||
max: 0 |
||||
}; |
||||
var searchSizeFilter = { |
||||
min: 0.00, |
||||
minUnit: 2, // B = 0, KiB = 1, MiB = 2, GiB = 3, TiB = 4, PiB = 5, EiB = 6 |
||||
max: 0.00, |
||||
maxUnit: 3 |
||||
}; |
||||
var prevNameFilterValue; |
||||
var selectedCategory = "QBT_TR(All categories)QBT_TR[CONTEXT=SearchEngineWidget]"; |
||||
var selectedPlugin = "all"; |
||||
var prevSelectedPlugin; |
||||
var activeSearchId = null; |
||||
|
||||
var initSearchTab = function() { |
||||
// load "Search in" preference from local storage |
||||
$('searchInTorrentName').set('value', (localStorage.getItem('search_in_filter') === "names") ? "names" : "everywhere"); |
||||
|
||||
searchResultsTable.setup('searchResultsTableDiv', 'searchResultsTableFixedHeaderDiv', null); |
||||
getPlugins(); |
||||
|
||||
var searchInNameFilterTimer = null; |
||||
// listen for changes to searchInNameFilter |
||||
$('searchInNameFilter').addEvent('input', function() { |
||||
var value = $('searchInNameFilter').get("value"); |
||||
if (value !== prevNameFilterValue) { |
||||
prevNameFilterValue = value; |
||||
clearTimeout(searchInNameFilterTimer); |
||||
searchInNameFilterTimer = setTimeout(function() { |
||||
searchFilterPattern = value; |
||||
searchFilterChanged(); |
||||
}, 400); |
||||
} |
||||
}); |
||||
|
||||
var searchKeyboardEvents = new Keyboard({ |
||||
defaultEventType: 'keydown', |
||||
events: { |
||||
'enter': function (e) { |
||||
// accept enter key as a click |
||||
new Event(e).stop(); |
||||
|
||||
var elem = e.event.srcElement; |
||||
if (elem.className.contains("searchInputField")) { |
||||
$('startSearchButton').click(); |
||||
return; |
||||
} |
||||
|
||||
switch (elem.id) { |
||||
case "downloadSearchTorrent": |
||||
downloadSearchTorrent(); |
||||
break; |
||||
case "openSearchTorrentDescription": |
||||
openSearchTorrentDescription(); |
||||
break; |
||||
case "copyDescriptionPageUrl": |
||||
copySearchTorrentUrl(); |
||||
break; |
||||
case "manageSearchPlugins": |
||||
manageSearchPlugins(); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
searchKeyboardEvents.activate(); |
||||
}; |
||||
|
||||
var startSearch = function(pattern, category, plugins) { |
||||
clearTimeout(loadSearchResultsTimer); |
||||
searchResultsTable.clear(); |
||||
$('numSearchResultsVisible').set('html', searchResultsTable.getFilteredAndSortedRows().length); |
||||
$('numSearchResultsTotal').set('html', searchResultsTable.getRowIds().length); |
||||
searchResultsRowId = 0; |
||||
requestCount = 0; |
||||
|
||||
var url = new URI('api/v2/search/start'); |
||||
new Request.JSON({ |
||||
url: url, |
||||
noCache: true, |
||||
method: 'post', |
||||
data: { |
||||
pattern: pattern, |
||||
category: category, |
||||
plugins: plugins |
||||
}, |
||||
onSuccess: function(response) { |
||||
$('startSearchButton').set('text', 'QBT_TR(Stop)QBT_TR[CONTEXT=SearchEngineWidget]'); |
||||
searchRunning = true; |
||||
activeSearchId = response.id; |
||||
updateSearchResultsData(); |
||||
} |
||||
}).send(); |
||||
}; |
||||
|
||||
var stopSearch = function() { |
||||
var url = new URI('api/v2/search/stop'); |
||||
new Request({ |
||||
url: url, |
||||
noCache: true, |
||||
method: 'post', |
||||
data: { |
||||
id: activeSearchId |
||||
}, |
||||
onSuccess: function(response) { |
||||
resetSearchState(); |
||||
} |
||||
}).send(); |
||||
}; |
||||
|
||||
var startStopSearch = function() { |
||||
if (!searchRunning || !activeSearchId) { |
||||
var pattern = $('searchPattern').getProperty('value').trim(); |
||||
var category = $('categorySelect').getProperty('value'); |
||||
var plugins = $('pluginsSelect').getProperty('value'); |
||||
|
||||
if (!pattern || !category || !plugins) return; |
||||
if (category === "QBT_TR(All categories)QBT_TR[CONTEXT=SearchEngineWidget]") |
||||
category = "all"; |
||||
|
||||
resetFilters(); |
||||
|
||||
searchPattern = pattern; |
||||
startSearch(pattern, category, plugins); |
||||
} |
||||
else { |
||||
stopSearch(); |
||||
} |
||||
}; |
||||
|
||||
var openSearchTorrentDescription = function() { |
||||
searchResultsTable.selectedRowsIds().each(function(rowId) { |
||||
window.open(searchResultsTable.rows.get(rowId).full_data.descrLink, "_blank"); |
||||
}); |
||||
}; |
||||
|
||||
var copySearchTorrentUrl = function() { |
||||
var urls = []; |
||||
searchResultsTable.selectedRowsIds().each(function(rowId) { |
||||
urls.push(searchResultsTable.rows.get(rowId).full_data.descrLink); |
||||
}); |
||||
return urls.join("\n"); |
||||
}; |
||||
|
||||
var downloadSearchTorrent = function() { |
||||
var urls = []; |
||||
searchResultsTable.selectedRowsIds().each(function(rowId) { |
||||
urls.push(encodeURIComponent(searchResultsTable.rows.get(rowId).full_data.fileUrl)); |
||||
}); |
||||
|
||||
// only proceed if at least 1 row was selected |
||||
if (!urls.length) return; |
||||
|
||||
showDownloadPage(urls); |
||||
}; |
||||
|
||||
var manageSearchPlugins = function() { |
||||
var id = 'searchPlugins'; |
||||
if (!$(id)) |
||||
new MochaUI.Window({ |
||||
id: id, |
||||
title: "QBT_TR(Search plugins)QBT_TR[CONTEXT=PluginSelectDlg]", |
||||
loadMethod: 'xhr', |
||||
contentURL: 'searchplugins.html', |
||||
scrollbars: false, |
||||
maximizable: false, |
||||
paddingVertical: 0, |
||||
paddingHorizontal: 0, |
||||
width: loadWindowWidth(id, 600), |
||||
height: loadWindowHeight(id, 360), |
||||
onResize: function() { |
||||
saveWindowSize(id); |
||||
}, |
||||
onBeforeBuild: function() { |
||||
loadSearchPlugins(); |
||||
}, |
||||
onClose: function() { |
||||
clearTimeout(loadSearchPluginsTimer); |
||||
} |
||||
}); |
||||
}; |
||||
|
||||
var loadSearchPlugins = function() { |
||||
getPlugins(); |
||||
loadSearchPluginsTimer = loadSearchPlugins.delay(2000); |
||||
}; |
||||
|
||||
var categorySelected = function() { |
||||
selectedCategory = $("categorySelect").get("value"); |
||||
}; |
||||
|
||||
var pluginSelected = function() { |
||||
selectedPlugin = $("pluginsSelect").get("value"); |
||||
|
||||
if (selectedPlugin !== prevSelectedPlugin) { |
||||
prevSelectedPlugin = selectedPlugin; |
||||
getSearchCategories(); |
||||
} |
||||
}; |
||||
|
||||
var reselectCategory = function() { |
||||
for (var i = 0; i < $("categorySelect").options.length; ++i) |
||||
if ($("categorySelect").options[i].get("value") === selectedCategory) |
||||
$("categorySelect").options[i].selected = true; |
||||
|
||||
categorySelected(); |
||||
}; |
||||
|
||||
var reselectPlugin = function() { |
||||
for (var i = 0; i < $("pluginsSelect").options.length; ++i) |
||||
if ($("pluginsSelect").options[i].get("value") === selectedPlugin) |
||||
$("pluginsSelect").options[i].selected = true; |
||||
|
||||
pluginSelected(); |
||||
}; |
||||
|
||||
var resetSearchState = function() { |
||||
clearTimeout(loadSearchResultsTimer); |
||||
$('startSearchButton').set('text', 'QBT_TR(Search)QBT_TR[CONTEXT=SearchEngineWidget]'); |
||||
searchResultsRowId = 0; |
||||
searchRunning = false; |
||||
activeSearchId = null; |
||||
}; |
||||
|
||||
var getSearchCategories = function() { |
||||
var populateCategorySelect = function(categories) { |
||||
var categoryHtml = []; |
||||
categories.each(function(category) { |
||||
categoryHtml.push("<option>" + category + "</option>"); |
||||
}); |
||||
|
||||
// first category is "All Categories" |
||||
if (categoryHtml.length > 1) |
||||
// add separator |
||||
categoryHtml.splice(1, 0, "<option disabled>──────────</option>"); |
||||
|
||||
$('categorySelect').set('html', categoryHtml.join("")); |
||||
}; |
||||
|
||||
var selectedPlugin = $('pluginsSelect').get("value"); |
||||
if ((selectedPlugin === "all") || (selectedPlugin === "enabled")) { |
||||
var url = new URI('api/v2/search/categories'); |
||||
url.setData('name', selectedPlugin); |
||||
new Request.JSON({ |
||||
url: url, |
||||
noCache: true, |
||||
method: 'get', |
||||
onSuccess: function(response) { |
||||
populateCategorySelect(response); |
||||
} |
||||
}).send(); |
||||
} |
||||
else { |
||||
var plugins = ["QBT_TR(All categories)QBT_TR[CONTEXT=SearchEngineWidget]"]; |
||||
var plugin = getPlugin(selectedPlugin); |
||||
if (plugin !== null) |
||||
plugins = plugins.concat(plugin.supportedCategories); |
||||
|
||||
populateCategorySelect(plugins); |
||||
} |
||||
|
||||
reselectCategory(); |
||||
}; |
||||
|
||||
var getPlugins = function() { |
||||
new Request.JSON({ |
||||
url: new URI('api/v2/search/plugins'), |
||||
noCache: true, |
||||
method: 'get', |
||||
onSuccess: function(response) { |
||||
if (response !== prevSearchPluginsResponse) { |
||||
prevSearchPluginsResponse = response; |
||||
searchPlugins = response; |
||||
|
||||
var pluginsHtml = []; |
||||
pluginsHtml.push('<option value="enabled">QBT_TR(Only enabled)QBT_TR[CONTEXT=SearchEngineWidget]</option>'); |
||||
pluginsHtml.push('<option value="all">QBT_TR(All plugins)QBT_TR[CONTEXT=SearchEngineWidget]</option>'); |
||||
|
||||
var searchPluginsEmpty = (searchPlugins.length === 0); |
||||
if (searchPluginsEmpty) { |
||||
$('searchResultsNoPlugins').style.display = "block"; |
||||
$('searchResultsFilters').style.display = "none"; |
||||
$('searchResultsTableContainer').style.display = "none"; |
||||
} |
||||
else { |
||||
$('searchResultsNoPlugins').style.display = "none"; |
||||
$('searchResultsFilters').style.display = "block"; |
||||
$('searchResultsTableContainer').style.display = "block"; |
||||
|
||||
// sort plugins alphabetically |
||||
var allPlugins = searchPlugins.sort(function(pluginA, pluginB){ |
||||
var a = pluginA.fullName.toLowerCase(); |
||||
var b = pluginB.fullName.toLowerCase(); |
||||
if (a < b) return -1; |
||||
if (a > b) return 1; |
||||
return 0; |
||||
}); |
||||
|
||||
allPlugins.each(function(plugin) { |
||||
if (plugin.enabled === true) |
||||
pluginsHtml.push("<option value='" + escapeHtml(plugin.name) + "'>" + escapeHtml(plugin.fullName) + "</option>"); |
||||
}); |
||||
|
||||
if (pluginsHtml.length > 2) |
||||
pluginsHtml.splice(2, 0, "<option disabled>──────────</option>"); |
||||
} |
||||
|
||||
$('pluginsSelect').set('html', pluginsHtml.join("")); |
||||
|
||||
$('searchPattern').setProperty('disabled', searchPluginsEmpty); |
||||
$('categorySelect').setProperty('disabled', searchPluginsEmpty); |
||||
$('pluginsSelect').setProperty('disabled', searchPluginsEmpty); |
||||
$('startSearchButton').setProperty('disabled', searchPluginsEmpty); |
||||
$('downloadSearchTorrent').setProperty('disabled', searchPluginsEmpty); |
||||
$('openSearchTorrentDescription').setProperty('disabled', searchPluginsEmpty); |
||||
$('copyDescriptionPageUrl').setProperty('disabled', searchPluginsEmpty); |
||||
|
||||
if (typeof updateSearchPluginsTable === "function") |
||||
updateSearchPluginsTable(); |
||||
|
||||
reselectPlugin(); |
||||
} |
||||
} |
||||
}).send(); |
||||
}; |
||||
|
||||
var getPlugin = function(name) { |
||||
for (var i = 0; i < searchPlugins.length; ++i) |
||||
if (searchPlugins[i].name === name) |
||||
return searchPlugins[i]; |
||||
|
||||
return null; |
||||
}; |
||||
|
||||
var searchInTorrentName = function() { |
||||
if ($('searchInTorrentName').get('value') === "names") |
||||
localStorage.setItem('search_in_filter', "names"); |
||||
else |
||||
localStorage.setItem('search_in_filter', "everywhere"); |
||||
|
||||
searchFilterChanged(); |
||||
}; |
||||
|
||||
var resetFilters = function() { |
||||
// reset filters |
||||
$('searchMinSeedsFilter').set('value', '0'); |
||||
$('searchMaxSeedsFilter').set('value', '0'); |
||||
$('searchMinSizeFilter').set('value', '0.00'); |
||||
$('searchMinSizePrefix').set('value', '2'); // MiB |
||||
$('searchMaxSizeFilter').set('value', '0.00'); |
||||
$('searchMaxSizePrefix').set('value', '3'); // GiB |
||||
}; |
||||
|
||||
var searchSeedsFilterChanged = function() { |
||||
searchSeedsFilter.min = $('searchMinSeedsFilter').get('value'); |
||||
searchSeedsFilter.max = $('searchMaxSeedsFilter').get('value'); |
||||
|
||||
searchFilterChanged(); |
||||
}; |
||||
|
||||
var searchSizeFilterChanged = function() { |
||||
searchSizeFilter.min = $('searchMinSizeFilter').get('value'); |
||||
searchSizeFilter.minUnit = $('searchMinSizePrefix').get('value'); |
||||
searchSizeFilter.max = $('searchMaxSizeFilter').get('value'); |
||||
searchSizeFilter.maxUnit = $('searchMaxSizePrefix').get('value'); |
||||
|
||||
searchFilterChanged(); |
||||
}; |
||||
|
||||
var searchSizeFilterPrefixChanged = function() { |
||||
if (($('searchMinSizeFilter').get('value') != 0) || ($('searchMaxSizeFilter').get('value') != 0)) |
||||
searchSizeFilterChanged(); |
||||
}; |
||||
|
||||
var searchFilterChanged = function() { |
||||
searchResultsTable.updateTable(); |
||||
$('numSearchResultsVisible').set('html', searchResultsTable.getFilteredAndSortedRows().length); |
||||
}; |
||||
|
||||
var setupSearchTableEvents = function(enable) { |
||||
if (enable) |
||||
$$(".searchTableRow").each(function(target) { |
||||
target.addEventListener('dblclick', downloadSearchTorrent, false); |
||||
}); |
||||
else |
||||
$$(".searchTableRow").each(function(target) { |
||||
target.removeEventListener('dblclick', downloadSearchTorrent, false); |
||||
}); |
||||
}; |
||||
|
||||
var loadSearchResultsData = function() { |
||||
var maxResults = 500; |
||||
var url = new URI('api/v2/search/results'); |
||||
new Request.JSON({ |
||||
url: url, |
||||
noCache: true, |
||||
method: 'post', |
||||
data: { |
||||
id: activeSearchId, |
||||
limit: maxResults, |
||||
offset: searchResultsRowId |
||||
}, |
||||
onFailure: function(response) { |
||||
if (response.status === 400) { |
||||
// bad params. search id is invalid |
||||
resetSearchState(); |
||||
} |
||||
else { |
||||
clearTimeout(loadSearchResultsTimer); |
||||
loadSearchResultsTimer = loadSearchResultsData.delay(3000); |
||||
} |
||||
}, |
||||
onSuccess: function(response) { |
||||
$('error_div').set('html', ''); |
||||
|
||||
// check if user stopped the search prior to receiving the response |
||||
if (!searchRunning) { |
||||
clearTimeout(loadSearchResultsTimer); |
||||
searchResultsRowId = 0; |
||||
return; |
||||
} |
||||
|
||||
if (response) { |
||||
setupSearchTableEvents(false); |
||||
|
||||
if (response.results) { |
||||
var results = response.results; |
||||
for (var i = 0; i < results.length; ++i) { |
||||
var result = results[i]; |
||||
var row = { |
||||
rowId: searchResultsRowId, |
||||
descrLink: result.descrLink, |
||||
fileName: result.fileName, |
||||
fileSize: result.fileSize, |
||||
fileUrl: result.fileUrl, |
||||
nbLeechers: result.nbLeechers, |
||||
nbSeeders: result.nbSeeders, |
||||
siteUrl: result.siteUrl, |
||||
}; |
||||
|
||||
searchResultsTable.updateRowData(row); |
||||
++searchResultsRowId; |
||||
} |
||||
|
||||
$('numSearchResultsVisible').set('html', searchResultsTable.getFilteredAndSortedRows().length); |
||||
$('numSearchResultsTotal').set('html', searchResultsTable.getRowIds().length); |
||||
} |
||||
|
||||
searchResultsTable.updateTable(); |
||||
searchResultsTable.altRow(); |
||||
|
||||
if ((response.status === "Stopped") && (searchResultsRowId >= response.total)) { |
||||
resetSearchState(); |
||||
return; |
||||
} |
||||
|
||||
setupSearchTableEvents(true); |
||||
} |
||||
|
||||
var timeout = 1000; |
||||
if (requestCount > 30) |
||||
timeout = 3000; |
||||
else if (requestCount > 10) |
||||
timeout = 2000; |
||||
|
||||
clearTimeout(loadSearchResultsTimer); |
||||
loadSearchResultsTimer = loadSearchResultsData.delay(timeout); |
||||
++requestCount; |
||||
} |
||||
}).send(); |
||||
}; |
||||
|
||||
var updateSearchResultsData = function() { |
||||
clearTimeout(loadSearchResultsTimer); |
||||
loadSearchResultsTimer = loadSearchResultsData.delay(500); |
||||
}; |
||||
|
||||
initSearchTab(); |
||||
</script> |
@ -0,0 +1,219 @@
@@ -0,0 +1,219 @@
|
||||
<style type="text/css"> |
||||
#searchPluginsContainer { |
||||
height: calc(100% - 20px); |
||||
margin: 10px; |
||||
overflow: auto; |
||||
} |
||||
|
||||
#searchPluginsContainer button { |
||||
padding: 2px; |
||||
} |
||||
|
||||
#searchPluginsContainer span { |
||||
display: block; |
||||
margin-top: 10px; |
||||
} |
||||
|
||||
#searchPluginsTable { |
||||
width: 100%; |
||||
height: calc(100% - 150px); |
||||
-moz-height: calc(100% - 150px); |
||||
-webkit-height: calc(100% - 150px); |
||||
} |
||||
|
||||
#searchPluginsTable .dynamicTable { |
||||
width: 100%; |
||||
} |
||||
|
||||
#searchPluginsTableDiv { |
||||
height: calc(100% - 26px); |
||||
-moz-height: calc(100% - 26px); |
||||
-webkit-height: calc(100% - 26px); |
||||
} |
||||
|
||||
#dynamicTableFixedHeaderDiv { |
||||
height: 26px; |
||||
} |
||||
|
||||
#searchPlugins_content { |
||||
height: 100%; |
||||
} |
||||
</style> |
||||
|
||||
<div id="searchPluginsContainer"> |
||||
<h2>QBT_TR(Installed search plugins:)QBT_TR[CONTEXT=PluginSelectDlg]</h2> |
||||
|
||||
<div id="searchPluginsTable"> |
||||
<div id="searchPluginsTableFixedHeaderDiv" class="dynamicTableFixedHeaderDiv"> |
||||
<table class="dynamicTable unselectable" style="position:relative;"> |
||||
<thead> |
||||
<tr class="dynamicTableHeader" id="searchPluginsTableFixedHeaderRow"></tr> |
||||
</thead> |
||||
</table> |
||||
</div> |
||||
<div id="searchPluginsTableDiv" class="dynamicTableDiv"> |
||||
<table class="dynamicTable unselectable"> |
||||
<thead> |
||||
<tr class="dynamicTableHeader"></tr> |
||||
</thead> |
||||
<tbody></tbody> |
||||
</table> |
||||
</div> |
||||
</div> |
||||
|
||||
<span>QBT_TR(Warning: Be sure to comply with your country's copyright laws when downloading torrents from any of these search engines.)QBT_TR[CONTEXT=PluginSelectDlg]</span> |
||||
<span style="font-style: italic;">QBT_TR(You can get new search engine plugins here:)QBT_TR[CONTEXT=PluginSelectDlg] <a href="http://plugins.qbittorrent.org" target="_blank">http://plugins.qbittorrent.org</a></span> |
||||
<div style="width: 100%; margin-top: 10px;"> |
||||
<button style="width: 33%; line-height: 1.4em;" onclick="installPlugin();">QBT_TR(Install new plugin)QBT_TR[CONTEXT=PluginSelectDlg]</button> |
||||
<button style="width: 33%; line-height: 1.4em;" onclick="checkForUpdates();">QBT_TR(Check for updates)QBT_TR[CONTEXT=PluginSelectDlg]</button> |
||||
<button style="width: 32%; line-height: 1.4em;" onclick="closeSearchWindow('searchPlugins');">QBT_TR(Close)QBT_TR[CONTEXT=PluginSelectDlg]</button> |
||||
</div> |
||||
</div> |
||||
|
||||
<ul id="searchPluginsTableMenu" class="contextMenu"> |
||||
<li><a href="#Enabled"><img src="images/qbt-theme/checked.svg" alt="QBT_TR(Enabled)QBT_TR[CONTEXT=PluginSelectDlg]"/> QBT_TR(Enabled)QBT_TR[CONTEXT=PluginSelectDlg]</a></li> |
||||
<li class="separator"><a href="#Uninstall"><img src="images/qbt-theme/list-remove.svg" alt="QBT_TR(Uninstall)QBT_TR[CONTEXT=PluginSelectDlg]"/> QBT_TR(Uninstall)QBT_TR[CONTEXT=PluginSelectDlg]</a></li> |
||||
</ul> |
||||
|
||||
<script> |
||||
'use strict'; |
||||
|
||||
var searchPluginsTableContextMenu; |
||||
var prevOffsetLeft; |
||||
var prevOffsetTop; |
||||
|
||||
var initSearchPlugins = function() { |
||||
searchPluginsTableContextMenu = new SearchPluginsTableContextMenu({ |
||||
targets: '.searchPluginsTableRow', |
||||
menu: 'searchPluginsTableMenu', |
||||
actions: { |
||||
Enabled: enablePlugin, |
||||
Uninstall: uninstallPlugin |
||||
}, |
||||
offsets : calculateContextMenuOffsets() |
||||
}); |
||||
searchPluginsTable.setup('searchPluginsTableDiv', 'searchPluginsTableFixedHeaderDiv', searchPluginsTableContextMenu); |
||||
updateSearchPluginsTable(); |
||||
}; |
||||
|
||||
var closeSearchWindow = function(id) { |
||||
window.parent.MochaUI.closeWindow(window.parent.$(id)); |
||||
}; |
||||
|
||||
var installPlugin = function(path) { |
||||
new MochaUI.Window({ |
||||
id: 'installSearchPlugin', |
||||
title: "QBT_TR(Install plugin)QBT_TR[CONTEXT=PluginSourceDlg]", |
||||
loadMethod: 'xhr', |
||||
contentURL: 'installsearchplugin.html', |
||||
scrollbars: false, |
||||
resizable: false, |
||||
maximizable: false, |
||||
paddingVertical: 0, |
||||
paddingHorizontal: 0, |
||||
width: 500, |
||||
height: 120 |
||||
}); |
||||
}; |
||||
|
||||
var uninstallPlugin = function() { |
||||
var plugins = searchPluginsTable.selectedRowsIds().join('|'); |
||||
var url = new URI('api/v2/search/uninstallPlugin'); |
||||
new Request({ |
||||
url: url, |
||||
noCache: true, |
||||
method: 'post', |
||||
data: { |
||||
names: plugins, |
||||
} |
||||
}).send(); |
||||
}; |
||||
|
||||
var enablePlugin = function() { |
||||
var plugins = searchPluginsTable.selectedRowsIds(); |
||||
var enable = true; |
||||
if (plugins && plugins.length) |
||||
enable = !getPlugin(plugins[0]).enabled; |
||||
|
||||
var url = new URI('api/v2/search/enablePlugin'); |
||||
new Request({ |
||||
url: url, |
||||
noCache: true, |
||||
method: 'post', |
||||
data: { |
||||
names: plugins.join('|'), |
||||
enable: enable |
||||
} |
||||
}).send(); |
||||
}; |
||||
|
||||
var checkForUpdates = function() { |
||||
var url = new URI('api/v2/search/updatePlugins'); |
||||
new Request({ |
||||
url: url, |
||||
noCache: true, |
||||
method: 'post' |
||||
}).send(); |
||||
}; |
||||
|
||||
var calculateContextMenuOffsets = function() { |
||||
prevOffsetLeft = document.getElementById("searchPlugins").getBoundingClientRect().left; |
||||
prevOffsetTop = document.getElementById("searchPlugins").getBoundingClientRect().top; |
||||
|
||||
return { |
||||
x: -(prevOffsetLeft + 20), |
||||
y: -(prevOffsetTop + 2) |
||||
}; |
||||
}; |
||||
|
||||
var updateSearchPluginsTableContextMenuOffset = function() { |
||||
// only re-calculate if window has moved |
||||
if ((prevOffsetLeft !== document.getElementById("searchPlugins").getBoundingClientRect().left) || (prevOffsetTop !== document.getElementById("searchPlugins").getBoundingClientRect().top)) |
||||
searchPluginsTableContextMenu.options.offsets = calculateContextMenuOffsets(); |
||||
}; |
||||
|
||||
var setupSearchPluginTableEvents = function(enable) { |
||||
if (enable) |
||||
$$(".searchPluginsTableRow").each(function(target) { |
||||
target.addEventListener('dblclick', enablePlugin, false); |
||||
target.addEventListener('contextmenu', updateSearchPluginsTableContextMenuOffset, true); |
||||
}); |
||||
else |
||||
$$(".searchPluginsTableRow").each(function(target) { |
||||
target.removeEventListener('dblclick', enablePlugin, false); |
||||
target.removeEventListener('contextmenu', updateSearchPluginsTableContextMenuOffset, true); |
||||
}); |
||||
}; |
||||
|
||||
var updateSearchPluginsTable = function() { |
||||
// clear event listeners |
||||
setupSearchPluginTableEvents(false); |
||||
|
||||
var oldPlugins = Object.keys(searchPluginsTable.rows); |
||||
// remove old rows from the table |
||||
for (var i = 0; i < oldPlugins.length; ++i) { |
||||
var found = false; |
||||
for (var j = 0; j < searchPlugins.length; ++j) { |
||||
if (searchPlugins[j].name === oldPlugins[i]) { |
||||
found = true; |
||||
break; |
||||
} |
||||
} |
||||
if (!found) |
||||
searchPluginsTable.removeRow(oldPlugins[i]); |
||||
} |
||||
|
||||
for (var i = 0; i < searchPlugins.length; ++i) { |
||||
searchPlugins[i].rowId = searchPlugins[i].name; |
||||
searchPluginsTable.updateRowData(searchPlugins[i]); |
||||
} |
||||
|
||||
searchPluginsTable.updateTable(); |
||||
searchPluginsTable.altRow(); |
||||
|
||||
// add event listeners |
||||
setupSearchPluginTableEvents(true); |
||||
}; |
||||
|
||||
initSearchPlugins(); |
||||
</script> |
Loading…
Reference in new issue