added tabbing

This commit is contained in:
Martchus 2016-02-10 21:09:20 +01:00
parent 0e83a39418
commit 82d4ae2eb7
17 changed files with 324 additions and 75 deletions

View File

@ -62,7 +62,6 @@ set(WEB_FILES
web/3rdparty/bootstrap/js/npm.js
web/3rdparty/bootstrap_dropdowns_enhancement/css/dropdowns-enhancement.min.css
web/3rdparty/bootstrap_dropdowns_enhancement/js/dropdowns-enhancement.js
web/css/.core.css.swp
web/css/core.css
web/css/dashboard.css
web/index.html
@ -75,6 +74,7 @@ set(WEB_FILES
web/js/pagination.js
web/js/proto.js
web/js/repomanagement.js
web/js/tabbing.js
web/js/utils.js
)
@ -86,7 +86,7 @@ set(META_APP_URL "https://github.com/${META_APP_AUTHOR}/${META_PROJECT_NAME}")
set(META_APP_DESCRIPTION "Arch Linux repository browser")
set(META_VERSION_MAJOR 0)
set(META_VERSION_MINOR 0)
set(META_VERSION_PATCH 1)
set(META_VERSION_PATCH 2)
# stringification of meta data
set(META_PROJECT_NAME_STR "\"${META_PROJECT_NAME}\"")
@ -140,7 +140,7 @@ add_definitions(
)
# executable and linking
add_executable(${META_PROJECT_NAME} ${HEADER_FILES} ${SRC_FILES} ${RES_FILES})
add_executable(${META_PROJECT_NAME} ${HEADER_FILES} ${SRC_FILES} ${WEB_FILES} ${RES_FILES})
target_link_libraries(${META_PROJECT_NAME} c++utilities alpm Qt5::Core Qt5::Concurrent Qt5::Network Qt5::WebSockets KF5::Archive)
set_target_properties(${META_PROJECT_NAME} PROPERTIES
CXX_STANDARD 11

View File

@ -7,18 +7,27 @@
namespace RepoIndex {
PackageFinder::PackageFinder(Manager &manager, const QList<Dependency> &dependencies, QObject *parent)
: QObject(parent),
m_remainingReplies(0)
PackageFinder::PackageFinder(Manager &manager, const QList<Dependency> &dependencies, bool sourcesRequired, QObject *parent) :
QObject(parent),
//m_sourcesRequired(sourcesRequired),
m_remainingReplies(0)
{
QStringList toRequest;
for(const auto &dependency : dependencies) {
if(auto *pkg = manager.packageProviding(dependency)) {
m_results << pkg;
} else {
if(!sourcesRequired) {
for(const auto &dependency : dependencies) {
if(auto *pkg = manager.packageProviding(dependency)) {
m_results << pkg;
} else {
toRequest << dependency.name;
}
}
} else {
toRequest.reserve(dependencies.size());
for(const auto &dependency : dependencies) {
toRequest << dependency.name;
}
}
if(manager.userRepository()) {
QReadLocker locker(manager.userRepository()->lock());
if(auto *reply = manager.userRepository()->requestFullPackageInfo(toRequest)) {

View File

@ -13,8 +13,9 @@ class PackageFinder : public QObject
{
Q_OBJECT
public:
explicit PackageFinder(Manager &manager, const QList<Dependency> &dependencies, QObject *parent = nullptr);
explicit PackageFinder(Manager &manager, const QList<Dependency> &dependencies, bool sourcesRequired = false, QObject *parent = nullptr);
void setSourcesRequired(bool sourcesRequired);
const QList<Package *> results() const;
bool areAllResultsAvailable() const;
Package *packageProviding(const Dependency &dependency);
@ -26,10 +27,16 @@ private slots:
void addResults();
private:
//bool m_sourcesRequired;
int m_remainingReplies;
QList<Package *> m_results;
};
//void PackageFinder::setSourcesRequired(bool sourcesRequired)
//{
// return m_sourcesRequired;
//}
inline const QList<Package *> PackageFinder::results() const
{
return m_results;

View File

@ -31,6 +31,8 @@ public:
void setName(const QString &name);
const QSet<TaskInfo *> deps() const;
void addDep(TaskInfo *dep);
bool areAllDepsAdded() const;
void setAllDepsAdded();
bool isDone() const;
bool isVisited() const;
bool isOnlyDependency() const;
@ -50,6 +52,7 @@ public:
private:
QString m_name;
QSet<TaskInfo *> m_deps;
bool m_allDepsAdded;
bool m_done;
bool m_visited;
bool m_onlyDep;
@ -65,6 +68,7 @@ private:
inline TaskInfo::TaskInfo(const QString &name, bool onlyDependency, const QSet<TaskInfo *> &deps) :
m_name(name),
m_deps(deps),
m_allDepsAdded(false),
m_done(false),
m_visited(false),
m_onlyDep(onlyDependency),
@ -106,6 +110,22 @@ inline void TaskInfo::addDep(TaskInfo *dep)
m_deps << dep;
}
/*!
* \brief Returns whether setAllDepsAdded() has been called for this task.
*/
bool TaskInfo::areAllDepsAdded() const
{
return m_allDepsAdded;
}
/*!
* \brief Sets that all dependencies have been added for this task.
*/
void TaskInfo::setAllDepsAdded()
{
m_allDepsAdded = true;
}
/*!
* \brief Returns whether the task already has been added to the resulting list of tasks.
* \sa add()
@ -211,7 +231,11 @@ inline void TaskInfo::addRequiredFor(const Dependency &dependency)
void TaskInfo::add(QList<TaskInfo *> &results)
{
if(!isDone()) {
if(name() == "mingw-w64-harfbuzz") {
cout << "harfbuzz" << endl;
}
if(isVisited()) {
cout << "cyclic dependency: " << name().toStdString() << endl;
// cyclic dependency
if(isOnlyDependency() || isBinaryAvailable()) {
// if this is only a dependency (which we don't want to build) don't care about it
@ -355,7 +379,7 @@ void BuildOrderResolver::findDependencies()
{
// find specified packages and their dependencies
for(int i = 0, size = m_tasks.size(); i != size; ++i) {
if(!addDependenciesToTask(m_tasks.at(i))) {
if(!addDependenciesToTask(m_tasks[i])) {
return;
}
}
@ -428,10 +452,10 @@ void BuildOrderResolver::resolve()
/*!
* \brief Returns the package for the specified \a dependency or nullptr if no package could be found.
*/
Package *BuildOrderResolver::findPackageForDependency(const Dependency &dependency)
Package *BuildOrderResolver::findPackageForDependency(const Dependency &dependency, bool sourceRequired)
{
Package *pkg;
if((pkg = m_manager.packageProviding(dependency))) {
if(!sourceRequired && (pkg = m_manager.packageProviding(dependency))) {
return pkg;
} else if(m_finder && (pkg = m_finder->packageProviding(dependency))) {
return pkg;
@ -445,12 +469,12 @@ Package *BuildOrderResolver::findPackageForDependency(const Dependency &dependen
bool BuildOrderResolver::addDependenciesToTask(TaskInfo *task)
{
// check whether dependencies have already been added
if(task->associatedPackage()) {
if(task->areAllDepsAdded()) {
// package associated -> dependencies already added
return true;
}
Dependency dep(task->name(), QString());
if(const auto pkg = findPackageForDependency(dep)) {
if(const auto pkg = findPackageForDependency(dep, !task->isOnlyDependency())) {
task->addRequiredFor(dep);
if(task->associatePackage(pkg)) {
if(pkg->repository()->isSourceOnly()) {
@ -461,6 +485,7 @@ bool BuildOrderResolver::addDependenciesToTask(TaskInfo *task)
task->setBinaryAvailable(true);
}
// add dependencies to task
task->setAllDepsAdded();
if(!addDependenciesToTask(task, pkg->allDependencies())) {
addError(QStringLiteral("Can not add dependencies of the dependency \"") % dep.toString() % QStringLiteral("\"."));
m_hasFinished = true;
@ -493,9 +518,12 @@ bool BuildOrderResolver::addDependenciesToTask(TaskInfo *task, const QList<const
{
for(auto *deps : dependencies) {
for(auto &dep : *deps) {
auto *depPkg = findPackageForDependency(dep);
const QString taskName = depPkg ? depPkg->name() : dep.name;
auto *depTask = TaskInfo::find(m_tasks, dep.name);
auto *depPkg = findPackageForDependency(dep, depTask && !depTask->isOnlyDependency());
if(depPkg && dep.name == "mingw-w64-harfbuzz") {
cout << "processing harfbuzz" << endl;
}
const QString taskName = depPkg ? depPkg->name() : dep.name;
bool newTask;
if(depTask) {
// we've already added a task for this dependency
@ -517,8 +545,9 @@ bool BuildOrderResolver::addDependenciesToTask(TaskInfo *task, const QList<const
} else {
depTask->setBinaryAvailable(true);
}
if(newTask) {
if(!depTask->areAllDepsAdded()) {
// add dependencies of the dependency
depTask->setAllDepsAdded();
if(!addDependenciesToTask(depTask, depPkg->allDependencies())) {
addError(QStringLiteral("Can not add dependencies of the dependency \"") % dep.toString() % QStringLiteral("\"."));
return false;
@ -561,7 +590,7 @@ void BuildOrderResolver::requestDependenciesToBeRequested()
}
// do requests (using package finder)
m_finder = make_unique<PackageFinder>(m_manager, m_dependenciesToBeRequested);
m_finder = make_unique<PackageFinder>(m_manager, m_dependenciesToBeRequested, true);
// all dependencies requested -> clear dependencies to be requested
m_dependenciesToBeRequested.clear();

View File

@ -45,7 +45,7 @@ protected:
private:
void addError(const QString &errorMessage);
Package *findPackageForDependency(const Dependency &dependency);
Package *findPackageForDependency(const Dependency &dependency, bool sourceRequired);
bool addDependenciesToTask(TaskInfo *task);
bool addDependenciesToTask(TaskInfo *task, const QList<const QList<Dependency> *> &dependencies);
void requestDependenciesToBeRequested();

View File

@ -58,12 +58,6 @@ QJsonArray sigLevelStrings(alpm_siglevel_t sigLevel)
if(sigLevel & ALPM_SIG_DATABASE_UNKNOWN_OK) {
options << QStringLiteral("database unknown ok");
}
if(sigLevel & ALPM_SIG_PACKAGE_SET) {
options << QStringLiteral("package set");
}
if(sigLevel & ALPM_SIG_PACKAGE_TRUST_SET) {
options << QStringLiteral("package trust set");
}
if(sigLevel & ALPM_SIG_USE_DEFAULT) {
options << QStringLiteral("use default");
}

View File

@ -4,7 +4,7 @@ appname = "Repository Index"
appauthor = Martchus
appurl = "https://github.com/$${appauthor}/$${projectname}"
QMAKE_TARGET_DESCRIPTION = "Provides a web interface to browse Arch Linux package repositories."
VERSION = 0.0.1
VERSION = 0.0.2
# include ../../common.pri when building as part of a subdirs project; otherwise include general.pri
!include(../../common.pri) {

Binary file not shown.

View File

@ -50,7 +50,7 @@ span.glyphicon {
background-color: #f9f9db!important;
cursor: pointer;
}
.info-container th, .info-container td {
.info-table th, .info-table td {
border: none!important;
font-size: 90%;
padding: 5px;
@ -92,6 +92,16 @@ span.glyphicon {
border-bottom: 5px solid #337ab7;
}
/*
* Tabbing
*/
.tab-content > div {
border-left: 1px solid #ddd;
border-right: 1px solid #ddd;
border-bottom: 1px solid #ddd;
padding: 5px;
}
/*
* Package info
*/

View File

@ -140,7 +140,7 @@
<!-- right column -->
<div id="right_column_container_packages">
<!-- package info container (right column) -->
<div id="single_package_info_container"><!-- package info panel generated by JavaScript --></div>
<!-- package info panel generated by JavaScript -->
</div>
</div>
<!-- begin of groups page -->
@ -180,7 +180,7 @@
</div>
<div id="right_column_container_repos">
<!-- repo info container (right column) -->
<div id="single_repo_info_container"><!-- repo info panel generated by JavaScript --></div>
<!-- repo info panel generated by JavaScript -->
</div>
</div>
</div>
@ -251,6 +251,7 @@
<script src="js/entrymanagement.js"></script>
<script src="js/repomanagement.js"></script>
<script src="js/pagination.js"></script>
<script src="js/tabbing.js"></script>
<script src="js/packagemanagement.js"></script>
<script src="js/groupmanagement.js"></script>
<script src="js/client.js"></script>

View File

@ -44,6 +44,19 @@
};
this.updateEnabled = function() {};
this.contained = function(names, searchDescription) {
for(var i = 0, len = names.length; i < len; ++i) {
if(this.name.contains(names[i])) {
return true;
} else if(searchDescription && this.info.desc && this.info.desc.contains(names[i])) {
// this doesn't work yet because only descriptions of entries which have already
// been shown are available
return true;
}
}
return false;
};
};
repoindex.EntryManager = function(EntryType, entryContainer, pagination) {
@ -62,7 +75,9 @@
// stuff for the filter
this.filteredEntries = [];
this.filterName = undefined;
this.filterNames = undefined;
this.filterNameExact = false;
this.filterNameInDesc = false;
this.filterRepos = undefined;
this.filterDescr = undefined;
this.customSelection = undefined;
@ -79,21 +94,19 @@
// define default filter predicate
this.filterPred = function(entry) {
return (!this.filterName || (this.filterNameExact ? entry.name === this.filterName : entry.name.contains(this.filterName)))
return (!this.filterNames || this.filterNames.length === 0 || (this.filterNameExact ? this.filterNames.contains(entry.name) : entry.contained(this.filterNames, this.filterNameInDesc)))
&& (!this.filterRepos || this.filterRepos.contains(entry.info.repo));
};
// provide functions to apply filter and upgrade UI
this.applyFilter = function() {
//if(this.customSelection) {
// this.filteredEntries = this.customSelection;
//} else {
if((this.filterName || this.filterRepos) && this.filterPred) {
this.filteredEntries = this.relevantEntries().filter(this.filterPred, this);
} else {
this.filteredEntries = this.relevantEntries();
}
//}
if((this.filterName || this.filterRepos) && this.filterPred) {
// split filterName into filterNames
this.filterNames = this.filterName ? this.filterName.split(" ") : undefined;
this.filteredEntries = this.relevantEntries().filter(this.filterPred, this);
} else {
this.filteredEntries = this.relevantEntries();
}
// upgrade pagination (the pageSelected method defined above will be invoked here automatically)
this.pagination.entryCount = this.filteredEntries.length;
this.pagination.update();

View File

@ -16,8 +16,8 @@
if(color) {
this.rowElement.style.backgroundColor = color;
}
this.rowElement.onclick = function() {
repoindex.pageManager.packageManager.showPackageInfoForIndex(this.entry.index);
this.rowElement.onclick = function(e) {
repoindex.pageManager.packageManager.showPackageInfoForIndex(this.entry.index, typeof e === "object" && e.button === 1);
};
this.initTableRow = function() {
@ -95,13 +95,13 @@
this.infoBox = document.getElementById("packages_info");
this.showPackageInfo = function(repo, name) {
this.showPackageInfo = function(repo, name, newTab) {
var determineEntry = function() {
var res = repoindex.pageManager.packageManager.entries.filter(function(entry) {
return entry.info.repo === repo && entry.info.name === name;
});
if(res.length > 0) {
repoindex.pageManager.packageManager.showPackageInfoForIndex(res[0].index);
repoindex.pageManager.packageManager.showPackageInfoForIndex(res[0].index, newTab);
} else {
repoindex.pageManager.packageManager.showPackageNotFound(repo, name);
}
@ -116,14 +116,14 @@
}
};
this.showPackageInfoForIndex = function(entryIndex) {
this.showPackageInfoForIndex = function(entryIndex, newTab) {
// check whether specified entry index is valid
var entry = this.entryByIndex(entryIndex);
if(entry) {
// show properties
var setProperties = function() {
// -> find info container and make info table
var infoContainer = document.getElementById("single_package_info_container");
var infoContainer = repoindex.pageManager.createPackageInfoPane(entry, newTab);
infoContainer.wipeChildren();
var infoTable = repoindex.makeInfoTable();
var tb = infoTable.tbodyElement;
@ -202,10 +202,7 @@
}
}
// -> make info panel
var infoPanel = repoindex.makeInfoPanel("Package info", repoindex.bind(repoindex.pageManager, repoindex.pageManager.hidePackageInfo));
infoPanel.bodyElement.appendChild(infoTable.tableElement);
infoContainer.appendChild(infoPanel.element);
infoContainer.appendChild(infoTable.tableElement);
};
setProperties();
if(!entry.info.basics || !entry.info.details) {

View File

@ -33,7 +33,8 @@
this.rightColumnContainerPackages = document.getElementById("right_column_container_packages");
this.leftColumnContainerRepos = document.getElementById("left_column_container_repos");
this.rightColumnContainerRepos = document.getElementById("right_column_container_repos");
this.packageInfoContainer = document.getElementById("container_package_info");
this.packageInfoTabbing = undefined;
this.repoInfoTabbing = undefined;
// provide a function to add an error message (shown in red box)
this.addError = function(msg) {
@ -269,6 +270,20 @@
return false;
};
this.createPackageInfoPane = function(entry, newTab) {
if(!this.packageInfoTabbing) {
this.packageInfoTabbing = new repoindex.Tabbing(this.rightColumnContainerPackages);
this.packageInfoTabbing.tabRemoved = function(tab) {
if(this.tabs.length === 0) {
repoindex.pageManager.hidePackageInfo();
}
};
}
var tabElement = this.packageInfoTabbing.addTab(repoindex.makeElementId([entry.info.repo, entry.name].join("--sep--")), entry.name, true, newTab !== true);
tabElement.activate();
return tabElement.paneElement;
};
this.hidePackageInfo = function() {
this.rehash(function(hash) {
hash[1].repo = hash[1].pkg = undefined;
@ -292,6 +307,20 @@
//}
};
this.createRepoInfoPane = function(entry, newTab) {
if(!this.repoInfoTabbing) {
this.repoInfoTabbing = new repoindex.Tabbing(this.rightColumnContainerRepos);
this.repoInfoTabbing.tabRemoved = function(tab) {
if(this.tabs.length === 0) {
repoindex.pageManager.hideRepoInfo();
}
};
}
var tabElement = this.repoInfoTabbing.addTab(repoindex.makeElementId(entry.name), entry.name, true, newTab !== true);
tabElement.activate();
return tabElement.paneElement;
};
this.hideRepoInfo = function() {
this.rehash(function(hash) {
hash[1].repo = hash[1].pkg = undefined;

View File

@ -3,14 +3,14 @@
// let's add some "evil" prototype definitions
if(!String.prototype.contains) {
String.prototype.contains = function(startIndex) {
return this.indexOf(startIndex) !== -1;
String.prototype.contains = function(substr) {
return this.indexOf(substr) !== -1;
};
}
if(!Array.prototype.contains) {
Array.prototype.contains = function(startIndex) {
return this.indexOf(startIndex) !== -1;
Array.prototype.contains = function(element) {
return this.indexOf(element) !== -1;
};
}
@ -26,6 +26,12 @@
};
}
if(!Array.prototype.second) {
Array.prototype.second = function() {
return this[1];
};
}
if(!Node.prototype.wipeChildren) {
Node.prototype.wipeChildren = function() {
while(this.lastChild) {

View File

@ -12,8 +12,8 @@
this.info.currentServer = 0;
this.rowElement.onclick = function() {
repoindex.pageManager.repoManager.showRepoInfoForIndex(this.entry.index);
this.rowElement.onclick = function(e) {
repoindex.pageManager.repoManager.showRepoInfoForIndex(this.entry.index, typeof e === "object" && e.button === 1);
};
this.initTableRow = function() {
@ -153,7 +153,7 @@
this.infoBox = document.getElementById("repos_info");
this.showRepoInfo = function(repo) {
this.showRepoInfo = function(repo, newTab) {
var determineEntry = function() {
var res = repoindex.pageManager.repoManager.entries.filter(function(entry) {
return entry.name === repo;
@ -161,7 +161,7 @@
// entry exists?
if(res.length > 0) {
// yes -> full package info available?
repoindex.pageManager.repoManager.showRepoInfoForIndex(res[0].index);
repoindex.pageManager.repoManager.showRepoInfoForIndex(res[0].index, newTab);
} else {
// no -> show error
repoindex.pageManager.repoManager.showRepoNotFound(repo);
@ -177,11 +177,11 @@
}
};
this.showRepoInfoForIndex = function(entryIndex) {
this.showRepoInfoForIndex = function(entryIndex, newTab) {
var entry = this.entryByIndex(entryIndex);
if(entry) {
// -> find info container and make info table
var infoContainer = document.getElementById("single_repo_info_container");
var infoContainer = repoindex.pageManager.createRepoInfoPane(entry, newTab);
infoContainer.wipeChildren();
var infoTable = repoindex.makeInfoTable();
var tb = infoTable.tbodyElement;
@ -204,10 +204,7 @@
// ensures, that the "Package Info" box (with the properties just set) is shown
repoindex.pageManager.showRepoInfo();
// -> make info panel
var infoPanel = repoindex.makeInfoPanel("Repository info", repoindex.bind(repoindex.pageManager, repoindex.pageManager.hideRepoInfo));
infoPanel.bodyElement.appendChild(infoTable.tableElement);
infoContainer.appendChild(infoPanel.element);
infoContainer.appendChild(infoTable.tableElement);
}
};

132
web/js/tabbing.js Normal file
View File

@ -0,0 +1,132 @@
var repoindex = (function(repoindex) {
/*!
* \brief Adds bootstrap tabs to the HTML element with the specified id.
*/
repoindex.Tabbing = function(containerId) {
// assemble required element structure
this.containerElement = document.createElement("div");
this.tabbingElement = document.createElement("ul");
this.tabbingElement.className = "nav nav-tabs";
this.contentElement = document.createElement("div");
this.contentElement.className = "tab-content";
this.containerElement.appendChild(this.tabbingElement);
this.containerElement.appendChild(this.contentElement);
repoindex.getElement(containerId).appendChild(this.containerElement);
this.tabs = [];
// returns a tab by ID
this.tabById = function(id) {
for(var i = 0, len = this.tabs.length; i < len; ++i) {
if(this.tabs[i].paneElement.id === id) {
return this.tabs[i];
}
}
};
// finds the currently shown tab
this.findActiveTab = function() {
for(var i = 0, len = this.tabs.length; i < len; ++i) {
if(this.tabs[i].classList.contains("active")) {
return this.tabs[i];
}
}
};
// adds a new tab
this.addTab = function(id, title, closeable, replaceActive) {
// check whether a tab with the specified ID already exists
var tabElement = this.tabById(id);
if(tabElement) {
// ID already used -> just return currenlty present tab
return tabElement;
}
// create new tab
tabElement = document.createElement("li");
// replace active tab
if(replaceActive) {
var activeTabElement = this.findActiveTab();
if(activeTabElement) {
this.tabbingElement.removeChild(activeTabElement);
this.contentElement.removeChild(activeTabElement.paneElement);
tabElement.tabbingIndex = activeTabElement.tabbingIndex;
}
}
// initiate new tab
if(tabElement.tabbingIndex === undefined) {
tabElement.tabbingIndex = this.tabs.length;
}
var paneElement = document.createElement("div");
var linkElement = document.createElement("a");
linkElement.setAttribute("data-toggle", "tab");
linkElement.href = "#" + id;
linkElement.appendChild(document.createTextNode(title));
tabElement.paneElement = paneElement;
tabElement.linkElement = linkElement;
tabElement.tabbing = this;
tabElement.appendChild(linkElement);
this.tabbingElement.appendChild(tabElement);
paneElement.tabElement = tabElement;
paneElement.setAttribute("id", id);
if(this.tabs.length === 0) {
tabElement.className = "active";
paneElement.className = "tab-pane fade in active";
} else {
paneElement.className = "tab-pane fade";
}
this.contentElement.appendChild(paneElement);
// method to active tab
tabElement.activate = function() {
this.linkElement.click();
};
if(closeable) {
var closeButton = repoindex.makeCloseButton();
closeButton.style.marginLeft = "4px";
closeButton.onclick = function() {
tabElement.tabbing.removeTab(tabElement);
};
linkElement.appendChild(closeButton);
};
this.tabs[tabElement.tabbingIndex] = tabElement;
return tabElement;
};
// removes a tab
this.removeTab = function(tabElement) {
this.tabbingElement.removeChild(tabElement);
this.contentElement.removeChild(tabElement.paneElement);
this.tabs.splice(tabElement.tabbingIndex, 1);
if(this.tabs.length !== 0) {
if(tabElement.tabbingIndex === 0) {
this.tabs[0].activate();
} else if(tabElement.tabbingIndex - 1 < this.tabs.length) {
this.tabs[tabElement.tabbingIndex - 1].activate();
} else {
this.tabs[this.tabs.length - 1].activate();
}
for(var i = tabElement.tabbingIndex, len = this.tabs.length; i < len; ++i) {
this.tabs[i].tabbingIndex = i;
}
}
this.tabRemoved(tabElement);
};
// disassembles element strucutre
this.remove = function() {
this.containerElement.parentNode.removeChild(this.containerElement);
};
this.tabRemoved = function(tab) {};
};
return repoindex;
})(repoindex || {});

View File

@ -45,6 +45,10 @@
.replace(/'/g, "&#039;");
};
repoindex.getElement = function(id) {
return typeof id === "string" ? document.getElementById(id) : id;
};
repoindex.pkgNamesFromDeps = function(dependencyInfos) {
if(dependencyInfos) {
var names = new Array(dependencyInfos.length);
@ -179,7 +183,7 @@
};
repoindex.setTree = function(id, nodes) {
var element = typeof id === "string" ? document.getElementById(id) : id;
var element = repoindex.getElement(id);
element.wipeChildren();
element.className = "file-tree";
// has root?
@ -283,6 +287,21 @@
});
};
repoindex.makeElementId = function(someName) {
if(someName) {
return "id_" + someName.replace(/\+/g, "--plus--")
.replace(/\?/g, "--question--")
.replace(/\\/g, "--bslash--")
.replace(/\//g, "--slash--")
.replace(/[\[\]\{\}\(\)]/g, "--bracket--")
.replace(/\./g, "--point--")
.replace(/\*/g, "--star--")
.replace(/[^0-1,a-z,A-Z,]/g, "--other--");
} else {
return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
}
};
repoindex.addField = function(element, fieldName, value) {
var nameElement = document.createElement("th");
nameElement.appendChild(document.createTextNode(fieldName));
@ -301,16 +320,25 @@
repoindex.setPackageNames(repoindex.addField(element, fieldName), packageNames, pageName);
};
repoindex.makeCloseButton = function() {
var closeButton = document.createElement("button");
closeButton.setAttribute("type", "button");
closeButton.setAttribute("class", "close");
closeButton.setAttribute("aria-label", "Close");
var closeButtonSpan = document.createElement("span");
closeButtonSpan.setAttribute("aria-hidden", "true");
closeButtonSpan.appendChild(document.createTextNode("\u00D7"));
closeButton.appendChild(closeButtonSpan);
return closeButton;
};
repoindex.makeInfoPanel = function(headingText, closeFunc) {
var panelElement = document.createElement("div");
panelElement.className = "panel panel-default info-container";
var panelHeadingElement = document.createElement("div");
panelHeadingElement.className = "panel-heading";
panelHeadingElement.appendChild(document.createTextNode(headingText));
var closeButton = document.createElement("button");
closeButton.setAttribute("type", "button");
closeButton.setAttribute("class", "close");
closeButton.setAttribute("aria-label", "Close");
var closeButton = repoindex.makeCloseButton();
closeButton.onclick = function() {
if(panelElement.parentNode) {
panelElement.parentNode.removeChild(panelElement);
@ -319,10 +347,6 @@
}
}
};
var closeButtonSpan = document.createElement("span");
closeButtonSpan.setAttribute("aria-hidden", "true");
closeButtonSpan.appendChild(document.createTextNode("\u00D7"));
closeButton.appendChild(closeButtonSpan);
panelHeadingElement.appendChild(closeButton);
panelElement.appendChild(panelHeadingElement);
var panelBodyElement = document.createElement("div");
@ -347,6 +371,7 @@
repoindex.makeInfoTable = function() {
var tableElement = document.createElement("table");
tableElement.className = "info-table";
tableElement.appendChild(repoindex.makeColumnGroup(["30%", "70%"]));
var tbodyElement = document.createElement("tbody");
tableElement.appendChild(tbodyElement);