aboutsummaryrefslogtreecommitdiffstats
path: root/core/src
diff options
context:
space:
mode:
authorChristoph Wurst <christoph@winzerhof-wurst.at>2019-01-29 10:15:46 +0100
committerChristoph Wurst <christoph@winzerhof-wurst.at>2019-01-29 11:07:48 +0100
commit3ced9cd83db38731a1e82dafc0dcbdfe7db6cc2b (patch)
tree3da933724684a709f6afa2a8cbaa1fae10baa575 /core/src
parent2682d672d8076302da61fef3cc15e4d647d50be5 (diff)
downloadnextcloud-server-3ced9cd83db38731a1e82dafc0dcbdfe7db6cc2b.tar.gz
nextcloud-server-3ced9cd83db38731a1e82dafc0dcbdfe7db6cc2b.zip
Move jQuery plugins into modules and add them to the bundle
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
Diffstat (limited to 'core/src')
-rw-r--r--core/src/Util/escapeHTML.js36
-rw-r--r--core/src/globals.js2
-rw-r--r--core/src/jquery/avatar.js162
-rw-r--r--core/src/jquery/contactsmenu.js125
-rw-r--r--core/src/jquery/exists.js31
-rw-r--r--core/src/jquery/filterattr.js31
-rw-r--r--core/src/jquery/index.js32
-rw-r--r--core/src/jquery/ocdialog.js270
-rw-r--r--core/src/jquery/octemplate.js104
-rw-r--r--core/src/jquery/placeholder.js174
-rw-r--r--core/src/jquery/selectrange.js43
-rw-r--r--core/src/jquery/showpassword.js149
-rw-r--r--core/src/jquery/tipsy.js83
-rw-r--r--core/src/jquery/ui-fixes.js8
-rw-r--r--core/src/main.js1
15 files changed, 1251 insertions, 0 deletions
diff --git a/core/src/Util/escapeHTML.js b/core/src/Util/escapeHTML.js
new file mode 100644
index 00000000000..f6cf868a6d0
--- /dev/null
+++ b/core/src/Util/escapeHTML.js
@@ -0,0 +1,36 @@
+/*
+ * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program 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, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 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/>.
+ */
+
+/**
+ * Sanitizes a HTML string by replacing all potential dangerous characters with HTML entities
+ * @param {string} s String to sanitize
+ * @return {string} Sanitized string
+ */
+export default function escapeHTML (s) {
+ return s.toString()
+ .split('&')
+ .join('&amp;')
+ .split('<')
+ .join('&lt;').split('>')
+ .join('&gt;').split('"')
+ .join('&quot;').split('\'')
+ .join('&#039;');
+}
diff --git a/core/src/globals.js b/core/src/globals.js
index 5d077f22486..ad1997c470d 100644
--- a/core/src/globals.js
+++ b/core/src/globals.js
@@ -51,6 +51,7 @@ import 'strengthify/strengthify.css'
import OC from './OC/index'
import OCP from './OCP/index'
import OCA from './OCA/index'
+import escapeHTML from './Util/escapeHTML'
window['_'] = _
window['$'] = $
@@ -72,6 +73,7 @@ window['moment'] = moment
window['OC'] = OC
window['OCP'] = OCP
window['OCA'] = OCA
+window['escapeHTML'] = escapeHTML
/**
* translate a string
diff --git a/core/src/jquery/avatar.js b/core/src/jquery/avatar.js
new file mode 100644
index 00000000000..75aef6d958f
--- /dev/null
+++ b/core/src/jquery/avatar.js
@@ -0,0 +1,162 @@
+/*
+ * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program 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, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 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/>.
+ */
+
+import $ from 'jquery'
+
+import OC from '../OC'
+
+/**
+ * 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) {
+ var 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, '');
+
+ var $div = this;
+ var url;
+
+ // If this is our own avatar we have to use the version attribute
+ if (user === OC.getCurrentUser().uid) {
+ url = OC.generateUrl(
+ '/avatar/{user}/{size}?v={version}',
+ {
+ user: user,
+ size: Math.ceil(size * window.devicePixelRatio),
+ version: oc_userconfig.avatar.version
+ });
+ } else {
+ url = OC.generateUrl(
+ '/avatar/{user}/{size}',
+ {
+ user: user,
+ size: Math.ceil(size * window.devicePixelRatio)
+ });
+ }
+
+ var 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 = '';
+};
diff --git a/core/src/jquery/contactsmenu.js b/core/src/jquery/contactsmenu.js
new file mode 100644
index 00000000000..8ee97dd51e9
--- /dev/null
+++ b/core/src/jquery/contactsmenu.js
@@ -0,0 +1,125 @@
+/*
+ * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program 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, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 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/>.
+ */
+
+import $ from 'jquery'
+
+import OC from '../OC'
+
+const LIST = ''
+ + '<div class="menu popovermenu menu-left hidden contactsmenu-popover">'
+ + ' <ul>'
+ + ' <li>'
+ + ' <a>'
+ + ' <span class="icon-loading-small"></span>'
+ + ' </a>'
+ + ' </li>'
+ + ' </ul>'
+ + '</div>';
+
+$.fn.contactsMenu = function (shareWith, shareType, appendTo) {
+ // 0 - user, 4 - email, 6 - remote
+ var allowedTypes = [0, 4, 6];
+ if (allowedTypes.indexOf(shareType) === -1) {
+ return;
+ }
+
+ var $div = this;
+ appendTo.append(LIST);
+ var $list = appendTo.find('div.contactsmenu-popover');
+
+ $div.click(function () {
+ if (!$list.hasClass('hidden')) {
+ $list.addClass('hidden');
+ $list.hide();
+ return;
+ }
+
+ $list.removeClass('hidden');
+ $list.show();
+
+ if ($list.hasClass('loaded')) {
+ return;
+ }
+
+ $list.addClass('loaded');
+ $.ajax(OC.generateUrl('/contactsmenu/findOne'), {
+ method: 'POST',
+ data: {
+ shareType: shareType,
+ shareWith: shareWith
+ }
+ }).then(function (data) {
+ $list.find('ul').find('li').addClass('hidden');
+
+ var actions;
+ if (!data.topAction) {
+ actions = [{
+ hyperlink: '#',
+ title: t('core', 'No action available')
+ }];
+ } else {
+ actions = [data.topAction].concat(data.actions);
+ }
+
+ actions.forEach(function (action) {
+ var template = OC.ContactsMenu.Templates['jquery_entry'];
+ $list.find('ul').append(template(action));
+ });
+
+ if (actions.length === 0) {
+
+ }
+ }, function (jqXHR) {
+ $list.find('ul').find('li').addClass('hidden');
+
+ var title;
+ if (jqXHR.status === 404) {
+ title = t('core', 'No action available');
+ } else {
+ title = t('core', 'Error fetching contact actions');
+ }
+
+ var template = OC.ContactsMenu.Templates['jquery_entry'];
+ $list.find('ul').append(template({
+ hyperlink: '#',
+ title: title
+ }));
+ });
+ });
+
+ $(document).click(function (event) {
+ var clickedList = ($list.has(event.target).length > 0);
+ var clickedTarget = ($div.has(event.target).length > 0);
+
+ $div.each(function () {
+ if ($(this).is(event.target)) {
+ clickedTarget = true;
+ }
+ });
+
+ if (clickedList || clickedTarget) {
+ return;
+ }
+
+ $list.addClass('hidden');
+ $list.hide();
+ });
+};
diff --git a/core/src/jquery/exists.js b/core/src/jquery/exists.js
new file mode 100644
index 00000000000..bdf62ab7d4b
--- /dev/null
+++ b/core/src/jquery/exists.js
@@ -0,0 +1,31 @@
+/*
+ * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program 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, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 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/>.
+ */
+
+import $ from 'jquery'
+
+/**
+ * check if an element exists.
+ * allows you to write if ($('#myid').exists()) to increase readability
+ * @link http://stackoverflow.com/questions/31044/is-there-an-exists-function-for-jquery
+ */
+$.fn.exists = function () {
+ return this.length > 0;
+};
diff --git a/core/src/jquery/filterattr.js b/core/src/jquery/filterattr.js
new file mode 100644
index 00000000000..7675eaa1e2d
--- /dev/null
+++ b/core/src/jquery/filterattr.js
@@ -0,0 +1,31 @@
+/*
+ * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program 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, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 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/>.
+ */
+
+import $ from 'jquery'
+
+/**
+ * Filter jQuery selector by attribute value
+ */
+$.fn.filterAttr = function (attrName, attrValue) {
+ return this.filter(function () {
+ return $(this).attr(attrName) === attrValue;
+ });
+};
diff --git a/core/src/jquery/index.js b/core/src/jquery/index.js
new file mode 100644
index 00000000000..8e2feb2b65e
--- /dev/null
+++ b/core/src/jquery/index.js
@@ -0,0 +1,32 @@
+/*
+ * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program 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, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 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/>.
+ */
+
+import './avatar'
+import './contactsmenu'
+import './exists'
+import './filterattr'
+import './ocdialog'
+import './octemplate'
+import './placeholder'
+import './selectrange'
+import './showpassword'
+import './tipsy'
+import './ui-fixes'
diff --git a/core/src/jquery/ocdialog.js b/core/src/jquery/ocdialog.js
new file mode 100644
index 00000000000..8899d9433d1
--- /dev/null
+++ b/core/src/jquery/ocdialog.js
@@ -0,0 +1,270 @@
+/*
+ * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program 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, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 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/>.
+ */
+
+import $ from 'jquery'
+
+$.widget('oc.ocdialog', {
+ options: {
+ width: 'auto',
+ height: 'auto',
+ closeButton: true,
+ closeOnEscape: true,
+ modal: false
+ },
+ _create: function () {
+ var 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" />')
+ .attr({
+ // Setting tabIndex makes the div focusable
+ tabIndex: -1,
+ role: 'dialog'
+ })
+ .insertBefore(this.element);
+ this.$dialog.append(this.element.detach());
+ this.element.removeAttr('title').addClass('oc-dialog-content').appendTo(this.$dialog);
+
+ 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;
+ }
+ // If no button is selected we trigger the primary
+ if (
+ self.$buttonrow &&
+ self.$buttonrow.find($(event.target)).length === 0
+ ) {
+ var $button = self.$buttonrow.find('button.primary');
+ if ($button && !$button.prop('disabled')) {
+ $button.trigger('click');
+ }
+ } else if (self.$buttonrow) {
+ $(event.target).trigger('click');
+ }
+ return false;
+ }
+ });
+
+ this._setOptions(this.options);
+ this._createOverlay();
+ },
+ _init: function () {
+ this.$dialog.focus();
+ this._trigger('open');
+ },
+ _setOption: function (key, value) {
+ var self = this;
+ switch (key) {
+ case 'title':
+ if (this.$title) {
+ this.$title.text(value);
+ } else {
+ var $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 {
+ var $buttonrow = $('<div class="oc-dialog-buttonrow" />');
+ 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) {
+ var $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.click(function () {
+ val.click.apply(self.element[0], arguments);
+ });
+ });
+ this.$buttonrow.find('button')
+ .on('focus', function (event) {
+ 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) {
+ var $closeButton = $('<a class="oc-dialog-close"></a>');
+ this.$dialog.prepend($closeButton);
+ $closeButton.on('click', function () {
+ 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: function (options) {
+ //this._super(options);
+ $.Widget.prototype._setOptions.apply(this, arguments);
+ },
+ _setSizes: function () {
+ var 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: function () {
+ if (!this.options.modal) {
+ return;
+ }
+
+ var self = this;
+ this.overlay = $('<div>')
+ .addClass('oc-dialog-dim')
+ .appendTo($('#content'));
+ 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();
+ return;
+ }
+ });
+ },
+ _destroyOverlay: function () {
+ if (!this.options.modal) {
+ return;
+ }
+
+ if (this.overlay) {
+ this.overlay.off('click keydown keyup');
+ this.overlay.remove();
+ this.overlay = null;
+ }
+ },
+ widget: function () {
+ return this.$dialog;
+ },
+ setEnterCallback: function (callback) {
+ this.enterCallback = callback;
+ },
+ unsetEnterCallback: function () {
+ this.enterCallback = null;
+ },
+ close: function () {
+ this._destroyOverlay();
+ var self = this;
+ // Ugly hack to catch remaining keyup events.
+ setTimeout(function () {
+ self._trigger('close', self);
+ }, 200);
+
+ self.$dialog.remove();
+ this.destroy();
+ },
+ destroy: function () {
+ 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();
+ }
+});
diff --git a/core/src/jquery/octemplate.js b/core/src/jquery/octemplate.js
new file mode 100644
index 00000000000..61fbea2af5f
--- /dev/null
+++ b/core/src/jquery/octemplate.js
@@ -0,0 +1,104 @@
+import $ from 'jquery'
+import escapeHTML from '../Util/escapeHTML'
+
+/**
+ * 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: function (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;
+ var self = this;
+
+ if (typeof this.options.escapeFunction === 'function') {
+ var keys = Object.keys(this.vars);
+ for (var key = 0; key < keys.length; key++) {
+ if (typeof this.vars[keys[key]] === 'string') {
+ this.vars[keys[key]] = self.options.escapeFunction(this.vars[keys[key]]);
+ }
+ }
+ }
+
+ var _html = this._build(this.vars);
+ return $(_html);
+ },
+ // From stackoverflow.com/questions/1408289/best-way-to-do-variable-interpolation-in-javascript
+ _build: function (o) {
+ var data = this.elem.attr('type') === 'text/template' ? this.elem.html() : this.elem.get(0).outerHTML;
+ try {
+ return data.replace(/{([^{}]*)}/g,
+ function (a, b) {
+ var r = o[b];
+ return typeof r === 'string' || typeof r === 'number' ? r : a;
+ }
+ );
+ } catch (e) {
+ console.error(e, 'data:', data);
+ }
+ },
+ options: {
+ escapeFunction: escapeHTML
+ }
+};
+
+$.fn.octemplate = function (vars, options) {
+ vars = vars || {};
+ if (this.length) {
+ var _template = Object.create(Template);
+ return _template.init(vars, options, this);
+ }
+};
diff --git a/core/src/jquery/placeholder.js b/core/src/jquery/placeholder.js
new file mode 100644
index 00000000000..074ad5029b5
--- /dev/null
+++ b/core/src/jquery/placeholder.js
@@ -0,0 +1,174 @@
+/**
+ * ownCloud
+ *
+ * @author John Molakvoæ
+ * @copyright 2016-2018 John Molakvoæ <skjnldsv@protonmail.com>
+ * @author Morris Jobke
+ * @copyright 2013 Morris Jobke <morris.jobke@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+import $ from 'jquery'
+
+/*
+ * 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}
+*
+*/
+
+String.prototype.toRgb = function () {
+ // Normalize hash
+ var hash = this.toLowerCase();
+
+ // Already a md5 hash?
+ if (hash.match(/^([0-9a-f]{4}-?){8}$/) === null) {
+ hash = md5(hash);
+ }
+
+ 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) {
+ var 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) {
+ var count = steps + 1;
+ var palette = new Array();
+ palette.push(color1);
+ var step = stepCalc(steps, [color1, color2])
+ for (var i = 1; i < steps; i++) {
+ var r = parseInt(color1.r + (step[0] * i));
+ var g = parseInt(color1.g + (step[1] * i));
+ var b = parseInt(color1.b + (step[2] * i));
+ palette.push(new Color(r, g, b));
+ }
+ return palette;
+ }
+
+ var red = new Color(182, 70, 157);
+ var yellow = new Color(221, 203, 85);
+ var 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
+ var steps = 6;
+
+ var palette1 = mixPalette(steps, red, yellow);
+ var palette2 = mixPalette(steps, yellow, blue);
+ var palette3 = mixPalette(steps, blue, red);
+
+ var finalPalette = palette1.concat(palette2).concat(palette3);
+
+ // Convert a string to an integer evenly
+ function hashToInt (hash, maximum) {
+ var finalInt = 0;
+ var result = Array();
+
+ // Splitting evenly the string
+ for (var 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 (var 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)];
+};
+
+$.fn.imageplaceholder = function (seed, text, size) {
+ text = text || seed;
+
+ // Compute the hash
+ var rgb = seed.toRgb();
+ this.css('background-color', 'rgb(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ')');
+
+ // Placeholders are square
+ var 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) {
+ this.html(text[0].toUpperCase());
+ }
+};
+
+$.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');
+};
diff --git a/core/src/jquery/selectrange.js b/core/src/jquery/selectrange.js
new file mode 100644
index 00000000000..b7e20361805
--- /dev/null
+++ b/core/src/jquery/selectrange.js
@@ -0,0 +1,43 @@
+/*
+ * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program 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, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 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/>.
+ */
+
+import $ from 'jquery'
+
+/**
+ * select a range in an input field
+ * @link http://stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area
+ * @param {type} start
+ * @param {type} end
+ */
+$.fn.selectRange = function (start, end) {
+ return this.each(function () {
+ if (this.setSelectionRange) {
+ this.focus();
+ this.setSelectionRange(start, end);
+ } else if (this.createTextRange) {
+ var range = this.createTextRange();
+ range.collapse(true);
+ range.moveEnd('character', end);
+ range.moveStart('character', start);
+ range.select();
+ }
+ });
+};
diff --git a/core/src/jquery/showpassword.js b/core/src/jquery/showpassword.js
new file mode 100644
index 00000000000..4dc39340e76
--- /dev/null
+++ b/core/src/jquery/showpassword.js
@@ -0,0 +1,149 @@
+/*
+ * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program 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, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 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/>.
+ */
+
+import $ from 'jquery'
+
+/*
+* @name Show Password
+* @description
+* @version 1.3
+* @requires Jquery 1.5
+*
+* @author Jan Jarfalk
+* @author-email jan.jarfalk@unwrongest.com
+* @author-website http://www.unwrongest.com
+*
+* @special-thanks Michel Gratton
+*
+* @licens MIT License - http://www.opensource.org/licenses/mit-license.php
+*/
+$.fn.extend({
+ showPassword: function (c) {
+
+ // Setup callback object
+ var callback = {'fn': null, 'args': {}};
+ callback.fn = c;
+
+ // Clones passwords and turn the clones into text inputs
+ var cloneElement = function (element) {
+
+ var $element = $(element);
+
+ var $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
+ var update = function (a, b) {
+ b.val(a.val());
+ };
+
+ // Shows a or b depending on checkbox
+ var 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 () {
+
+ var $input = $(this),
+ $checkbox = $($input.data('typetoggle'));
+
+ // Create clone
+ var $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 (e) {
+ // .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);
+ }
+
+ });
+ }
+});
diff --git a/core/src/jquery/tipsy.js b/core/src/jquery/tipsy.js
new file mode 100644
index 00000000000..816a93fb9a9
--- /dev/null
+++ b/core/src/jquery/tipsy.js
@@ -0,0 +1,83 @@
+/*
+ * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program 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, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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 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/>.
+ */
+
+import $ from 'jquery'
+
+/**
+ * $ tipsy shim for the bootstrap tooltip
+ * @deprecated
+ */
+$.fn.tipsy = function (argument) {
+ console.warn('Deprecation warning: tipsy is deprecated. Use tooltip instead.');
+ if (typeof argument === 'object' && argument !== null) {
+
+ // tipsy defaults
+ var options = {
+ placement: 'bottom',
+ delay: {'show': 0, 'hide': 0},
+ trigger: 'hover',
+ html: false,
+ container: 'body'
+ };
+ if (argument.gravity) {
+ switch (argument.gravity) {
+ case 'n':
+ case 'nw':
+ case 'ne':
+ options.placement = 'bottom';
+ break;
+ case 's':
+ case 'sw':
+ case 'se':
+ options.placement = 'top';
+ break;
+ case 'w':
+ options.placement = 'right';
+ break;
+ case 'e':
+ options.placement = 'left';
+ break;
+ }
+ }
+ if (argument.trigger) {
+ options.trigger = argument.trigger;
+ }
+ if (argument.delayIn) {
+ options.delay.show = argument.delayIn;
+ }
+ if (argument.delayOut) {
+ options.delay.hide = argument.delayOut;
+ }
+ if (argument.html) {
+ options.html = true;
+ }
+ if (argument.fallback) {
+ options.title = argument.fallback;
+ }
+ // destroy old tooltip in case the title has changed
+ $.fn.tooltip.call(this, 'destroy');
+ $.fn.tooltip.call(this, options);
+ } else {
+ this.tooltip(argument);
+ $.fn.tooltip.call(this, argument);
+ }
+ return this;
+}; \ No newline at end of file
diff --git a/core/src/jquery/ui-fixes.js b/core/src/jquery/ui-fixes.js
new file mode 100644
index 00000000000..d3cebfc346e
--- /dev/null
+++ b/core/src/jquery/ui-fixes.js
@@ -0,0 +1,8 @@
+import $ from 'jquery'
+
+// Set autocomplete width the same as the related input
+// See http://stackoverflow.com/a/11845718
+$.ui.autocomplete.prototype._resizeMenu = function () {
+ var ul = this.menu.element;
+ ul.outerWidth(this.element.outerWidth());
+};
diff --git a/core/src/main.js b/core/src/main.js
index 85e8200f10c..baded7067b4 100644
--- a/core/src/main.js
+++ b/core/src/main.js
@@ -23,6 +23,7 @@ import '@babel/polyfill'
import './globals'
import $ from 'jquery'
+import './jquery/index'
import {registerAppsSlideToggle} from './OC/apps'
$(document).ready(function () {