@instructure/canvas-rce
Version:
A component wrapping Canvas's usage of Tinymce
165 lines (161 loc) • 6.86 kB
JavaScript
/// <reference types="jquery" />
/*
* Copyright (C) 2011 - present Instructure, Inc.
*
* This file is part of Canvas.
*
* Canvas is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, version 3 of the License.
*
* Canvas 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 Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* TL;DR: Remove this file when possible.
*
* Please note that this file is considered very legacy. All instances of it
* should be evaluated and replaced with the newer and far better looking
* KyleMenu. The only other place that I've seen it in used is the file
* attendance.js which is on the chopping block at some point in the future.
* Once that file has been axed, then this file should be able to be removed.
*/
;
(function (global) {
// @ts-expect-error
const $ = global.jQuery || global.$;
if (!$) {
return;
}
// Simple dropdown list. Takes the list of attributes specified in "options" and displays them
// in a menu anchored to the selected element.
$.fn.dropdownList = Object.assign(
// @ts-expect-error
function (options) {
if (this.length) {
var _this$offset, _this$outerHeight, _$div$offset$left, _$div$width, _$$width;
let $div = $('#instructure_dropdown_list');
if (options === 'hide' || options === 'remove' || $div.data('current_dropdown_initiator') === this[0]) {
$div.remove().data('current_dropdown_initiator', null);
return this;
}
options = $.extend({}, $.fn.dropdownList.defaults, options);
let $list = $div.children('div.list');
if (!$list.length) {
$div = $("<div id='instructure_dropdown_list'><div class='list ui-widget-content'></div></div>").appendTo('body');
$(document).mousedown(event => {
if ($div.data('current_dropdown_initiator') && !$(event.target).closest('#instructure_dropdown_list').length) {
$div.hide().data('current_dropdown_initiator', null);
}
}).mouseup(event => {
if ($div.data('current_dropdown_initiator') && !$(event.target).closest('#instructure_dropdown_list').length) {
$div.hide();
setTimeout(() => {
$div.data('current_dropdown_initiator', null);
}, 100);
}
}).add(this).add($div).keydown(event => {
if ($div.data('current_dropdown_initiator')) {
const $current = $div.find('.ui-state-hover,.ui-state-active');
if (event.keyCode === 38) {
// up
if ($current.length && $current.prev().length) {
$current.removeClass('ui-state-hover ui-state-active').addClass('minimal').prev().addClass('ui-state-hover').removeClass('minimal').find('span').focus();
} else {
;
window.$item?.focus();
}
return false;
} else if (event.keyCode === 40) {
// down
if (!$current.length) {
$div.find('.option:first').addClass('ui-state-hover').removeClass('minimal').find('span').focus();
} else if ($current.next().length) {
$current.removeClass('ui-state-hover ui-state-active').addClass('minimal').next().addClass('ui-state-hover').removeClass('minimal').find('span').focus();
}
return false;
} else if (event.keyCode === 13 && $current.length) {
$current.click();
return false;
} else {
$div.hide().data('current_dropdown_initiator', null);
}
}
});
$div.find('.option').removeClass('ui-state-hover ui-state-active').addClass('minimal');
$div.click(_event => {
$div.hide().data('current_dropdown_initiator', null);
});
$list = $div.children('div.list');
}
$div.data('current_dropdown_initiator', this[0]);
if (options.width) {
$div.width(options.width);
}
if (options.height) {
$div.find('.list').css('maxHeight', options.height);
}
$list.empty();
$.each(options.options, (optionHtml, callback) => {
const $option = $("<div class='option minimal' style='cursor: pointer; padding: 2px 5px; overflow: hidden; white-space: nowrap;'>" + " <span tabindex='-1'>" + optionHtml.toString() + '</span>' + '</div>').appendTo($list);
function unhoverOtherOptions() {
$option.parent().find('div.option').removeClass('ui-state-hover ui-state-active').addClass('minimal');
}
if ($.isFunction(callback)) {
$option.addClass('ui-state-default').bind({
mouseenter() {
unhoverOtherOptions();
$option.addClass('ui-state-hover').removeClass('minimal');
},
mouseleave: unhoverOtherOptions,
mousedown(event) {
event.preventDefault();
unhoverOtherOptions();
$option.addClass('ui-state-active').removeClass('minimal');
},
mouseup: unhoverOtherOptions,
click: callback
});
} else {
$option.addClass('ui-state-disabled').bind({
mousedown(event) {
event.preventDefault();
}
});
}
});
const offset = (_this$offset = this.offset()) !== null && _this$offset !== void 0 ? _this$offset : {
top: 0,
left: 0
};
const height = (_this$outerHeight = this.outerHeight()) !== null && _this$outerHeight !== void 0 ? _this$outerHeight : 0;
$div.css({
whiteSpace: 'nowrap',
position: 'absolute',
top: offset.top + height,
left: offset.left + 5,
right: ''
}).hide().show();
// this is a fix so that if the dropdown ends up being off the page then move it back in so that it is on the page.
if (((_$div$offset$left = $div.offset()?.left) !== null && _$div$offset$left !== void 0 ? _$div$offset$left : 0) + ((_$div$width = $div.width()) !== null && _$div$width !== void 0 ? _$div$width : 0) > ((_$$width = $(window).width()) !== null && _$$width !== void 0 ? _$$width : 0)) {
$div.css({
left: '',
right: 0
});
}
}
return this;
}, {
defaults: {
height: 250,
width: 'auto'
}
});
// @ts-expect-error
})(typeof window !== 'undefined' ? window : this);
export {};