Move jQuery plugins into modules and add them to the bundle
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
This commit is contained in:
parent
2682d672d8
commit
3ced9cd83d
26 changed files with 1246 additions and 1031 deletions
|
@ -1,12 +1,7 @@
|
|||
{
|
||||
"libraries": [
|
||||
"jquery-showpassword.js",
|
||||
"jquery.avatar.js",
|
||||
"jquery.contactsmenu.js",
|
||||
"placeholder.js"
|
||||
],
|
||||
"modules": [
|
||||
"jquery.ocdialog.js",
|
||||
"oc-dialogs.js",
|
||||
"js.js",
|
||||
"share.js",
|
||||
|
@ -18,7 +13,6 @@
|
|||
"sharedialoglinkshareview.js",
|
||||
"sharedialogresharerinfoview.js",
|
||||
"sharedialogshareelistview.js",
|
||||
"octemplate.js",
|
||||
"contactsmenu_templates.js",
|
||||
"public/appconfig.js",
|
||||
"public/comments.js",
|
||||
|
|
BIN
core/js/dist/main.js
vendored
BIN
core/js/dist/main.js
vendored
Binary file not shown.
BIN
core/js/dist/main.js.map
vendored
BIN
core/js/dist/main.js.map
vendored
Binary file not shown.
127
core/js/jquery-showpassword.js
vendored
127
core/js/jquery-showpassword.js
vendored
|
@ -1,127 +0,0 @@
|
|||
/*
|
||||
* @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
|
||||
*/
|
||||
(function($){
|
||||
$.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 );
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
|
@ -1,146 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2013 Christopher Schäpers <christopher@schaepers.it>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
$.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 = '';
|
||||
};
|
||||
}(jQuery));
|
|
@ -1,110 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2017 Georg Ehrke <oc.list@georgehrke.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
|
||||
var 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();
|
||||
});
|
||||
};
|
||||
}(jQuery));
|
|
@ -1,249 +0,0 @@
|
|||
(function($) {
|
||||
$.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();
|
||||
}
|
||||
});
|
||||
}(jQuery));
|
106
core/js/js.js
106
core/js/js.js
|
@ -29,15 +29,6 @@ if (typeof console === "undefined" || typeof console.log === "undefined") {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes a HTML string by replacing all potential dangerous characters with HTML entities
|
||||
* @param {string} s String to sanitize
|
||||
* @return {string} Sanitized string
|
||||
*/
|
||||
function escapeHTML(s) {
|
||||
return s.toString().split('&').join('&').split('<').join('<').split('>').join('>').split('"').join('"').split('\'').join(''');
|
||||
}
|
||||
|
||||
/** @namespace OCP */
|
||||
var OCP = Object.assign({}, window.OCP);
|
||||
|
||||
|
@ -1832,13 +1823,6 @@ OC.PasswordConfirmation = {
|
|||
|
||||
$(document).ready(initCore);
|
||||
|
||||
/**
|
||||
* Filter Jquery selector by attribute value
|
||||
*/
|
||||
$.fn.filterAttr = function(attr_name, attr_value) {
|
||||
return this.filter(function() { return $(this).attr(attr_name) === attr_value; });
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a human readable file size
|
||||
* @param {number} size Size in bytes
|
||||
|
@ -2338,93 +2322,3 @@ OC.set=function(name, value) {
|
|||
document.getElementsByTagName("head")[0].appendChild(msViewportStyle);
|
||||
}
|
||||
})();
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
jQuery.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();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
jQuery.fn.exists = function(){
|
||||
return this.length > 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* jQuery tipsy shim for the bootstrap tooltip
|
||||
*/
|
||||
jQuery.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
|
||||
jQuery.fn.tooltip.call(this, 'destroy');
|
||||
jQuery.fn.tooltip.call(this, options);
|
||||
} else {
|
||||
this.tooltip(argument);
|
||||
jQuery.fn.tooltip.call(this, argument);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
[
|
||||
"jquery.ocdialog.js",
|
||||
"oc-dialogs.js",
|
||||
"js.js",
|
||||
"octemplate.js",
|
||||
"public/appconfig.js",
|
||||
"public/comments.js",
|
||||
"public/whatsnew.js",
|
||||
"oc-requesttoken.js",
|
||||
"mimetype.js",
|
||||
"mimetypelist.js",
|
||||
"select2-toggleselect.js",
|
||||
"placeholder.js",
|
||||
"jquery.avatar.js",
|
||||
"jquery.contactsmenu.js"
|
||||
"select2-toggleselect.js"
|
||||
]
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
/**
|
||||
* 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(),
|
||||
* });
|
||||
* );
|
||||
* });
|
||||
*/
|
||||
(function( $ ) {
|
||||
/**
|
||||
* Object Template
|
||||
* Inspired by micro templating done by e.g. underscore.js
|
||||
*/
|
||||
var 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);
|
||||
}
|
||||
};
|
||||
|
||||
})( jQuery );
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 ($) {
|
||||
|
||||
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');
|
||||
};
|
||||
}(jQuery));
|
36
core/src/Util/escapeHTML.js
Normal file
36
core/src/Util/escapeHTML.js
Normal file
|
@ -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('&')
|
||||
.split('<')
|
||||
.join('<').split('>')
|
||||
.join('>').split('"')
|
||||
.join('"').split('\'')
|
||||
.join(''');
|
||||
}
|
|
@ -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
|
||||
|
|
162
core/src/jquery/avatar.js
vendored
Normal file
162
core/src/jquery/avatar.js
vendored
Normal file
|
@ -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 = '';
|
||||
};
|
125
core/src/jquery/contactsmenu.js
vendored
Normal file
125
core/src/jquery/contactsmenu.js
vendored
Normal file
|
@ -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();
|
||||
});
|
||||
};
|
31
core/src/jquery/exists.js
vendored
Normal file
31
core/src/jquery/exists.js
vendored
Normal file
|
@ -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;
|
||||
};
|
31
core/src/jquery/filterattr.js
vendored
Normal file
31
core/src/jquery/filterattr.js
vendored
Normal file
|
@ -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;
|
||||
});
|
||||
};
|
32
core/src/jquery/index.js
vendored
Normal file
32
core/src/jquery/index.js
vendored
Normal file
|
@ -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'
|
270
core/src/jquery/ocdialog.js
vendored
Normal file
270
core/src/jquery/ocdialog.js
vendored
Normal file
|
@ -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();
|
||||
}
|
||||
});
|
104
core/src/jquery/octemplate.js
vendored
Normal file
104
core/src/jquery/octemplate.js
vendored
Normal file
|
@ -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);
|
||||
}
|
||||
};
|
174
core/src/jquery/placeholder.js
vendored
Normal file
174
core/src/jquery/placeholder.js
vendored
Normal file
|
@ -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');
|
||||
};
|
43
core/src/jquery/selectrange.js
vendored
Normal file
43
core/src/jquery/selectrange.js
vendored
Normal file
|
@ -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();
|
||||
}
|
||||
});
|
||||
};
|
149
core/src/jquery/showpassword.js
vendored
Normal file
149
core/src/jquery/showpassword.js
vendored
Normal file
|
@ -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);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
});
|
83
core/src/jquery/tipsy.js
vendored
Normal file
83
core/src/jquery/tipsy.js
vendored
Normal file
|
@ -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;
|
||||
};
|
|
@ -1,8 +1,8 @@
|
|||
// Various jquery fixes
|
||||
import $ from 'jquery'
|
||||
|
||||
// Set autocomplete width the same as the related input
|
||||
// See http://stackoverflow.com/a/11845718
|
||||
jQuery.ui.autocomplete.prototype._resizeMenu = function () {
|
||||
$.ui.autocomplete.prototype._resizeMenu = function () {
|
||||
var ul = this.menu.element;
|
||||
ul.outerWidth(this.element.outerWidth());
|
||||
};
|
|
@ -23,6 +23,7 @@ import '@babel/polyfill'
|
|||
|
||||
import './globals'
|
||||
import $ from 'jquery'
|
||||
import './jquery/index'
|
||||
import {registerAppsSlideToggle} from './OC/apps'
|
||||
|
||||
$(document).ready(function () {
|
||||
|
|
Loading…
Reference in a new issue