439 lines
17 KiB
JavaScript
439 lines
17 KiB
JavaScript
/**
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; under version 2
|
|
* of the License (non-upgradable).
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* Copyright (c) 2018 (original work) Open Assessment Technologies SA ;
|
|
*/
|
|
|
|
define([
|
|
'jquery',
|
|
'i18n',
|
|
'ui/feedback',
|
|
'./depends-on-property',
|
|
'./secondary-property'
|
|
], function ($, __, feedback, dependsOn, secondaryProps) {
|
|
'use strict';
|
|
|
|
function _createCopyToClipboardHandler($field) {
|
|
var
|
|
successFeedback = $field.data('copy-success-feedback')
|
|
|| __('Resource Identifier has been copied to the clipboard'),
|
|
failureFeedback = $field.data('copy-failure-feedback')
|
|
|| __('Resource Identifier could not be copied to the clipboard');
|
|
|
|
return function () {
|
|
var success;
|
|
try {
|
|
$field.select();
|
|
success = document.execCommand('copy');
|
|
$field.blur();
|
|
if (success) {
|
|
feedback().success(successFeedback);
|
|
} else {
|
|
feedback().error(failureFeedback);
|
|
}
|
|
} catch (err) {
|
|
feedback().error(__('Your browser does not support copying to the clipboard'));
|
|
}
|
|
}
|
|
}
|
|
|
|
function _cloneField($field) {
|
|
return $field.clone()
|
|
// To make MS browsers happy, value needs to be removed and re-added
|
|
.val('')
|
|
.attr({readonly: true, type: 'text'});
|
|
}
|
|
|
|
/**
|
|
* Add a field with URI of an item etc and a button to copy it to the clipboard
|
|
* @param $container
|
|
* @private
|
|
*/
|
|
function _initializeCopyToClipboard($container) {
|
|
// Early return in case:
|
|
// 1. isInstanceForm that will not work with jquery|querySelector
|
|
// 2. The field has already been added
|
|
if (!document.getElementById('tao.forms.instance') || $('.uri-container').length) {
|
|
return;
|
|
}
|
|
|
|
$container.find('#id, .copy-to-clipboard').each(function () {
|
|
var $field = $(this),
|
|
$fieldCopy = _cloneField($field),
|
|
$button = $('<span>', {class: 'icon-clipboard clipboard-command', title: __('Copy to clipboard')}),
|
|
$label = $('<span>', {class: 'form_desc', text: __('Resource Identifier')}),
|
|
$fieldBox = $('<span>', {class: 'uri-container'}),
|
|
value = $field.val();
|
|
|
|
if ($field.attr('id') === 'id') {
|
|
$field.remove();
|
|
$field = $fieldCopy;
|
|
|
|
$fieldBox.append([$field, $button]);
|
|
|
|
$container.find('div')
|
|
.first()
|
|
.after($('<div>').append([$label, $fieldBox]));
|
|
$fieldBox.height($field.outerHeight());
|
|
} else {
|
|
$fieldBox.height($field.outerHeight());
|
|
$field.wrap($fieldBox).parent().append($button);
|
|
}
|
|
|
|
$button.on('click', _createCopyToClipboardHandler($field));
|
|
$field.addClass('final').val(value);
|
|
});
|
|
}
|
|
|
|
|
|
/**
|
|
* Toggle availability of mode switch (advanced/simple)
|
|
*
|
|
* @param newMode
|
|
* @private
|
|
*/
|
|
function _toggleModeBtn(newMode) {
|
|
var $modeToggle = $('.property-mode');
|
|
if (newMode === 'disabled') {
|
|
$modeToggle.addClass('disabled');
|
|
} else {
|
|
$modeToggle.removeClass('disabled');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reposition the radio buttons or checkboxes of a property and make them look nice.
|
|
*
|
|
* @param $container the container in which to search and upgrade buttons
|
|
* @param type string the type of input we want to upgrade 'checkbox' or 'radio' by default we use radio
|
|
* @private
|
|
*/
|
|
function _upgradeButtons($container, type) {
|
|
|
|
//if the type is not radio or checkbox we put by default radio
|
|
if (type !== 'radio' && type !== 'checkbox') {
|
|
type = 'radio';
|
|
}
|
|
var selector = '.form_checklst';
|
|
var notSelector = '';
|
|
if (type === 'radio') {
|
|
selector = '.form_radlst';
|
|
notSelector = '.form_checklst, ';
|
|
}
|
|
|
|
$container.find(selector).not(notSelector + '.property-' + type + '-list').each(function () {
|
|
var $radioList = $(this);
|
|
$radioList.addClass('property-' + type + '-list');
|
|
$radioList.parent().addClass('property-' + type + '-list-box');
|
|
$radioList.each(function () {
|
|
var $block = $(this),
|
|
$inputs = $block.find('input');
|
|
|
|
if ($inputs.length <= 2) {
|
|
$block.find('br').remove();
|
|
}
|
|
|
|
$inputs.each(function () {
|
|
var $input = $(this),
|
|
$label = $block.find('label[for="' + this.id + '"]'),
|
|
$icon = $('<span>', {'class': 'icon-' + type});
|
|
|
|
$label.prepend($icon);
|
|
$label.prepend($input);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
|
|
/**
|
|
* Get reference to property container. If it doesn't' exist create one and add it to the DOM.
|
|
*
|
|
* @returns {*|HTMLElement}
|
|
*/
|
|
function getPropertyContainer() {
|
|
var $propertyContainer = $('.content-block .property-container');
|
|
if ($propertyContainer.length) {
|
|
return $propertyContainer;
|
|
}
|
|
$propertyContainer = $('<div>', {'class': 'property-container'});
|
|
$('.content-block .form-group').first().before($propertyContainer);
|
|
return $propertyContainer;
|
|
}
|
|
|
|
|
|
/**
|
|
* Add properties to the designated container. Also add some CSS classes for easier access.
|
|
*
|
|
* @param $properties
|
|
* @private
|
|
*/
|
|
function _wrapPropsInContainer($properties) {
|
|
var $propertyContainer = getPropertyContainer(),
|
|
// the reason why this is not done via a simple counter is that
|
|
// the function could have been called multiple times, e.g. when
|
|
// properties are created dynamically.
|
|
hasAlreadyProperties = !!$propertyContainer.find('.property-block').length;
|
|
|
|
|
|
$properties.each(function () {
|
|
var $property = $(this);
|
|
if ($property.attr !== undefined) {
|
|
var type = (function () {
|
|
var $propertyMode = $('.property-mode');
|
|
|
|
switch ($property.attr('id').replace(/_?property_[\d]+/, '')) {
|
|
case 'ro':
|
|
return 'readonly-property';
|
|
case 'parent':
|
|
return 'parent-property';
|
|
default:
|
|
var $editIcon = $property.find('.icon-edit'),
|
|
$editContainer = $property.children('div:first');
|
|
|
|
var $indexIcon = $property.find('.icon-find');
|
|
|
|
$editContainer.addClass('property-edit-container');
|
|
|
|
|
|
_hideProperties($editContainer);
|
|
_hideIndexes($editContainer);
|
|
|
|
if ($propertyMode.hasClass('property-mode-simple')) {
|
|
$indexIcon.hide();
|
|
} else if ($propertyMode.hasClass('property-mode-advanced')) {
|
|
$indexIcon.show();
|
|
}
|
|
|
|
//on click on edit icon show property form or hide it
|
|
$editIcon.on('click', function () {
|
|
//form is close so open it (hide index, show property)
|
|
if (!$editContainer.parent().hasClass('property-edit-container-open')) {
|
|
//hide index and show properties
|
|
_hideIndexes($editContainer);
|
|
_showProperties($editContainer);
|
|
$editContainer.slideToggle(function () {
|
|
$editContainer.parent().toggleClass('property-edit-container-open');
|
|
});
|
|
}
|
|
//it is open so switch between index and property or close it
|
|
else {
|
|
// close form
|
|
if ($($('.property', $editContainer)[0]).is(':visible')) {
|
|
$editContainer.slideToggle(function () {
|
|
$editContainer.parent().toggleClass('property-edit-container-open');
|
|
//hide properties
|
|
_hideProperties($editContainer);
|
|
});
|
|
}
|
|
// hide index and show properties
|
|
else {
|
|
//hide index properties
|
|
_hideIndexes($editContainer);
|
|
//show properties
|
|
_showProperties($editContainer);
|
|
}
|
|
}
|
|
});
|
|
|
|
//on click on index icon show index form or hide it
|
|
$indexIcon.on('click', function () {
|
|
//if form property is simple we can show index form
|
|
if ($('.property-mode').hasClass('property-mode-advanced')) {
|
|
//form is close so open it (hide property, show index)
|
|
if (!$editContainer.parent().hasClass('property-edit-container-open')) {
|
|
//hide index and show properties
|
|
_hideProperties($editContainer);
|
|
_showIndexes($editContainer);
|
|
$editContainer.slideToggle(function () {
|
|
$editContainer.parent().toggleClass('property-edit-container-open');
|
|
});
|
|
}
|
|
//it is open so switch between index and property or close it
|
|
else {
|
|
// close form
|
|
if ($($('.index', $editContainer)[0]).is(':visible')) {
|
|
$editContainer.slideToggle(function () {
|
|
$editContainer.parent().toggleClass('property-edit-container-open');
|
|
//hide indexes
|
|
_hideIndexes($editContainer);
|
|
});
|
|
}
|
|
// hide properties and show indexes
|
|
else {
|
|
_hideProperties($editContainer);
|
|
//show properties
|
|
_showIndexes($editContainer);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
return 'regular-property';
|
|
}
|
|
}());
|
|
$property.addClass(!hasAlreadyProperties ? 'property-block-first property-block ' + type : 'property-block ' + type);
|
|
$propertyContainer.append($property);
|
|
hasAlreadyProperties = true;
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
/**
|
|
* Make properties look nice
|
|
*
|
|
* @param $properties (optional)
|
|
*/
|
|
function init($properties) {
|
|
var $container = $('.content-block .xhtml_form:first form');
|
|
if (!$container.length) {
|
|
return;
|
|
}
|
|
|
|
_initializeCopyToClipboard($container);
|
|
|
|
// case no or empty argument -> find all properties not upgraded yet
|
|
if (!$properties || !$properties.length) {
|
|
$properties = $container.children('div[id*="property_"]').not('.property-block');
|
|
}
|
|
if (!$properties.length) {
|
|
if ($container.children('[name="tao.forms.instance"]').length) {
|
|
secondaryProps.init($container);
|
|
}
|
|
return;
|
|
}
|
|
_wrapPropsInContainer($properties);
|
|
_upgradeButtons($container, 'radio');
|
|
_upgradeButtons($container, 'checkbox');
|
|
_toggleModeBtn('disabled');
|
|
_showErrors($container);
|
|
_checkRegularPropertyLabels($properties);
|
|
}
|
|
|
|
function _showErrors($container) {
|
|
var $editContainer;
|
|
var $error = $container.find('.error');
|
|
if ($error.length) {
|
|
$editContainer = $error.closest('.property-edit-container');
|
|
if ($editContainer.length) {
|
|
_hideIndexes($editContainer);
|
|
_showProperties($editContainer);
|
|
$editContainer.slideToggle(function () {
|
|
$editContainer.parent().toggleClass('property-edit-container-open');
|
|
});
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
function _hideProperties($container) {
|
|
$('.property', $container).each(function () {
|
|
var $currentTarget = $(this);
|
|
while (!_.isEqual($currentTarget.parent()[0], $container[0])) {
|
|
$currentTarget = $currentTarget.parent();
|
|
}
|
|
$currentTarget.hide();
|
|
});
|
|
_toggleModeBtn('disabled');
|
|
}
|
|
|
|
function _showProperties($container) {
|
|
$('.property', $container).each(function () {
|
|
var $currentTarget = $(this);
|
|
while (!_.isEqual($currentTarget.parent()[0], $container[0])) {
|
|
$currentTarget = $currentTarget.parent();
|
|
}
|
|
if ($(this).hasClass('property-depends-on')) {
|
|
if ($(this)[0].length > 1) {
|
|
dependsOn.toggle($(this), $currentTarget, $container);
|
|
}
|
|
return;
|
|
}
|
|
$currentTarget.show();
|
|
});
|
|
//show or hide the list values select
|
|
var elt = $('[class*="property-type"]', $container).parent("div").next("div");
|
|
|
|
var propertiesTypes = ['list', 'tree'];
|
|
var re = new RegExp(propertiesTypes.join('$|').concat('$'));
|
|
|
|
if (re.test($('[class*="property-type"]', $container).val())) {
|
|
if (elt.css('display') === 'none') {
|
|
elt.show();
|
|
elt.find('select').removeAttr('disabled');
|
|
}
|
|
} else if (elt.css('display') !== 'none') {
|
|
elt.css('display', 'none');
|
|
elt.find('select').prop('disabled', "disabled");
|
|
}
|
|
|
|
_toggleModeBtn('enabled');
|
|
}
|
|
|
|
function _hideIndexes($container) {
|
|
$('.index', $container).each(function () {
|
|
var $currentTarget = $(this);
|
|
while (!_.isEqual($currentTarget.parent()[0], $container[0])) {
|
|
$currentTarget = $currentTarget.parent();
|
|
}
|
|
$currentTarget.hide();
|
|
});
|
|
$('.index-remover', $container).each(function () {
|
|
$(this).parent().hide();
|
|
});
|
|
}
|
|
|
|
function _showIndexes($container) {
|
|
$('.index', $container).each(function () {
|
|
var $currentTarget = $(this);
|
|
while (!_.isEqual($currentTarget.parent()[0], $container[0])) {
|
|
$currentTarget = $currentTarget.parent();
|
|
}
|
|
$currentTarget.show();
|
|
});
|
|
$('.index-remover', $container).each(function () {
|
|
$(this).parent().show();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Checks and updates property labels
|
|
* @param {Object} $properties - properties object
|
|
*/
|
|
function _checkRegularPropertyLabels($properties) {
|
|
$properties.each(function() {
|
|
if($(this).hasClass('regular-property')) {
|
|
var $parentHeadingLabel = $(this).find('.property-heading-label');
|
|
var $editBlockLabel = $(this).find('.property-edit-container input[name$="_label"]');
|
|
|
|
if ($editBlockLabel.val() !== '') {
|
|
$parentHeadingLabel.text($editBlockLabel.val());
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
return {
|
|
/**
|
|
* Initialize post renderer, this can be done multiple times
|
|
*/
|
|
init: init,
|
|
getPropertyContainer: getPropertyContainer
|
|
};
|
|
});
|
|
|
|
|