Refactoring/rewrite of modal boxes handling

This commit is contained in:
Frederic Guillot
2017-01-02 17:01:27 -05:00
parent d49ce63e51
commit 3833c12ccc
173 changed files with 1526 additions and 1654 deletions

View File

@@ -1,28 +1,27 @@
KB.component('submit-cancel', function (containerElement, options) {
KB.component('confirm-buttons', function (containerElement, options) {
var isLoading = false;
function onSubmit() {
isLoading = true;
KB.find('#modal-submit-button').replace(buildButton());
KB.trigger('modal.submit');
KB.find('#modal-confirm-button').replace(buildButton());
window.location.href = options.url;
}
function onCancel() {
KB.trigger('modal.cancel');
_KB.get('Popover').close();
KB.trigger('modal.close');
}
function onStop() {
isLoading = false;
KB.find('#modal-submit-button').replace(buildButton());
KB.find('#modal-confirm-button').replace(buildButton());
}
function buildButton() {
var button = KB.dom('button')
.click(onSubmit)
.attr('id', 'modal-submit-button')
.attr('type', 'submit')
.attr('class', 'btn btn-blue');
.attr('id', 'modal-confirm-button')
.attr('type', 'button')
.attr('class', 'btn btn-red');
if (isLoading) {
button
@@ -32,6 +31,10 @@ KB.component('submit-cancel', function (containerElement, options) {
;
}
if (options.tabindex) {
button.attr('tabindex', options.tabindex);
}
return button
.text(options.submitLabel)
.build();

View File

@@ -0,0 +1,192 @@
KB.component('file-upload', function (containerElement, options) {
var inputFileElement = null;
var dropzoneElement = null;
var files = [];
var currentFileIndex = null;
function onProgress(e) {
if (e.lengthComputable) {
var progress = e.loaded / e.total;
var percentage = Math.floor(progress * 100);
KB.find('#file-progress-' + currentFileIndex).attr('value', progress);
KB.find('#file-percentage-' + currentFileIndex).replaceText('(' + percentage + '%)');
}
}
function onError() {
var errorElement = KB.dom('div').addClass('file-error').text(options.labelUploadError).build();
KB.find('#file-item-' + currentFileIndex).add(errorElement);
}
function onComplete() {
currentFileIndex++;
if (currentFileIndex < files.length) {
KB.http.uploadFile(options.url, files[currentFileIndex], onProgress, onComplete, onError);
} else {
KB.trigger('modal.stop');
KB.trigger('modal.hide');
var alertElement = KB.dom('div')
.addClass('alert')
.addClass('alert-success')
.text(options.labelSuccess)
.build();
var buttonElement = KB.dom('button')
.attr('type', 'button')
.addClass('btn')
.addClass('btn-blue')
.click(onCloseWindow)
.text(options.labelCloseSuccess)
.build();
KB.dom(dropzoneElement).replace(KB.dom('div').add(alertElement).add(buttonElement).build());
}
}
function onCloseWindow() {
window.location.reload();
}
function onSubmit() {
currentFileIndex = 0;
uploadFiles();
}
function onFileChange() {
files = inputFileElement.files;
showFiles();
}
function onClickFileBrowser() {
files = [];
currentFileIndex = 0;
inputFileElement.click();
}
function onDragOver(e) {
e.stopPropagation();
e.preventDefault();
}
function onDrop(e) {
e.stopPropagation();
e.preventDefault();
files = e.dataTransfer.files;
showFiles();
}
function uploadFiles() {
if (files.length > 0) {
KB.http.uploadFile(options.url, files[currentFileIndex], onProgress, onComplete, onError);
}
}
function showFiles() {
if (files.length > 0) {
KB.trigger('modal.enable');
KB.dom(dropzoneElement)
.empty()
.add(buildFileListElement());
} else {
KB.trigger('modal.disable');
KB.dom(dropzoneElement)
.empty()
.add(buildInnerDropzoneElement());
}
}
function buildFileInputElement() {
return KB.dom('input')
.attr('id', 'file-input-element')
.attr('type', 'file')
.attr('name', 'files[]')
.attr('multiple', true)
.on('change', onFileChange)
.hide()
.build();
}
function buildInnerDropzoneElement() {
var dropzoneLinkElement = KB.dom('a')
.attr('href', '#')
.text(options.labelChooseFiles)
.click(onClickFileBrowser)
.build();
return KB.dom('div')
.attr('id', 'file-dropzone-inner')
.text(options.labelDropzone + ' ' + options.labelOr + ' ')
.add(dropzoneLinkElement)
.build();
}
function buildDropzoneElement() {
var dropzoneElement = KB.dom('div')
.attr('id', 'file-dropzone')
.add(buildInnerDropzoneElement())
.build();
dropzoneElement.ondragover = onDragOver;
dropzoneElement.ondrop = onDrop;
dropzoneElement.ondragover = onDragOver;
return dropzoneElement;
}
function buildFileListItem(index) {
var isOversize = false;
var progressElement = KB.dom('progress')
.attr('id', 'file-progress-' + index)
.attr('value', 0)
.build();
var percentageElement = KB.dom('span')
.attr('id', 'file-percentage-' + index)
.text('(0%)')
.build();
var itemElement = KB.dom('li')
.attr('id', 'file-item-' + index)
.add(progressElement)
.text(' ' + files[index].name + ' ')
.add(percentageElement);
if (files[index].size > options.maxSize) {
itemElement.add(KB.dom('div').addClass('file-error').text(options.labelOversize).build());
isOversize = true;
}
if (isOversize) {
KB.trigger('modal.disable');
}
return itemElement.build();
}
function buildFileListElement() {
var fileListElement = KB.dom('ul')
.attr('id', 'file-list')
.build();
for (var i = 0; i < files.length; i++) {
fileListElement.appendChild(buildFileListItem(i));
}
return fileListElement;
}
this.render = function () {
KB.on('modal.submit', onSubmit);
inputFileElement = buildFileInputElement();
dropzoneElement = buildDropzoneElement();
containerElement.appendChild(inputFileElement);
containerElement.appendChild(dropzoneElement);
};
});

View File

@@ -15,19 +15,19 @@ KB.keyboardShortcuts = function () {
} else if (forms.length > 1) {
if (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA') {
$(document.activeElement).parents("form").submit();
} else if (_KB.get("Popover").isOpen()) {
$("#popover-container form").submit();
} else if (KB.modal.isOpen()) {
KB.modal.getForm().submit();
}
}
}
KB.onKey('?', function () {
_KB.get("Popover").open($("body").data("keyboard-shortcut-url"));
KB.modal.open(KB.find('body').data('keyboardShortcutUrl'));
});
KB.onKey('Escape', function () {
if (! KB.exists('#suggest-menu')) {
_KB.get("Popover").close();
KB.trigger('modal.close');
_KB.get("Dropdown").close();
}
});
@@ -49,25 +49,25 @@ KB.keyboardShortcuts = function () {
});
KB.onKey('n', function () {
_KB.get("Popover").open($("#board").data("task-creation-url"));
KB.modal.open(KB.find('#board').data('taskCreationUrl'), 'large', false);
});
}
if (KB.exists('#task-view')) {
KB.onKey('e', function () {
_KB.get("Popover").open(KB.find('#task-view').data('editUrl'));
KB.modal.open(KB.find('#task-view').data('editUrl'), 'large');
});
KB.onKey('c', function () {
_KB.get("Popover").open(KB.find('#task-view').data('commentUrl'));
KB.modal.open(KB.find('#task-view').data('commentUrl'));
});
KB.onKey('s', function () {
_KB.get("Popover").open(KB.find('#task-view').data('subtaskUrl'));
KB.modal.open(KB.find('#task-view').data('subtaskUrl'));
});
KB.onKey('l', function () {
_KB.get("Popover").open(KB.find('#task-view').data('internalLinkUrl'));
KB.modal.open(KB.find('#task-view').data('internalLinkUrl'));
});
}

View File

@@ -0,0 +1,29 @@
(function () {
function getLink(e) {
if (e.target.tagName === 'I') {
return e.target.parentNode.getAttribute('href');
}
return e.target.getAttribute('href')
}
KB.onClick('.js-modal-large', function (e) {
KB.modal.open(getLink(e), 'large', false);
});
KB.onClick('.js-modal-medium', function (e) {
KB.modal.open(getLink(e), 'medium', false);
});
KB.onClick('.js-modal-small', function (e) {
KB.modal.open(getLink(e), 'small', false);
});
KB.onClick('.js-modal-confirm', function (e) {
KB.modal.open(getLink(e), 'small');
});
KB.onClick('.js-modal-close', function () {
KB.modal.close();
});
}());

View File

@@ -0,0 +1,120 @@
KB.component('screenshot', function (containerElement) {
var pasteCatcher = null;
var inputElement = null;
function onPaste(e) {
// Firefox doesn't have the property e.clipboardData.items (only Chrome)
if (e.clipboardData && e.clipboardData.items) {
var items = e.clipboardData.items;
if (items) {
for (var i = 0; i < items.length; i++) {
// Find an image in pasted elements
if (items[i].type.indexOf("image") !== -1) {
var blob = items[i].getAsFile();
// Get the image as base64 data
var reader = new FileReader();
reader.onload = function (event) {
createImage(event.target.result);
};
reader.readAsDataURL(blob);
}
}
}
} else {
// Handle Firefox
setTimeout(checkInput, 100);
}
}
function initialize() {
destroy();
if (! window.Clipboard) {
// Insert the content editable at the top to avoid scrolling down in the board view
pasteCatcher = document.createElement('div');
pasteCatcher.id = 'screenshot-pastezone';
pasteCatcher.contentEditable = true;
pasteCatcher.style.opacity = 0;
pasteCatcher.style.position = 'fixed';
pasteCatcher.style.top = 0;
pasteCatcher.style.right = 0;
pasteCatcher.style.width = 0;
document.body.insertBefore(pasteCatcher, document.body.firstChild);
pasteCatcher.focus();
// Set the focus when clicked anywhere in the document
document.addEventListener('click', setFocus);
// Set the focus when clicked in screenshot dropzone
document.getElementById('screenshot-zone').addEventListener('click', setFocus);
}
window.addEventListener('paste', onPaste, false);
}
function destroy() {
if (pasteCatcher !== null) {
document.body.removeChild(pasteCatcher);
} else if (document.getElementById('screenshot-pastezone')) {
document.body.removeChild(document.getElementById('screenshot-pastezone'));
}
document.removeEventListener('click', setFocus);
pasteCatcher = null;
}
function setFocus() {
if (pasteCatcher !== null) {
pasteCatcher.focus();
}
}
function checkInput() {
var child = pasteCatcher.childNodes[0];
if (child) {
// If the user pastes an image, the src attribute
// will represent the image as a base64 encoded string.
if (child.tagName === 'IMG') {
createImage(child.src);
}
}
pasteCatcher.innerHTML = '';
}
function createImage(blob) {
var pastedImage = new Image();
pastedImage.src = blob;
// Send the image content to the form variable
pastedImage.onload = function() {
var sourceSplit = blob.split('base64,');
inputElement.value = sourceSplit[1];
};
var zone = document.getElementById('screenshot-zone');
zone.innerHTML = '';
zone.className = 'screenshot-pasted';
zone.appendChild(pastedImage);
destroy();
initialize();
}
this.render = function () {
inputElement = KB.dom('input')
.attr('type', 'hidden')
.attr('name', 'screenshot')
.build();
containerElement.appendChild(inputElement);
initialize();
};
});

View File

@@ -1,5 +1,24 @@
KB.component('select-dropdown-autocomplete', function(containerElement, options) {
var componentElement, inputElement, inputHiddenElement;
var componentElement, inputElement, inputHiddenElement, chevronIconElement, loadingIconElement;
function onLoadingStart() {
KB.dom(loadingIconElement).show();
KB.dom(chevronIconElement).hide();
}
function onLoadingStop() {
KB.dom(loadingIconElement).hide();
KB.dom(chevronIconElement).show();
}
function onScroll() {
var menuElement = KB.find('#select-dropdown-menu');
if (menuElement) {
var componentPosition = componentElement.getBoundingClientRect();
menuElement.style('top', (document.body.scrollTop + componentPosition.bottom) + 'px');
}
}
function onKeyDown(e) {
switch (KB.utils.getKey(e)) {
@@ -66,8 +85,10 @@ KB.component('select-dropdown-autocomplete', function(containerElement, options)
destroyDropdownMenu();
if (options.redirect) {
var regex = new RegExp(options.redirect.regex, 'g');
window.location = options.redirect.url.replace(regex, value);
window.location = options.redirect.url.replace(new RegExp(options.redirect.regex, 'g'), value);
} else if (options.replace) {
onLoadingStart();
KB.modal.replace(options.replace.url.replace(new RegExp(options.replace.regex, 'g'), value));
}
}
@@ -158,7 +179,7 @@ KB.component('select-dropdown-autocomplete', function(containerElement, options)
return KB.dom('ul')
.attr('id', 'select-dropdown-menu')
.style('top', componentPosition.bottom + 'px')
.style('top', (document.body.scrollTop + componentPosition.bottom) + 'px')
.style('left', componentPosition.left + 'px')
.style('width', componentPosition.width + 'px')
.style('maxHeight', (window.innerHeight - componentPosition.bottom - 20) + 'px')
@@ -203,11 +224,20 @@ KB.component('select-dropdown-autocomplete', function(containerElement, options)
}
this.render = function () {
var dropdownIconElement = KB.dom('i')
KB.on('select.dropdown.loading.start', onLoadingStart);
KB.on('select.dropdown.loading.stop', onLoadingStop);
chevronIconElement = KB.dom('i')
.attr('class', 'fa fa-chevron-down select-dropdown-chevron')
.click(toggleDropdownMenu)
.build();
loadingIconElement = KB.dom('span')
.hide()
.addClass('select-loading-icon')
.add(KB.dom('i').attr('class', 'fa fa-spinner fa-pulse').build())
.build();
inputHiddenElement = KB.dom('input')
.attr('type', 'hidden')
.attr('name', options.name)
@@ -227,7 +257,8 @@ KB.component('select-dropdown-autocomplete', function(containerElement, options)
.addClass('select-dropdown-input-container')
.add(inputHiddenElement)
.add(inputElement)
.add(dropdownIconElement)
.add(chevronIconElement)
.add(loadingIconElement)
.build();
containerElement.appendChild(componentElement);
@@ -237,5 +268,7 @@ KB.component('select-dropdown-autocomplete', function(containerElement, options)
KB.on(eventName, function() { inputElement.focus(); });
});
}
window.addEventListener('scroll', onScroll, false);
};
});

View File

@@ -0,0 +1,94 @@
KB.component('submit-buttons', function (containerElement, options) {
var isLoading = false;
var isDisabled = options.disabled || false;
var submitLabel = options.submitLabel;
var formActionElement = null;
function onSubmit() {
isLoading = true;
KB.find('#modal-submit-button').replace(buildButton());
KB.trigger('modal.submit');
}
function onCancel() {
KB.trigger('modal.close');
}
function onStop() {
isLoading = false;
KB.find('#modal-submit-button').replace(buildButton());
}
function onDisable() {
isLoading = false;
isDisabled = true;
KB.find('#modal-submit-button').replace(buildButton());
}
function onEnable() {
isLoading = false;
isDisabled = false;
KB.find('#modal-submit-button').replace(buildButton());
}
function onHide() {
KB.dom(formActionElement).hide();
}
function onUpdateSubmitLabel(eventData) {
submitLabel = eventData.submitLabel;
KB.find('#modal-submit-button').replace(buildButton());
}
function buildButton() {
var button = KB.dom('button')
.attr('id', 'modal-submit-button')
.attr('type', 'submit')
.attr('class', 'btn btn-' + (options.color || 'blue'));
if (KB.modal.isOpen()) {
button.click(onSubmit);
}
if (options.tabindex) {
button.attr('tabindex', options.tabindex);
}
if (isLoading) {
button
.disable()
.add(KB.dom('i').attr('class', 'fa fa-spinner fa-pulse').build())
.text(' ')
;
}
if (isDisabled) {
button.disable();
}
return button
.text(submitLabel)
.build();
}
this.render = function () {
KB.on('modal.stop', onStop);
KB.on('modal.disable', onDisable);
KB.on('modal.enable', onEnable);
KB.on('modal.hide', onHide);
KB.on('modal.submit.label', onUpdateSubmitLabel);
var formActionElementBuilder = KB.dom('div')
.attr('class', 'form-actions')
.add(buildButton());
if (KB.modal.isOpen()) {
formActionElementBuilder
.text(' ' + options.orLabel + ' ')
.add(KB.dom('a').attr('href', '#').click(onCancel).text(options.cancelLabel).build())
}
formActionElement = formActionElementBuilder.build();
containerElement.appendChild(formActionElement);
};
});

View File

@@ -62,7 +62,7 @@ KB.component('suggest-menu', function(containerElement, options) {
}
function getParentElement() {
var selectors = ['.popover-form', '#popover-content', 'body'];
var selectors = ['#modal-content form', '#modal-content', 'body'];
for (var i = 0; i < selectors.length; i++) {
var element = document.querySelector(selectors[i]);

View File

@@ -74,8 +74,6 @@ KB.component('task-move-position', function (containerElement, options) {
"column_id": getColumnId(),
"swimlane_id": getSwimlaneId(),
"position": position
}).success(function () {
window.location.reload(true);
}).error(function (response) {
if (response) {
onError(response.message);
@@ -150,7 +148,6 @@ KB.component('task-move-position', function (containerElement, options) {
KB.on('modal.submit', onSubmit);
var form = KB.dom('div')
.on('submit', onSubmit)
.add(KB.dom('div').attr('id', 'message-container').build())
.add(KB.html.label(options.swimlaneLabel, 'form-swimlanes'))
.add(buildSwimlaneSelect())