chore!(core): remove deprecated jQuery and jQuery UI

"jQuery is deprecated and will be removed with Nextcloud 19"
Well... At least it is removed now 😉

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
This commit is contained in:
Ferdinand Thiessen 2026-01-19 17:27:31 +01:00
parent 00a5c028a4
commit b0df06d533
No known key found for this signature in database
GPG key ID: 7E849AE05218500F
36 changed files with 88 additions and 2537 deletions

File diff suppressed because it is too large Load diff

View file

@ -51,7 +51,6 @@
"@vueuse/components": "^11.3.0",
"@vueuse/core": "^11.3.0",
"@vueuse/integrations": "^11.3.0",
"backbone": "^1.6.1",
"blurhash": "^2.0.5",
"browserslist-useragent-regexp": "^4.1.3",
"camelcase": "^9.0.0",
@ -67,9 +66,6 @@
"focus-trap": "^7.8.0",
"handlebars": "^4.7.8",
"is-svg": "^6.1.0",
"jquery": "~3.7",
"jquery-ui": "1.14.1",
"jquery-ui-dist": "^1.13.3",
"libphonenumber-js": "^1.12.36",
"lodash": "^4.17.23",
"marked": "^17.0.2",
@ -81,9 +77,6 @@
"pinia": "^2.3.1",
"query-string": "^9.3.1",
"regenerator-runtime": "^0.14.1",
"select2": "3.5.1",
"snap.js": "^2.0.9",
"strengthify": "github:nextcloud/strengthify#0.5.9",
"throttle-debounce": "^5.0.2",
"underscore": "1.13.7",
"url-search-params-polyfill": "^8.2.5",

View file

@ -197,12 +197,6 @@ const config = {
new NodePolyfillPlugin({
additionalAliases: ['process'],
}),
new webpack.ProvidePlugin({
// Provide jQuery to jquery plugins as some are loaded before $ is exposed globally.
// We need to provide the path to node_moduels as otherwise npm link will fail due
// to tribute.js checking for jQuery in @nextcloud/vue
jQuery: require.resolve('jquery'),
}),
new WorkboxPlugin.GenerateSW({
swDest: 'preview-service-worker.js',

View file

@ -53,7 +53,7 @@ class BeforeTemplateRenderedListener implements IEventListener {
Util::addTranslations('core');
if ($event->getResponse()->getRenderAs() !== TemplateResponse::RENDER_AS_ERROR) {
Util::addScript('core', 'merged-template-prepend', 'core', true);
Util::addScript('core', 'mimetypelist', 'core', true);
// If installed and background job is set to ajax, add dedicated script
if ($this->appConfig->getValueString('core', 'backgroundjobs_mode', 'ajax') === 'ajax') {

View file

@ -122,84 +122,6 @@
flex-shrink: 1;
// Add some spacing so the last entry looks ok
margin-inline-end: calc(3 * var(--default-grid-baseline));
// legacy JQuery header menus
// TODO: we already migrated our own code and deprecated it - can be removed together with global jQuery
> div,
> form {
height: 100%;
position: relative;
> .menutoggle {
display: flex;
justify-content: center;
align-items: center;
width: var(--header-height);
height: var(--header-menu-item-height);
cursor: pointer;
opacity: 0.85;
padding: 0;
margin: 2px 0;
&:focus {
opacity: 1;
}
&:focus-visible {
outline: none;
}
}
> .menu {
background-color: var(--color-main-background);
filter: drop-shadow(0 1px 5px var(--color-box-shadow));
border-radius: var(--border-radius-large);
box-sizing: border-box;
z-index: 2000;
position: absolute;
max-width: 350px;
@include header-menu-height();
inset-inline-end: 8px; // relative to parent
top: var(--header-height);
margin: 0;
overflow-y: auto;
&:not(.popovermenu) {
display: none;
}
/* Dropdown arrow */
&:after {
border: 10px solid transparent;
border-bottom-color: var(--color-main-background);
bottom: 100%;
content: ' ';
height: 0;
width: 0;
position: absolute;
pointer-events: none;
inset-inline-end: 10px;
}
& > div,
& > ul {
-webkit-overflow-scrolling: touch;
@include header-menu-height();
}
}
.emptycontent {
h2 {
font-weight: normal;
font-size: 16px;
}
[class^='icon-'],
[class*='icon-'] {
background-size: 48px;
height: 48px;
width: 48px;
}
}
}
}
// Public layout related headers

View file

@ -13,14 +13,6 @@ input, textarea, select, button, div[contenteditable=true], div[contenteditable=
font-family: var(--font-face);
}
.select2-container-multi .select2-choices .select2-search-field input, .select2-search input, .ui-widget {
font-family: var(--font-face) !important;
}
.select2-container.select2-drop-above .select2-choice {
background-image: unset !important;
}
$opacity-disabled: .7;
/* Simple selector to allow easy overriding */
@ -61,7 +53,6 @@ input:not([type="range"]) {
}
/* Default global values */
div.select2-drop .select2-search input, // TODO: REMOVE WHEN DROPPING SELECT2
input[type='submit'],
input[type='button'],
input[type='reset'],
@ -241,7 +232,6 @@ input:not(
[type='button'],
[type='reset'],
.multiselect__input,
.select2-input,
.action-input__input,
[class^="vs__"]
),
@ -269,11 +259,6 @@ textarea {
}
}
.multiselect__input, .select2-input {
background-color: var(--color-main-background);
color: var(--color-main-text);
}
textarea, div[contenteditable=true] {
padding: 12px;
height: auto;
@ -548,185 +533,6 @@ input[type='radio'] {
}
}
/* Select2 overriding. Merged to core with vendor stylesheet */
div.select2-drop {
margin-top: -2px;
background-color: var(--color-main-background);
&.select2-drop-active {
border-color: var(--color-border-dark);
}
.avatar {
display: inline-block;
margin-inline-end: 8px;
vertical-align: middle;
img {
cursor: pointer;
}
}
.select2-search input {
min-height: auto;
background: var(--icon-search-dark) no-repeat !important;
background-origin: content-box !important;
}
.select2-results {
max-height: 250px;
margin: 0;
padding: 0;
.select2-result-label {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
span {
cursor: pointer;
em {
cursor: inherit;
background: unset;
}
}
}
.select2-result,
.select2-no-results,
.select2-searching {
position: relative;
display: list-item;
padding: 12px;
background-color: transparent;
cursor: pointer;
color: var(--color-text-maxcontrast);
}
.select2-result {
&.select2-selected {
background-color: var(--color-background-dark);
}
}
.select2-highlighted {
background-color: var(--color-background-dark);
color: var(--color-main-text);
}
}
}
body[dir='ltr'] div.select2-drop .select2-search input {
background-position: right center !important;
}
body[dir='rtl'] div.select2-drop .select2-search input {
background-position: left center !important;
}
.select2-chosen,
#select2-drop {
.avatar,
.avatar img {
cursor: pointer;
}
}
div.select2-container-multi {
.select2-choices,
&.select2-container-active .select2-choices {
box-shadow: none;
white-space: nowrap;
text-overflow: ellipsis;
background: var(--color-main-background);
color: var(--color-text-maxcontrast) !important;
box-sizing: content-box;
border-radius: var(--border-radius-large);
border: 2px solid var(--color-border-dark);
margin: 0;
padding: 6px;
min-height: 44px;
&:focus-within {
border-color: var(--color-primary-element)
}
.select2-search-choice {
line-height: 20px;
padding-inline-start: 5px;
&.select2-search-choice-focus,
&:hover,
&:active,
& {
background-image: none;
background-color: var(--color-main-background);
color: var(--color-text-maxcontrast);
border: 1px solid var(--color-border-dark);
}
.select2-search-choice-close {
display: none;
}
}
.select2-search-field input {
line-height: 20px;
min-height: 28px;
max-height: 28px;
color: var(--color-main-text);
&.select2-active {
background: none !important;
}
}
}
}
div.select2-container {
margin: 3px;
margin-inline-start: 0;
&.select2-container-multi .select2-choices {
display: flex;
flex-wrap: wrap;
li {
float: none;
}
}
a.select2-choice {
box-shadow: none;
white-space: nowrap;
text-overflow: ellipsis;
background: var(--color-main-background);
color: var(--color-text-maxcontrast) !important;
box-sizing: content-box;
border-radius: var(--border-radius-large);
border: 2px solid var(--color-border-dark);
margin: 0;
padding: 6px 12px;
min-height: 44px;
&:focus-within {
border-color: var(--color-primary-element)
}
.select2-search-choice {
line-height: 20px;
padding-inline-start: 5px;
background-image: none;
background-color: var(--color-background-dark);
border-color: var(--color-background-dark);
.select2-search-choice-close {
display: none;
}
&.select2-search-choice-focus,
&:hover {
background-color: var(--color-border);
border-color: var(--color-border);
}
}
.select2-arrow {
background: none;
border-radius: 0;
border: none;
b {
background: var(--icon-triangle-s-dark) no-repeat center !important;
opacity: .5;
}
}
&:hover .select2-arrow b,
&:focus .select2-arrow b,
&:active .select2-arrow b {
opacity: .7;
}
.select2-search-field input {
line-height: 20px;
}
}
}
/* Vue v-select */
.v-select {
margin: 3px;

View file

@ -445,232 +445,6 @@ code {
}
}
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
overflow: hidden;
text-overflow: ellipsis;
}
.ui-icon-circle-triangle-e {
background-image: url('../img/actions/play-next.svg?v=1');
}
.ui-icon-circle-triangle-w {
background-image: url('../img/actions/play-previous.svg?v=1');
}
/* ---- jQuery UI datepicker ---- */
.ui-widget.ui-datepicker {
margin-top: 10px;
padding: 4px 8px;
width: auto;
border-radius: var(--border-radius);
border: none;
z-index: 1600 !important; // above sidebar
.ui-state-default,
.ui-widget-content .ui-state-default,
.ui-widget-header .ui-state-default {
border: 1px solid transparent;
background: inherit;
}
.ui-widget-header {
padding: 7px;
font-size: 13px;
border: none;
background-color: var(--color-main-background);
color: var(--color-main-text);
.ui-datepicker-title {
line-height: 1;
font-weight: normal;
}
.ui-icon {
opacity: .5;
&.ui-icon-circle-triangle-e,
&.ui-icon-circle-triangle-w {
background-position: center center;
background-repeat: no-repeat;
}
}
.ui-state-hover .ui-icon {
opacity: 1;
}
}
.ui-datepicker-calendar {
th {
font-weight: normal;
color: var(--color-text-maxcontrast);
opacity: .8;
width: 26px;
padding: 2px;
}
tr:hover {
background-color: inherit;
}
td {
&.ui-datepicker-today a:not(.ui-state-hover) {
background-color: var(--color-background-darker);
}
&.ui-datepicker-current-day a.ui-state-active,
.ui-state-hover,
.ui-state-focus {
background-color: var(--color-primary-element);
color: var(--color-primary-element-text);
font-weight: bold;
}
&.ui-datepicker-week-end:not(.ui-state-disabled) :not(.ui-state-hover),
.ui-priority-secondary:not(.ui-state-hover) {
color: var(--color-text-maxcontrast);
opacity: .8;
}
}
}
}
body[dir='ltr'] .ui-widget.ui-datepicker .ui-widget-header .ui-icon {
&.ui-icon-circle-triangle-e {
background: url("../img/actions/arrow-right.svg");
}
&.ui-icon-circle-triangle-w {
background: url("../img/actions/arrow-left.svg");
}
}
body[dir='rtl'] .ui-widget.ui-datepicker .ui-widget-header .ui-icon {
&.ui-icon-circle-triangle-e {
background: url("../img/actions/arrow-left.svg");
}
&.ui-icon-circle-triangle-w {
background: url("../img/actions/arrow-right.svg");
}
}
.ui-datepicker-prev, .ui-datepicker-next {
border: var(--color-border-dark);
background: var(--color-main-background);
}
/* ---- jQuery UI timepicker ---- */
.ui-widget.ui-timepicker {
margin-top: 10px !important;
width: auto !important;
border-radius: var(--border-radius);
z-index: 1600 !important;
.ui-widget-content {
border: none !important;
}
.ui-state-default,
.ui-widget-content .ui-state-default,
.ui-widget-header .ui-state-default {
border: 1px solid transparent;
background: inherit;
}
.ui-widget-header {
padding: 7px;
font-size: 13px;
border: none;
background-color: var(--color-main-background);
color: var(--color-main-text);
.ui-timepicker-title {
line-height: 1;
font-weight: normal;
}
}
/* AM/PM fix */
table.ui-timepicker tr .ui-timepicker-hour-cell:first-child {
margin-inline-start: 30px;
}
.ui-timepicker-table {
th {
font-weight: normal;
color: var(--color-text-maxcontrast);
opacity: .8;
&.periods {
padding: 0;
width: 30px;
line-height: 30px;
}
}
tr:hover {
background-color: inherit;
}
td {
&.ui-timepicker-hour-cell a.ui-state-active,
&.ui-timepicker-minute-cell a.ui-state-active,
.ui-state-hover,
.ui-state-focus {
background-color: var(--color-primary-element);
color: var(--color-primary-element-text);
font-weight: bold;
}
&.ui-timepicker-minutes:not(.ui-state-hover) {
color: var(--color-text-maxcontrast);
}
&.ui-timepicker-hours {
border-inline-end: 1px solid var(--color-border);
}
}
}
}
/* ---- jQuery UI datepicker & timepicker global rules ---- */
.ui-widget.ui-datepicker .ui-datepicker-calendar,
.ui-widget.ui-timepicker table.ui-timepicker {
tr {
display: flex;
flex-wrap: nowrap;
justify-content: space-between;
td {
flex: 1 1 auto;
margin: 0;
padding: 2px;
height: 26px;
width: 26px;
display: flex;
align-items: center;
justify-content: center;
> * {
border-radius: 50%;
text-align: center;
font-weight: normal;
color: var(--color-main-text);
display: block;
line-height: 18px;
width: 18px;
height: 18px;
padding: 3px;
font-size: .9em;
}
}
}
}
/* ---- DIALOGS ---- */
.ui-dialog {
position: fixed !important;
}
span.ui-icon {
float: left;
margin-block: 3px 30px;
margin-inline: 0 7px;
}
/* ---- TOOLTIPS ---- */
.extra-data {
padding-inline-end: 5px !important;
}
/* ---- TAGS ---- */
#tagsdialog {

View file

@ -1,4 +0,0 @@
[
"mimetypelist.js",
"select2-toggleselect.js"
]

View file

@ -1,48 +0,0 @@
/**
* SPDX-FileCopyrightText: 2016 ownCloud Inc.
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/* global Select2 */
/**
* Select2 extension for toggling values in a multi-select dropdown
*
* @param Select2
*/
(function(Select2) {
const Select2FindHighlightableChoices = Select2.class.multi.prototype.findHighlightableChoices
Select2.class.multi.prototype.findHighlightableChoices = function() {
if (this.opts.toggleSelect) {
return this.results.find('.select2-result-selectable:not(.select2-disabled)')
}
return Select2FindHighlightableChoices.apply(this, arguments)
}
const Select2TriggerSelect = Select2.class.multi.prototype.triggerSelect
Select2.class.multi.prototype.triggerSelect = function(data) {
if (this.opts.toggleSelect && this.val().indexOf(this.id(data)) !== -1) {
const self = this
const val = this.id(data)
const selectionEls = this.container.find('.select2-search-choice').filter(function() {
return (self.id($(this).data('select2-data')) === val)
})
if (this.unselect(selectionEls)) {
// also unselect in dropdown
this.results.find('.select2-result.select2-selected').each(function() {
const $this = $(this)
if (self.id($this.data('select2-data')) === val) {
$this.removeClass('select2-selected')
}
})
this.clearSearch()
}
return false
} else {
return Select2TriggerSelect.apply(this, arguments)
}
}
})(Select2)

View file

@ -8,7 +8,8 @@ import ContactsMenu from '../views/ContactsMenu.vue'
import ContactsMenuService from '../services/ContactsMenuService.ts'
/**
* @todo move to contacts menu code https://github.com/orgs/nextcloud/projects/31#card-21213129
* Set up the contacts menu component ("ContactsMenu")
* This is the menu where users can access their contacts or other users on this instance.
*/
export function setUp() {
const mountPoint = document.getElementById('contactsmenu')

View file

@ -8,7 +8,8 @@ import Vue from 'vue'
import AppMenu from './AppMenu.vue'
/**
*
* Set up the main menu component ("AppMenu")
* This is the top left menu where users can navigate between different apps.
*/
export function setUp() {
Vue.mixin({

View file

@ -7,7 +7,8 @@ import Vue from 'vue'
import AccountMenu from '../views/AccountMenu.vue'
/**
*
* Set up the user menu component ("AccountMenu")
* This is the top right menu where users can access their settings, profile, logout, etc.
*/
export function setUp() {
const mountPoint = document.getElementById('user-menu')

View file

@ -7,7 +7,6 @@
import ClipboardJS from 'clipboard'
import { dav } from 'davclient.js'
import Handlebars from 'handlebars'
import $ from 'jquery'
import moment from 'moment'
import _ from 'underscore'
import { initCore } from './init.js'
@ -16,17 +15,6 @@ import { getRequestToken } from './OC/requesttoken.ts'
import OCA from './OCA/index.js'
import OCP from './OCP/index.js'
// TODO: switch to `jquery-ui` package and import widgets and effects individually
// `jquery-ui-dist` is used as a workaround for the issue of missing effects
import 'jquery-ui-dist/jquery-ui.js'
import 'jquery-ui-dist/jquery-ui.css'
import 'jquery-ui-dist/jquery-ui.theme.css'
import 'select2'
import 'select2/select2.css'
import 'snap.js/dist/snap.js'
import 'strengthify'
import 'strengthify/strengthify.css'
/**
*
*/
@ -37,25 +25,6 @@ function warnIfNotTesting() {
}
}
/**
* Mark a function as deprecated and automatically
* warn if used!
*
* @param {Function} func the library to deprecate
* @param {string} funcName the name of the library
* @param {number} version the version this gets removed
* @return {Function}
*/
function deprecate(func, funcName, version) {
const oldFunc = func
const newFunc = function() {
warnIfNotTesting(`The ${funcName} library is deprecated! It will be removed in nextcloud ${version}.`)
return oldFunc.apply(this, arguments)
}
Object.assign(newFunc, oldFunc)
return newFunc
}
/**
*
* @param global
@ -81,10 +50,9 @@ function setDeprecatedProp(global, cb, msg) {
})
}
setDeprecatedProp(['$', 'jQuery'], () => $, 'The global jQuery is deprecated. It will be removed in a later versions without another warning. Please ship your own.')
setDeprecatedProp(['_'], () => _, 'The global underscore is deprecated. It will be removed in a later versions without another warning. Please ship your own.')
setDeprecatedProp(['Clipboard', 'ClipboardJS'], () => ClipboardJS, 'please ship your own, this will be removed in Nextcloud 20')
window.dav = dav
setDeprecatedProp(['dav'], () => dav, 'please ship your own. It will be removed in a later versions without another warning. Please ship your own.')
setDeprecatedProp('Handlebars', () => Handlebars, 'please ship your own, this will be removed in Nextcloud 20')
setDeprecatedProp('moment', () => moment, 'please ship your own, this will be removed in Nextcloud 20')
@ -101,7 +69,6 @@ setDeprecatedProp('oc_webroot', () => OC.webroot, 'use OC.getRootPath() instead,
setDeprecatedProp('OCDialogs', () => OC.dialogs, 'use OC.dialogs instead, this will be removed in Nextcloud 20')
window.OCP = OCP
window.OCA = OCA
$.fn.select2 = deprecate($.fn.select2, 'select2', 19)
/**
* translate a string

View file

@ -1,148 +0,0 @@
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { getCurrentUser } from '@nextcloud/auth'
import { generateUrl } from '@nextcloud/router'
import $ from 'jquery'
/**
* This plugin inserts the right avatar for the user, depending on, whether a
* custom avatar is uploaded - which it uses then - or not, and display a
* placeholder with the first letter of the users name instead.
* For this it queries the core_avatar_get route, thus this plugin is fit very
* tightly for owncloud, and it may not work anywhere else.
*
* You may use this on any <div></div>
* Here I'm using <div class="avatardiv"></div> as an example.
*
* There are 5 ways to call this:
*
* 1. $('.avatardiv').avatar('jdoe', 128);
* This will make the div to jdoe's fitting avatar, with a size of 128px.
*
* 2. $('.avatardiv').avatar('jdoe');
* This will make the div to jdoe's fitting avatar. If the div already has a
* height, it will be used for the avatars size. Otherwise this plugin will
* search for 'size' DOM data, to use for avatar size. If neither are available
* it will default to 64px.
*
* 3. $('.avatardiv').avatar();
* This will search the DOM for 'user' data, to use as the username. If there
* is no username available it will default to a placeholder with the value of
* "?". The size will be determined the same way, as the second example.
*
* 4. $('.avatardiv').avatar('jdoe', 128, true);
* This will behave like the first example, except it will also append random
* hashes to the custom avatar images, to force image reloading in IE8.
*
* 5. $('.avatardiv').avatar('jdoe', 128, undefined, true);
* This will behave like the first example, but it will hide the avatardiv, if
* it will display the default placeholder. undefined is the ie8fix from
* example 4 and can be either true, or false/undefined, to be ignored.
*
* 6. $('.avatardiv').avatar('jdoe', 128, undefined, true, callback);
* This will behave like the above example, but it will call the function
* defined in callback after the avatar is placed into the DOM.
*
*/
$.fn.avatar = function(user, size, ie8fix, hidedefault, callback, displayname) {
const setAvatarForUnknownUser = function(target) {
target.imageplaceholder('?')
target.css('background-color', '#b9b9b9')
}
if (typeof (user) !== 'undefined') {
user = String(user)
}
if (typeof (displayname) !== 'undefined') {
displayname = String(displayname)
}
if (typeof (size) === 'undefined') {
if (this.height() > 0) {
size = this.height()
} else if (this.data('size') > 0) {
size = this.data('size')
} else {
size = 64
}
}
this.height(size)
this.width(size)
if (typeof (user) === 'undefined') {
if (typeof (this.data('user')) !== 'undefined') {
user = this.data('user')
} else {
setAvatarForUnknownUser(this)
return
}
}
// sanitize
user = String(user).replace(/\//g, '')
const $div = this
let url
// If this is our own avatar we have to use the version attribute
if (user === getCurrentUser()?.uid) {
url = generateUrl(
'/avatar/{user}/{size}?v={version}',
{
user,
size: Math.ceil(size * window.devicePixelRatio),
version: window.oc_userconfig.avatar.version,
},
)
} else {
url = generateUrl(
'/avatar/{user}/{size}',
{
user,
size: Math.ceil(size * window.devicePixelRatio),
},
)
}
const img = new Image()
// If the new image loads successfully set it.
img.onload = function() {
$div.clearimageplaceholder()
$div.append(img)
if (typeof callback === 'function') {
callback()
}
}
// Fallback when avatar loading fails:
// Use old placeholder when a displayname attribute is defined,
// otherwise show the unknown user placeholder.
img.onerror = function() {
$div.clearimageplaceholder()
if (typeof (displayname) !== 'undefined') {
$div.imageplaceholder(user, displayname)
} else {
setAvatarForUnknownUser($div)
}
if (typeof callback === 'function') {
callback()
}
}
if (size < 32) {
$div.addClass('icon-loading-small')
} else {
$div.addClass('icon-loading')
}
img.width = size
img.height = size
img.src = url
img.alt = ''
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

View file

@ -1,264 +0,0 @@
/**
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/* Component containers
----------------------------------*/
.ui-widget-content {
border: 1px solid var(--color-border);
background: var(--color-main-background) none;
color: var(--color-main-text);
}
.ui-widget-content a {
color: var(--color-main-text);
}
.ui-widget-header {
border: none;
color: var(--color-main-text);
background-image: none;
}
.ui-widget-header a {
color: var(--color-main-text);
}
/* Interaction states
----------------------------------*/
.ui-state-default,
.ui-widget-content .ui-state-default,
.ui-widget-header .ui-state-default {
border: 1px solid var(--color-border);
background: var(--color-main-background) none;
font-weight: bold;
color: #555;
}
.ui-state-default a,
.ui-state-default a:link,
.ui-state-default a:visited {
color: #555;
}
.ui-state-hover,
.ui-widget-content .ui-state-hover,
.ui-widget-header .ui-state-hover,
.ui-state-focus,
.ui-widget-content .ui-state-focus,
.ui-widget-header .ui-state-focus {
border: 1px solid #ddd;
background: var(--color-main-background) none;
font-weight: bold;
color: var(--color-main-text);
}
.ui-state-hover a,
.ui-state-hover a:hover,
.ui-state-hover a:link,
.ui-state-hover a:visited {
color: var(--color-main-text);
}
.ui-state-active,
.ui-widget-content .ui-state-active,
.ui-widget-header .ui-state-active {
border: 1px solid var(--color-primary-element);
background: var(--color-main-background) none;
font-weight: bold;
color: var(--color-main-text);
}
.ui-state-active a,
.ui-state-active a:link,
.ui-state-active a:visited {
color: var(--color-main-text);
}
/* Interaction Cues
----------------------------------*/
.ui-state-highlight,
.ui-widget-content .ui-state-highlight,
.ui-widget-header .ui-state-highlight {
border: 1px solid var(--color-main-background);
background: var(--color-main-background) none;
color: var(--color-main-text);
font-weight: 600;
}
.ui-state-highlight a,
.ui-widget-content .ui-state-highlight a,
.ui-widget-header .ui-state-highlight a {
color: var(--color-text-maxcontrast);
}
.ui-state-error,
.ui-widget-content .ui-state-error,
.ui-widget-header .ui-state-error {
border: var(--color-error);
background: var(--color-error) none;
color: #ffffff;
}
.ui-state-error a,
.ui-widget-content .ui-state-error a,
.ui-widget-header .ui-state-error a {
color: #ffffff;
}
.ui-state-error-text,
.ui-widget-content .ui-state-error-text,
.ui-widget-header .ui-state-error-text {
color: #ffffff;
}
/* Icons
----------------------------------*/
.ui-state-default .ui-icon {
background-image: url('images/ui-icons_1d2d44_256x240.png');
}
.ui-state-hover .ui-icon,
.ui-state-focus .ui-icon {
background-image: url('images/ui-icons_1d2d44_256x240.png');
}
.ui-state-active .ui-icon {
background-image: url('images/ui-icons_1d2d44_256x240.png');
}
.ui-state-highlight .ui-icon {
background-image: url('images/ui-icons_ffffff_256x240.png');
}
.ui-state-error .ui-icon,
.ui-state-error-text .ui-icon {
background-image: url('images/ui-icons_ffd27a_256x240.png');
}
.ui-icon.ui-icon-none {
display: none;
}
/* Misc visuals
----------------------------------*/
/* Overlays */
.ui-widget-overlay {
background: #666666 url('images/ui-bg_diagonals-thick_20_666666_40x40.png') 50% 50% repeat;
opacity: .5;
}
.ui-widget-shadow {
margin: -5px 0 0 -5px;
padding: 5px;
background: #000000 url('images/ui-bg_flat_10_000000_40x100.png') 50% 50% repeat-x;
opacity: .2;
border-radius: 5px;
}
/* Tabs customizations */
.ui-tabs {
border: none;
.ui-tabs-nav.ui-corner-all {
border-end-start-radius: 0;
border-end-end-radius: 0;
}
.ui-tabs-nav {
background: none;
margin-bottom: 15px;
.ui-state-default {
border: none;
border-bottom: 1px solid transparent;
font-weight: normal;
margin: 0 !important;
padding: 0 !important;
}
.ui-state-hover,
.ui-state-active {
border: none;
border-bottom: 1px solid var(--color-main-text);
color: var(--color-main-text);
a, a:link, a:hover, a:visited {
color: var(--color-main-text);
}
}
.ui-state-active {
font-weight: bold;
}
}
}
/* Select menus */
.ui-autocomplete {
&.ui-menu {
padding: 0;
/* scrolling starts from three items,
* so hide overflow and scrollbars for a clean layout */
&.item-count-1,
&.item-count-2 {
overflow-y: hidden;
}
.ui-menu-item a {
color: var(--color-text-maxcontrast);
display: block;
padding: 4px;
padding-inline-start: 14px;
&.ui-state-focus, &.ui-state-active {
box-shadow: inset 4px 0 var(--color-primary-element);
color: var(--color-main-text);
}
}
}
&.ui-widget-content {
background: var(--color-main-background);
border-top: none;
}
&.ui-corner-all {
border-radius: 0;
border-end-start-radius: var(--border-radius);
border-end-end-radius: var(--border-radius);
}
.ui-state-hover, .ui-widget-content .ui-state-hover,
.ui-widget-header .ui-state-hover,
.ui-state-focus,
.ui-widget-content .ui-state-focus,
.ui-widget-header .ui-state-focus {
border: 1px solid transparent;
background: inherit;
color: var(--color-primary-element);
}
.ui-menu-item {
a {
border-radius: 0 !important;
}
}
}
.ui-button.primary {
background-color: var(--color-primary-element);
color: var(--color-primary-element-text);
border: 1px solid var(--color-primary-element-text);
}
// fix ui-buttons on hover
.ui-button:hover {
font-weight:bold !important;
}
/* DRAGGABLE */
.ui-draggable-handle,
.ui-selectable {
touch-action: pan-y;
}

View file

@ -1,93 +0,0 @@
/**
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
.oc-dialog {
background: var(--color-main-background);
border-radius: var(--border-radius-large);
box-shadow: 0 0 30px var(--color-box-shadow);
color: var(--color-main-text);
padding: 24px;
z-index: 100001;
font-size: 100%;
box-sizing: border-box;
min-width: 200px;
top: 50%;
inset-inline-start: 50%;
transform: translate(-50%, -50%);
max-height: calc(100% - 20px);
max-width: calc(100% - 20px);
overflow: auto;
}
.oc-dialog-title {
background: var(--color-main-background);
}
.oc-dialog-buttonrow {
position: relative;
display: flex;
background: transparent;
inset-inline-end: 0;
bottom: 0;
padding: 0;
padding-top: 10px;
box-sizing: border-box;
width: 100%;
background-image: linear-gradient(rgba(255, 255, 255, 0.0), var(--color-main-background));
&.twobuttons {
justify-content: space-between;
}
&.onebutton,
&.twobuttons.aside {
justify-content: flex-end;
}
button {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
height: 44px;
min-width: 44px;
}
}
.oc-dialog-close {
position: absolute;
width: 44px !important;
height: 44px !important;
top: 4px;
inset-inline-end: 4px;
padding: 25px;
background: var(--icon-close-dark) no-repeat center;
opacity: .5;
border-radius: var(--border-radius-pill);
&:hover,
&:focus,
&:active {
opacity: 1;
}
}
.oc-dialog-dim {
background-color: #000;
opacity: .2;
z-index: 100001;
position: fixed;
top: 0;
inset-inline-start: 0;
width: 100%;
height: 100%;
}
body.theme--dark .oc-dialog-dim {
opacity: .8;
}
.oc-dialog-content {
width: 100%;
max-width: 550px;
}

View file

@ -1,17 +0,0 @@
/**
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import $ from 'jquery'
/**
* check if an element exists.
* allows you to write if ($('#myid').exists()) to increase readability
*
* @see {@link http://stackoverflow.com/questions/31044/is-there-an-exists-function-for-jquery}
* @return {boolean}
*/
$.fn.exists = function() {
return this.length > 0
}

View file

@ -1,19 +0,0 @@
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import $ from 'jquery'
/**
* Filter jQuery selector by attribute value
*
* @param {string} attrName attribute name
* @param {string} attrValue attribute value
* @return {void}
*/
$.fn.filterAttr = function(attrName, attrValue) {
return this.filter(function() {
return $(this).attr(attrName) === attrValue
})
}

View file

@ -1,44 +0,0 @@
/**
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import $ from 'jquery'
import './avatar.js'
import './exists.js'
import './filterattr.js'
import './ocdialog.js'
import './octemplate.js'
import './placeholder.js'
import './requesttoken.js'
import './selectrange.js'
import './showpassword.js'
import './ui-fixes.js'
import './css/jquery-ui-fixes.scss'
import './css/jquery.ocdialog.scss'
/**
* Disable automatic evaluation of responses for $.ajax() functions (and its
* higher-level alternatives like $.get() and $.post()).
*
* If a response to a $.ajax() request returns a content type of "application/javascript"
* JQuery would previously execute the response body. This is a pretty unexpected
* behaviour and can result in a bypass of our Content-Security-Policy as well as
* multiple unexpected XSS vectors.
*/
$.ajaxSetup({
contents: {
script: false,
},
})
/**
* Disable execution of eval in jQuery. We do require an allowed eval CSP
* configuration at the moment for handlebars et al. But for jQuery there is
* not much of a reason to execute JavaScript directly via eval.
*
* This thus mitigates some unexpected XSS vectors.
*/
$.globalEval = function() {
}

View file

@ -1,289 +0,0 @@
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { isA11yActivation } from '@nextcloud/vue/functions/a11y'
import { createFocusTrap } from 'focus-trap'
import $ from 'jquery'
$.widget('oc.ocdialog', {
options: {
width: 'auto',
height: 'auto',
closeButton: true,
closeOnEscape: true,
closeCallback: null,
modal: false,
},
_create() {
const self = this
this.originalCss = {
display: this.element[0].style.display,
width: this.element[0].style.width,
height: this.element[0].style.height,
}
this.originalTitle = this.element.attr('title')
this.options.title = this.options.title || this.originalTitle
this.$dialog = $('<div class="oc-dialog"></div>')
.attr({
// Setting tabIndex makes the div focusable
tabIndex: -1,
role: 'dialog',
'aria-modal': true,
})
.insertBefore(this.element)
this.$dialog.append(this.element.detach())
this.element.removeAttr('title').addClass('oc-dialog-content').appendTo(this.$dialog)
// Activate the primary button on enter if there is a single input
if (self.element.find('input').length === 1) {
const $input = self.element.find('input')
$input.on('keydown', function(event) {
if (isA11yActivation(event)) {
if (self.$buttonrow) {
const $button = self.$buttonrow.find('button.primary')
if ($button && !$button.prop('disabled')) {
$button.click()
}
}
}
})
}
this.$dialog.css({
display: 'inline-block',
position: 'fixed',
})
this.enterCallback = null
$(document).on('keydown keyup', function(event) {
if (
event.target !== self.$dialog.get(0)
&& self.$dialog.find($(event.target)).length === 0
) {
return
}
// Escape
if (
event.keyCode === 27
&& event.type === 'keydown'
&& self.options.closeOnEscape
) {
event.stopImmediatePropagation()
self.close()
return false
}
// Enter
if (event.keyCode === 13) {
event.stopImmediatePropagation()
if (self.enterCallback !== null) {
self.enterCallback()
event.preventDefault()
return false
}
if (event.type === 'keyup') {
event.preventDefault()
return false
}
return false
}
})
this._setOptions(this.options)
this._createOverlay()
this._useFocusTrap()
},
_init() {
this._trigger('open')
},
_setOption(key, value) {
const self = this
switch (key) {
case 'title':
if (this.$title) {
this.$title.text(value)
} else {
const $title = $('<h2 class="oc-dialog-title">'
+ value
+ '</h2>')
this.$title = $title.prependTo(this.$dialog)
}
this._setSizes()
break
case 'buttons':
if (this.$buttonrow) {
this.$buttonrow.empty()
} else {
const $buttonrow = $('<div class="oc-dialog-buttonrow"></div>')
this.$buttonrow = $buttonrow.appendTo(this.$dialog)
}
if (value.length === 1) {
this.$buttonrow.addClass('onebutton')
} else if (value.length === 2) {
this.$buttonrow.addClass('twobuttons')
} else if (value.length === 3) {
this.$buttonrow.addClass('threebuttons')
}
$.each(value, function(idx, val) {
const $button = $('<button>').text(val.text)
if (val.classes) {
$button.addClass(val.classes)
}
if (val.defaultButton) {
$button.addClass('primary')
self.$defaultButton = $button
}
self.$buttonrow.append($button)
$button.on('click keydown', function(event) {
if (isA11yActivation(event)) {
val.click.apply(self.element[0], arguments)
}
})
})
this.$buttonrow.find('button')
.on('focus', function() {
self.$buttonrow.find('button').removeClass('primary')
$(this).addClass('primary')
})
this._setSizes()
break
case 'style':
if (value.buttons !== undefined) {
this.$buttonrow.addClass(value.buttons)
}
break
case 'closeButton':
if (value) {
const $closeButton = $('<button class="oc-dialog-close"></button>')
$closeButton.attr('aria-label', t('core', 'Close "{dialogTitle}" dialog', { dialogTitle: this.$title || this.options.title }))
this.$dialog.prepend($closeButton)
$closeButton.on('click keydown', function(event) {
if (isA11yActivation(event)) {
self.options.closeCallback && self.options.closeCallback()
self.close()
}
})
} else {
this.$dialog.find('.oc-dialog-close').remove()
}
break
case 'width':
this.$dialog.css('width', value)
break
case 'height':
this.$dialog.css('height', value)
break
case 'close':
this.closeCB = value
break
}
// this._super(key, value);
$.Widget.prototype._setOption.apply(this, arguments)
},
_setOptions() {
// this._super(options);
$.Widget.prototype._setOptions.apply(this, arguments)
},
_setSizes() {
let lessHeight = 0
if (this.$title) {
lessHeight += this.$title.outerHeight(true)
}
if (this.$buttonrow) {
lessHeight += this.$buttonrow.outerHeight(true)
}
this.element.css({
height: 'calc(100% - ' + lessHeight + 'px)',
})
},
_createOverlay() {
if (!this.options.modal) {
return
}
const self = this
let contentDiv = $('#content')
if (contentDiv.length === 0) {
// nextcloud-vue compatibility
contentDiv = $('.content')
}
this.overlay = $('<div>')
.addClass('oc-dialog-dim')
.insertBefore(this.$dialog)
this.overlay.on('click keydown keyup', function(event) {
if (event.target !== self.$dialog.get(0) && self.$dialog.find($(event.target)).length === 0) {
event.preventDefault()
event.stopPropagation()
}
})
},
_destroyOverlay() {
if (!this.options.modal) {
return
}
if (this.overlay) {
this.overlay.off('click keydown keyup')
this.overlay.remove()
this.overlay = null
}
},
_useFocusTrap() {
// Create global stack if undefined
Object.assign(window, { _nc_focus_trap: window._nc_focus_trap || [] })
const dialogElement = this.$dialog[0]
this.focusTrap = createFocusTrap(dialogElement, {
allowOutsideClick: true,
trapStack: window._nc_focus_trap,
fallbackFocus: dialogElement,
})
this.focusTrap.activate()
},
_clearFocusTrap() {
this.focusTrap?.deactivate()
this.focusTrap = null
},
widget() {
return this.$dialog
},
setEnterCallback(callback) {
this.enterCallback = callback
},
unsetEnterCallback() {
this.enterCallback = null
},
close() {
this._clearFocusTrap()
this._destroyOverlay()
const self = this
// Ugly hack to catch remaining keyup events.
setTimeout(function() {
self._trigger('close', self)
}, 200)
self.$dialog.remove()
this.destroy()
},
destroy() {
if (this.$title) {
this.$title.remove()
}
if (this.$buttonrow) {
this.$buttonrow.remove()
}
if (this.originalTitle) {
this.element.attr('title', this.originalTitle)
}
this.element.removeClass('oc-dialog-content')
.css(this.originalCss).detach().insertBefore(this.$dialog)
this.$dialog.remove()
},
})

View file

@ -1,111 +0,0 @@
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import escapeHTML from 'escape-html'
import $ from 'jquery'
import logger from '../logger.js'
/**
* jQuery plugin for micro templates
*
* Strings are automatically escaped, but that can be disabled by setting
* escapeFunction to null.
*
* Usage examples:
*
* var htmlStr = '<p>Bake, uncovered, until the {greasystuff} is melted and the {pasta} is heated through, about {min} minutes.</p>'
* $(htmlStr).octemplate({greasystuff: 'cheese', pasta: 'macaroni', min: 10});
*
* var htmlStr = '<p>Welcome back {user}</p>';
* $(htmlStr).octemplate({user: 'John Q. Public'}, {escapeFunction: null});
*
* Be aware that the target string must be wrapped in an HTML element for the
* plugin to work. The following won't work:
*
* var textStr = 'Welcome back {user}';
* $(textStr).octemplate({user: 'John Q. Public'});
*
* For anything larger than one-liners, you can use a simple $.get() ajax
* request to get the template, or you can embed them it the page using the
* text/template type:
*
* <script id="contactListItemTemplate" type="text/template">
* <tr class="contact" data-id="{id}">
* <td class="name">
* <input type="checkbox" name="id" value="{id}" /><span class="nametext">{name}</span>
* </td>
* <td class="email">
* <a href="mailto:{email}">{email}</a>
* </td>
* <td class="phone">{phone}</td>
* </tr>
* </script>
*
* var $tmpl = $('#contactListItemTemplate');
* var contacts = // fetched in some ajax call
*
* $.each(contacts, function(idx, contact) {
* $contactList.append(
* $tmpl.octemplate({
* id: contact.getId(),
* name: contact.getDisplayName(),
* email: contact.getPreferredEmail(),
* phone: contact.getPreferredPhone(),
* });
* );
* });
*/
/**
* Object Template
* Inspired by micro templating done by e.g. underscore.js
*/
const Template = {
init(vars, options, elem) {
// Mix in the passed in options with the default options
this.vars = vars
this.options = $.extend({}, this.options, options)
this.elem = elem
const self = this
if (typeof this.options.escapeFunction === 'function') {
const keys = Object.keys(this.vars)
for (let key = 0; key < keys.length; key++) {
if (typeof this.vars[keys[key]] === 'string') {
this.vars[keys[key]] = self.options.escapeFunction(this.vars[keys[key]])
}
}
}
const _html = this._build(this.vars)
return $(_html)
},
// From stackoverflow.com/questions/1408289/best-way-to-do-variable-interpolation-in-javascript
_build(o) {
const data = this.elem.attr('type') === 'text/template' ? this.elem.html() : this.elem.get(0).outerHTML
try {
return data.replace(
/{([^{}]*)}/g,
function(a, b) {
const r = o[b]
return typeof r === 'string' || typeof r === 'number' ? r : a
},
)
} catch (error) {
logger.error('failed to build octemplate', { data, error })
}
},
options: {
escapeFunction: escapeHTML,
},
}
$.fn.octemplate = function(vars, options) {
vars = vars || {}
if (this.length) {
const _template = Object.create(Template)
return _template.init(vars, options, this)
}
}

View file

@ -1,169 +0,0 @@
/* eslint-disable jsdoc/require-jsdoc */
/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2013-2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { createHash } from 'crypto-browserify'
import $ from 'jquery'
import logger from '../logger.js'
/*
* Adds a background color to the element called on and adds the first character
* of the passed in string. This string is also the seed for the generation of
* the background color.
*
* You have following HTML:
*
* <div id="albumart"></div>
*
* And call this from Javascript:
*
* $('#albumart').imageplaceholder('The Album Title');
*
* Which will result in:
*
* <div id="albumart" style="background-color: rgb(121, 90, 171); ... ">T</div>
*
* You may also call it like this, to have a different background, than the seed:
*
* $('#albumart').imageplaceholder('The Album Title', 'Album Title');
*
* Resulting in:
*
* <div id="albumart" style="background-color: rgb(121, 90, 171); ... ">A</div>
*
*/
/*
* Alternatively, you can use the prototype function to convert your string to rgb colors:
*
* "a6741a86aded5611a8e46ce16f2ad646".toRgb()
*
* Will return the rgb parameters within the following object:
*
* Color {r: 208, g: 158, b: 109}
*
*/
function toRgb(s) {
// Normalize hash
let hash = s.toLowerCase()
// Already a md5 hash?
if (hash.match(/^([0-9a-f]{4}-?){8}$/) === null) {
createHash('md5')
.update(hash)
.digest('hex')
}
hash = hash.replace(/[^0-9a-f]/g, '')
function Color(r, g, b) {
this.r = r
this.g = g
this.b = b
}
function stepCalc(steps, ends) {
const step = new Array(3)
step[0] = (ends[1].r - ends[0].r) / steps
step[1] = (ends[1].g - ends[0].g) / steps
step[2] = (ends[1].b - ends[0].b) / steps
return step
}
function mixPalette(steps, color1, color2) {
const palette = []
palette.push(color1)
const step = stepCalc(steps, [color1, color2])
for (let i = 1; i < steps; i++) {
const r = parseInt(color1.r + (step[0] * i))
const g = parseInt(color1.g + (step[1] * i))
const b = parseInt(color1.b + (step[2] * i))
palette.push(new Color(r, g, b))
}
return palette
}
const red = new Color(182, 70, 157)
const yellow = new Color(221, 203, 85)
const blue = new Color(0, 130, 201) // Nextcloud blue
// Number of steps to go from a color to another
// 3 colors * 6 will result in 18 generated colors
const steps = 6
const palette1 = mixPalette(steps, red, yellow)
const palette2 = mixPalette(steps, yellow, blue)
const palette3 = mixPalette(steps, blue, red)
const finalPalette = palette1.concat(palette2).concat(palette3)
// Convert a string to an integer evenly
function hashToInt(hash, maximum) {
let finalInt = 0
const result = []
// Splitting evenly the string
for (let i = 0; i < hash.length; i++) {
// chars in md5 goes up to f, hex:16
result.push(parseInt(hash.charAt(i), 16) % 16)
}
// Adds up all results
for (const j in result) {
finalInt += result[j]
}
// chars in md5 goes up to f, hex:16
// make sure we're always using int in our operation
return parseInt(parseInt(finalInt) % maximum)
}
return finalPalette[hashToInt(hash, steps * 3)]
}
String.prototype.toRgb = function() {
logger.warn('String.prototype.toRgb is deprecated! It will be removed in Nextcloud 22.')
return toRgb(this)
}
$.fn.imageplaceholder = function(seed, text, size) {
text = text || seed
// Compute the hash
const rgb = toRgb(seed)
this.css('background-color', 'rgb(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ')')
// Placeholders are square
const height = this.height() || size || 32
this.height(height)
this.width(height)
// CSS rules
this.css('color', '#fff')
this.css('font-weight', 'normal')
this.css('text-align', 'center')
// calculate the height
this.css('line-height', height + 'px')
this.css('font-size', (height * 0.55) + 'px')
if (seed !== null && seed.length) {
const placeholderText = text.replace(/\s+/g, ' ').trim().split(' ', 2).map((word) => word[0].toUpperCase()).join('')
this.html(placeholderText)
}
}
$.fn.clearimageplaceholder = function() {
this.css('background-color', '')
this.css('color', '')
this.css('font-weight', '')
this.css('text-align', '')
this.css('line-height', '')
this.css('font-size', '')
this.html('')
this.removeClass('icon-loading')
this.removeClass('icon-loading-small')
}

View file

@ -1,14 +0,0 @@
/**
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import $ from 'jquery'
import { getRequestToken } from '../OC/requesttoken.ts'
$(document).on('ajaxSend', function(elm, xhr, settings) {
if (settings.crossDomain === false) {
xhr.setRequestHeader('requesttoken', getRequestToken())
xhr.setRequestHeader('OCS-APIREQUEST', 'true')
}
})

View file

@ -1,29 +0,0 @@
/**
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import $ from 'jquery'
/**
* select a range in an input field
*
* @see {@link http://stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area}
* @param {number} start start selection from
* @param {number} end number of char from start
* @return {void}
*/
$.fn.selectRange = function(start, end) {
return this.each(function() {
if (this.setSelectionRange) {
this.focus()
this.setSelectionRange(start, end)
} else if (this.createTextRange) {
const range = this.createTextRange()
range.collapse(true)
range.moveEnd('character', end)
range.moveStart('character', start)
range.select()
}
})
}

View file

@ -1,124 +0,0 @@
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/** @typedef {import('jquery')} jQuery */
import $ from 'jquery'
/**
* @name Show Password
* @description
* @version 1.3.0
* @requires jQuery 1.5
*
* @author Jan Jarfalk <jan.jarfalk@unwrongest.com>
* author-website http://www.unwrongest.com
*
* special-thanks Michel Gratton
*
* @license MIT
*/
$.fn.extend({
showPassword(c) {
// Setup callback object
const callback = { fn: null, args: {} }
callback.fn = c
// Clones passwords and turn the clones into text inputs
const cloneElement = function(element) {
const $element = $(element)
const $clone = $('<input />')
// Name added for JQuery Validation compatibility
// Element name is required to avoid script warning.
$clone.attr({
type: 'text',
class: $element.attr('class'),
style: $element.attr('style'),
size: $element.attr('size'),
name: $element.attr('name') + '-clone',
tabindex: $element.attr('tabindex'),
autocomplete: 'off',
})
if ($element.attr('placeholder') !== undefined) {
$clone.attr('placeholder', $element.attr('placeholder'))
}
return $clone
}
// Transfers values between two elements
const update = function(a, b) {
b.val(a.val())
}
// Shows a or b depending on checkbox
const setState = function(checkbox, a, b) {
if (checkbox.is(':checked')) {
update(a, b)
b.show()
a.hide()
} else {
update(b, a)
b.hide()
a.show()
}
}
return this.each(function() {
const $input = $(this)
const $checkbox = $($input.data('typetoggle'))
// Create clone
const $clone = cloneElement($input)
$clone.insertAfter($input)
// Set callback arguments
if (callback.fn) {
callback.args.input = $input
callback.args.checkbox = $checkbox
callback.args.clone = $clone
}
$checkbox.bind('click', function() {
setState($checkbox, $input, $clone)
})
$input.bind('keyup', function() {
update($input, $clone)
})
$clone.bind('keyup', function() {
update($clone, $input)
// Added for JQuery Validation compatibility
// This will trigger validation if it's ON for keyup event
$input.trigger('keyup')
})
// Added for JQuery Validation compatibility
// This will trigger validation if it's ON for blur event
$clone.bind('blur', function() {
$input.trigger('focusout')
})
setState($checkbox, $input, $clone)
// set type of password field clone (type=text) to password right on submit
// to prevent browser save the value of this field
$clone.closest('form').submit(function() {
// .prop has to be used, because .attr throws
// an error while changing a type of an input
// element
$clone.prop('type', 'password')
})
if (callback.fn) {
callback.fn(callback.args)
}
})
},
})

View file

@ -1,13 +0,0 @@
/**
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import $ from 'jquery'
// Set autocomplete width the same as the related input
// See http://stackoverflow.com/a/11845718
$.ui.autocomplete.prototype._resizeMenu = function() {
const ul = this.menu.element
ul.outerWidth(this.element.outerWidth())
}

View file

@ -13,7 +13,6 @@ import OC from './OC/index.js'
import 'core-js/stable/index.js'
import 'regenerator-runtime/runtime.js'
import './globals.js'
import './jquery/index.js'
__webpack_nonce__ = getCSPNonce()

150
core/vendor/.gitignore vendored
View file

@ -1,150 +0,0 @@
# SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-FileCopyrightText: 2014-2016 ownCloud, Inc.
# SPDX-License-Identifier: AGPL-3.0-only
test/
src/
bower.json
component.json
.jshintrc
CHANGELOG*
Gemfile
gruntfile.js
Gruntfile.js
Gulpfile.js
Makefile
package.json
README*
# underscore
underscore/**
!underscore/.bower.json
!underscore/underscore-min.js
!underscore/LICENSE
# blueimp-md5
blueimp-md5/css
blueimp-md5/js/*
!blueimp-md5/js/md5.min.js
blueimp-md5/index.html
# momentjs - ignore all files except the two listed below
moment/**
!moment/.bower.json
!moment/min
!moment/LICENSE
moment/min/**
!moment/min/moment-with-locales.min.js
# jquery
jquery/**
!jquery/.bower.json
!jquery/dist
!jquery/dist/jquery.*
!jquery/MIT-LICENSE.txt
# jquery-ui
jquery-ui/**
!jquery-ui/themes/base/jquery-ui.css
!jquery-ui/jquery-ui.min.js
!jquery-ui/.bower.json
# jcrop
jcrop/index.html
jcrop/demos
jcrop/css/jquery.Jcrop.min.css
jcrop/js/**
!jcrop/js/jquery.Jcrop.js
# handlebars
handlebars/**
!handlebars/.bower.json
!handlebars/handlebars.runtime.min.js
# select2
select2/**
!select2/.bower.json
!select2/select2.js
!select2/select2.css
!select2/select2.png
!select2/select2x2.png
!select2/select2-spinner.gif
!select2/LICENSE
#zxcvbn
zxcvbn/**
!zxcvbn/.bower.json
!zxcvbn/dist
zxcvbn/dist/**
!zxcvbn/dist/zxcvbn.js
!zxcvbn/LICENSE.txt
# snapjs
snapjs/demo
snapjs/dist/2.0.0-rc1
snapjs/dist/latest/snap.css
snapjs/dist/latest/snap.min.js
snapjs/scripts
# bootstrap - only include the tooltip plugin
bootstrap/**
!bootstrap/.bower.json
!bootstrap/js
bootstrap/js/*
!bootstrap/js/tooltip.js
# backbone
backbone/backbone-min*
# davclient.js
davclient.js/**
!davclient.js/.bower.json
!davclient.js/lib
!davclient.js/lib/client.js
!davclient.js/LICENSE
# es6-shim
es6-shim/**
!es6-shim/.bower.json
!es6-shim/LICENSE
!es6-shim/es6-shim.min.js
# base64
base64/*min.js
# clipboard
clipboard/**
!clipboard/.bower.json
!clipboard/dist
!clipboard/dist/clipboard.min.js
# autosize
autosize/**
!autosize/dist
!autosize/dist/autosize.min.js
!autosize/.bower.json
!autosize/LICENCE.md
#marked
marked/bin
marked/doc
marked/index.js
marked/lib
marked/man
# DOMPurity
DOMPurify/**
!DOMPurify/dist
!DOMPurify/dist/purify.min.js
!DOMPurify/.bower.json
!DOMPurify/LICENSE
# strengthify
strengthify/examples.html
strengthify/examples.png
# underscore
css-vars-ponyfill/**
!css-vars-ponyfill/dist
!css-vars-ponyfill/dist/css-vars-ponyfill.min.js
!css-vars-ponyfill/dist/css-vars-ponyfill.min.js.map
!css-vars-ponyfill/LICENSE

View file

@ -1,20 +0,0 @@
Copyright (c) 2012-2016 Dan Wheeler and Dropbox, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

File diff suppressed because one or more lines are too long