blob: 44f40247fc928e8697534a3a21a9060a253751b6 [file] [log] [blame] [raw]
// Copyright (c) 2018, Compiler Explorer Authors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
'use strict';
var options = require('options'),
_ = require('underscore'),
$ = require('jquery');
function LibsWidget(langId, dropdownButton, state, onChangeCallback) {
this.dropdownButton = dropdownButton;
this.currentLangId = langId;
this.initButtons();
this.domRoot = null;
this.onChangeCallback = onChangeCallback;
this.availableLibs = {};
this.updateAvailableLibs(langId);
_.each(state.libs, _.bind(function (lib) {
this.markLibrary(lib.name, lib.ver, true);
}, this));
}
LibsWidget.prototype.initButtons = function () {
this.noLibsPanel = $('#libs-dropdown .no-libs');
this.libsEntry = $('#libs-entry .input-group');
};
LibsWidget.prototype.initLangDefaultLibs = function () {
var defaultLibs = options.defaultLibs[this.currentLangId];
if (!defaultLibs) return;
_.each(defaultLibs.split(':'), _.bind(function (libPair) {
var pairSplits = libPair.split('.');
if (pairSplits.length === 2) {
var lib = pairSplits[0];
var ver = pairSplits[1];
this.markLibrary(lib, ver, true);
}
}, this));
};
LibsWidget.prototype.updateAvailableLibs = function () {
if (!this.availableLibs[this.currentLangId]) {
this.availableLibs[this.currentLangId] = $.extend(true, {}, options.libs[this.currentLangId]);
}
this.initLangDefaultLibs();
this.updateLibsDropdown();
};
LibsWidget.prototype.setNewLangId = function (langId) {
this.currentLangId = langId;
};
LibsWidget.prototype.lazyDropdownLoad = function () {
var libsCount = _.keys(this.availableLibs[this.currentLangId]).length;
if (libsCount === 0) {
return this.noLibsPanel;
}
if (this.domRoot === null) {
var MAX_COLUMNS = 3;
this.domRoot = $('<div></div>');
var libsPanel = $('<div></div>')
.addClass('card-columns');
var currentColumn = -1;
var getOrCreateNextColumn = function () {
var column = null;
currentColumn++;
if (libsPanel.children()[currentColumn] != null) {
column = $(libsPanel.children()[currentColumn]);
} else {
column = $('<div></div>')
.addClass('card');
libsPanel.append(column);
}
if (currentColumn >= MAX_COLUMNS - 1) currentColumn = -1;
return column;
};
var libsInUse = this.listUsedLibs();
_.each(this.availableLibs[this.currentLangId], _.bind(function (libEntry, id) {
var newLibCard = this.libsEntry.clone();
var label = newLibCard.find('.input-group-prepend label')
.text(libEntry.name)
.prop('title', libEntry.description || '')
.prop('for', id);
var select = newLibCard.find('select')
.prop('id', id)
.append($('<option>', {
value: '-',
text: '-'
}));
_.each(libEntry.versions, _.bind(function (version, versionId) {
select.append($('<option>', {
value: versionId,
text: version.version,
selected: libsInUse[id] && libsInUse[id] === versionId
}));
}, this));
label.toggleClass('bg-success text-white', select.val() !== '-');
select.on('change', _.bind(function () {
var newVal = select.val();
label.toggleClass('bg-success text-white', newVal !== '-');
// Disable every version for this lib
_.each(libEntry.versions, _.bind(function (version, verId) {
this.markLibrary(id, verId, false);
}, this));
if (newVal !== '-') {
this.markLibrary(id, newVal, true);
}
this.onChangeCallback();
}, this));
var column = getOrCreateNextColumn();
column.append(newLibCard);
}, this));
this.domRoot.append(libsPanel);
return this.domRoot;
}
return this.domRoot;
};
LibsWidget.prototype.updateLibsDropdown = function () {
this.dropdownButton.popover({
container: 'body',
content: _.bind(this.lazyDropdownLoad, this),
html: true,
placement: 'bottom',
trigger: 'click',
template: '<div class="popover libs-popover" role="tooltip"><div class="arrow"></div>' +
'<h3 class="popover-header"></h3>' +
'<div class="popover-body"></div></div>'
});
};
LibsWidget.prototype.markLibrary = function (name, version, used) {
if (this.availableLibs[this.currentLangId] &&
this.availableLibs[this.currentLangId][name] &&
this.availableLibs[this.currentLangId][name].versions[version]) {
this.availableLibs[this.currentLangId][name].versions[version].used = used;
}
};
LibsWidget.prototype.get = function () {
return _.map(this.listUsedLibs(), function (item, libId) {
return {name: libId, ver: item};
});
};
LibsWidget.prototype.listUsedLibs = function () {
var libs = {};
_.each(this.availableLibs[this.currentLangId], function (library, libId) {
_.each(library.versions, function (version, ver) {
if (library.versions[ver].used) {
// We trust the invariant of only 1 used version at any given time per lib
libs[libId] = ver;
}
});
});
return libs;
};
LibsWidget.prototype.getLibsInUse = function () {
var libs = [];
_.each(this.availableLibs[this.currentLangId], function (library) {
_.each(library.versions, function (version, ver) {
if (library.versions[ver].used) {
// We trust the invariant of only 1 used version at any given time per lib
libs.push(library.versions[ver]);
}
});
});
return libs;
};
module.exports = {
Widget: LibsWidget
};