Removed legacy flatelements.

This commit is contained in:
buddh4 2017-01-09 10:01:58 +01:00
parent b096ff6ecc
commit 218bf7dbfa
7 changed files with 120 additions and 636 deletions

View File

@ -155,9 +155,9 @@ humhub.module('ui.additions', function(module, require, $) {
});*/
// Replace the standard checkbox and radio buttons
module.register('forms', ':checkbox, :radio', function($match) {
$match.flatelements();
});
/* module.register('forms', ':checkbox, :radio', function($match) {
//$match.flatelements();
});*/
// Deprecated!
module.register('', 'a[data-loader="modal"], button[data-loader="modal"]', function($match) {

View File

@ -0,0 +1,102 @@
humhub.module('ui.form.elements', function (module, require, $) {
var additions = require('ui.additions');
var init = function () {
additions.register('form_elements', ':checkbox, :radio', function ($match) {
$match.each(function () {
var $this = $(this);
if ($this.is(':checkbox')) {
module.initCheckbox($this);
} else if($this.is(':radio')) {
module.initRadio($this);
}
});
});
};
var initCheckbox = function ($input) {
if ($input.data('form_element')) {
return;
}
// Check if the standard bootstrap container <div> exists
if ($input.parent().parent().attr('class') === "checkbox") {
$input.parent().parent().addClass('regular-checkbox-container')
.append('<div class="regular-checkbox-clear"></div>');
}
_checkInputLabel($input);
// Create new checkbox
var $checkbox = $('<div class="regular-checkbox-box"></div>').attr('style', $input.attr('style'));
if ($input.is(':disabled')) {
$checkbox.addClass('disabled');
}
// add new checkbox element
$input.parent().append($checkbox);
// add new class to checkbox
$input.addClass('regular-checkbox').data('form_element', $checkbox);
};
var initRadio = function ($input) {
if ($input.data('form_element')) {
return;
}
// Check if the standard bootstrap container <div> exists
if ($input.parent().parent().attr('class') === "radio") {
$input.parent().parent().addClass('regular-radio-container');
}
_checkInputLabel($input);
// Create new checkbox
var $radio = $('<div class="regular-radio-button"></div>');
if ($input.is(':disabled')) {
$radio.addClass('disabled');
}
// add new radio element
$input.parent().append($radio);
// add new class to checkbox
$input.addClass('regular-radio').data('form_element', $radio);
};
/**
* Checks the label style of $input.
* If the $input is not wrapped in a label we wrap it around a new label and use the old label text if given.
*
* @param {type} $input
* @returns {undefined}
*/
var _checkInputLabel = function ($input) {
if (!$input.parent().is('label')) {
var $parent = $input.parent();
var $newLabel = $('<label>');
// check for old label
var $oldLabel = $('label[for="' + $input.attr('id') + '"]');
if ($oldLabel.length) {
$newLabel.html($oldLabel.html());
$oldLabel.remove();
}
$parent.append($newLabel.append($input));
}
};
module.export({
init: init,
initCheckbox: initCheckbox,
initRadio: initRadio
});
});

View File

@ -1,438 +0,0 @@
/**
* Manages the client/server communication. Handles humhub json api responses and
* pjax requests.
*/
humhub.module('ui.richtext', function(module, require, $) {
var Widget = require('ui.widget').Widget;
var util = require('util');
var object = util.object;
var string = util.string;
var Richtext = function(node, options) {
Widget.call(this, node, options);
};
object.inherits(Richtext, Widget);
Richtext.component = 'humhub-ui-richtext';
Richtext.prototype.init = function() {
this.$input = $('#' + this.$.attr('id') + '_input').hide();
this.features = [];
this.checkPlaceholder();
this.initEvents();
if(this.options.disabled) {
this.disable();
}
console.log(module.config['emoji.url']);
};
Richtext.prototype.initEvents = function() {
var that = this;
this.$.on('focus', function() {
that.checkPlaceholder(true);
// Initialize features on first focus.
if(!that.featuresInitialized) {
that.initFeatures();
}
}).on('focusout', function() {
that.update();
that.checkPlaceholder();
}).on('paste', function(event) {
event.preventDefault();
event.stopImmediatePropagation();
var text = "";
if(event.originalEvent.clipboardData) { //Forefox, Webkit
text = event.originalEvent.clipboardData.getData('text/plain');
} else if(window.clipboardData) { // IE
text = window.clipboardData.getData("Text");
}
that.insertTextAtCursor(text);
}).on('keydown', function(e) {
that.checkForEmptySpans();
}).on('keypress', function(e) {
switch(e.which) {
case 13: // Enter
// Insert a space after some delay to not interupt the browsers default new line insertion.
var $context = $(window.getSelection().getRangeAt(0).commonAncestorContainer);
setTimeout(function() {
if($context[0].nodeType === Node.TEXT_NODE) {
$context[0].textContent += '\u00a0';
}
}, 1000);
break;
case 8: // Backspace
// Note chrome won't fire the backspace keypress event, but we don't need the workaround for chrome so its ok..
that.checkLinkRemoval();
break;
}
}).on('clear', function(e) {
that.clear();
}).on('disable', function(e) {
that.disable();
});
};
/**
* This is a workaround for deleting links as a whole in firefox https://bugzilla.mozilla.org/show_bug.cgi?id=685445
*/
Richtext.prototype.checkLinkRemoval = function() {
var position = this.$.caret('offset');
if(!position) {
return;
}
var that = this;
// Check if the caret position is right before a link, if yes remove link and perhaps also the parent if empty.
this.$.find('.richtext-link').each(function() {
var $this = $(this);
var offset = $this.offset();
var right = offset.left + $this.outerWidth(true);
// The caret top position seems a bit out in some cases...
if(Math.abs(position.left - right) < 1 && Math.abs(position.top - offset.top) < 18) {
$this.remove();
// This is a workaround for a caret position issue in firefox https://bugzilla.mozilla.org/show_bug.cgi?id=904846
_checkCaretPositionAfterRemove(that.$);
return false; // leave loop
}
});
};
var _checkCaretPositionAfterRemove = function($node) {
if(!$node.text().length) {
var spaceText = document.createTextNode("\u00a0");
$node.prepend(spaceText);
var sel = window.getSelection();
var range = document.createRange();
range.setStart(spaceText, 0);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
};
/**
* Inserts the given text at the current cursor position.
* This function gets sure not to insert unwanted html by escaping html chars.
*
* @param {type} text
* @returns {undefined}
*/
Richtext.prototype.insertTextAtCursor = function(text) {
// Get rid of unwanted html
var text = $('<div></div>').append(string.escapeHtml(text)).text();
var lastNode;
var sel = window.getSelection();
// Clear current selection, we'll overwrite selected text
var range = sel.getRangeAt(0);
range.deleteContents();
// Remove leading line-breaks and spaces
text = text.replace(/^(?:\r\n|\r|\n)/g, '').trim();
// We insert the lines reversed since we don't have to align the range
var lines = text.split(/(?:\r\n|\r|\n)/g).reverse();
$.each(lines, function(i, line) {
// Prevent break after last line
if(i !== 0) {
var br = document.createElement("br");
range.insertNode(br);
}
// Insert actual text node
var newNode = document.createTextNode(line.trim());
range.insertNode(newNode);
//Insert leading spaces as textnodes
var leadingSpaces = line.match(/^\s+/);
if(leadingSpaces) {
var spaceCount = leadingSpaces[0].length;
while(spaceCount > 0) {
var spaceNode = document.createTextNode("\u00a0");
range.insertNode(spaceNode);
spaceCount--;
}
}
// The last node of the loop is the first node in dom since we insert reversed
if(i === 0) {
lastNode = newNode;
}
});
// Align range after insertion
range.setStartAfter(lastNode);
range.setEndAfter(lastNode);
sel.removeAllRanges();
sel.addRange(range);
};
Richtext.prototype.update = function() {
this.$input.val(this.getPlainText());
};
Richtext.prototype.checkPlaceholder = function(focus) {
if(!focus && !this.$.text().trim().length) {
this.$.addClass('atwho-placeholder');
this.$.html(this.options.placeholder);
this.$.attr('spellcheck', 'false');
} else if(this.$.hasClass('atwho-placeholder')) {
this.$.removeClass('atwho-placeholder');
this.$.attr('spellcheck', 'true');
this.$.html('');
}
};
Richtext.prototype.initFeatures = function() {
var that = this;
$.each(Richtext.features, function(id, feature) {
if(!that.isFeatureEnabled(id)) {
return;
}
if(feature.atwho) {
that.initAtwhoFeature(id, feature);
}
});
// It seems atwho detatches the original element so we have to do a requery
this.$ = $('#' + this.$.attr('id'));
this.featuresInitialized = true;
};
Richtext.prototype.checkForEmptySpans = function($node) {
$node = $node || this.$;
$node.find('span').each(function() {
_checkEmptySpan($(this));
});
};
var _checkEmptySpan = function($node) {
if($node.is('span') && !$node.contents().length) {
var $parent = $node.parent();
$node.remove();
_checkEmptySpan($parent);
}
};
Richtext.prototype.isFeatureEnabled = function(id) {
if(this.options.excludes && this.options.excludes.indexOf(id) >= 0) {
return false;
}
if(this.options.includes && this.options.includes.length && this.options.includes.indexOf(id) < 0) {
return false;
}
return true;
};
Richtext.prototype.initAtwhoFeature = function(id, feature) {
var options = (object.isFunction(feature.atwho))
? feature.atwho.call(this, feature)
: $.extend({}, feature.atwho);
if(object.isFunction(feature.init)) {
feature.init.call(this, feature, options);
}
if(feature.atwho) {
this.$.atwho(options);
}
this.features.push(id);
};
Richtext.prototype.disable = function(tooltip) {
tooltip = tooltip || this.options.disabledText;
this.$.removeAttr('contenteditable').attr({
disabled: 'disabled',
title : tooltip,
}).tooltip({
placement : 'bottom'
});
};
Richtext.prototype.clear = function() {
this.$.html('');
this.checkPlaceholder();
};
Richtext.prototype.getFeatures = function() {
var result = [];
$.each(this.features, function(i, id) {
result.push(Richtext.features[id]);
});
return result;
};
Richtext.prototype.getPlainText = function() {
// GENERATE USER GUIDS
var that = this;
var $clone = this.$.clone();
$.each(this.getFeatures(), function(id, feature) {
if(object.isFunction(feature.parse)) {
feature.parse($clone, that, feature);
}
});
var html = $clone.html();
// replace html space
html = html.replace(/\&nbsp;/g, ' ');
// rebuild tag structure for webkit browsers
html = html.replace(/\<div>\s*<br\s*\\*>\<\/div>/g, '<div></div>');
// replace all div tags with br tags (webkit)
html = html.replace(/\<div>/g, '<br>');
// replace all p tags with br tags (IE)
html = html.replace(/\<p>\<br\s*\\*>\<\/p>/g, '<br>');
html = html.replace(/\<\/p>/g, '<br>');
// remove all line breaks
html = html.replace(/(?:\r\n|\r|\n)/g, "");
// replace all <br> with new line break
$clone.html(html.replace(/\<br\s*\>/g, '\n'));
// return plain text without html tags
return $clone.text().trim();
}
;
Richtext.features = {};
Richtext.features.emoji = {
'emojis': [
"Relaxed", "Yum", "Relieved", "Hearteyes", "Cool", "Smirk",
"KissingClosedEyes", "StuckOutTongue", "StuckOutTongueWinkingEye", "StuckOutTongueClosedEyes", "Disappointed", "Frown",
"ColdSweat", "TiredFace", "Grin", "Sob", "Gasp", "Gasp2",
"Laughing", "Joy", "Sweet", "Satisfied", "Innocent", "Wink",
"Ambivalent", "Expressionless", "Sad", "Slant", "Worried", "Kissing",
"KissingHeart", "Angry", "Naughty", "Furious", "Cry", "OpenMouth",
"Fearful", "Confused", "Weary", "Scream", "Astonished", "Flushed",
"Sleeping", "NoMouth", "Mask", "Worried", "Smile", "Muscle",
"Facepunch", "ThumbsUp", "ThumbsDown", "Beers", "Cocktail", "Burger",
"PoultryLeg", "Party", "Cake", "Sun", "Fire", "Heart"
],
'atwho': {
at: ":",
highlight_first: true,
limit: 100
},
init: function(feature, options) {
options.data = feature.emojis;
options.insert_tpl = "<img data-emoji-name=';${name};' class='atwho-emoji' with='18' height='18' src='" + module.config['emoji.url'] + "${name}.svg' />";
options.tpl = "<li class='atwho-emoji-entry' data-value=';${name};'><img with='18' height='18' src='" + module.config['emoji.url'] + "${name}.svg' /></li>";
},
parse: function($clone) {
$clone.find('.atwho-emoji').each(function() {
$(this).replaceWith($(this).data('emoji-name'));
});
}
};
/**
* Mentioning feature supports mentionings by typing @ the default mentioning calls an url after typing three digits.
* Other mentionings can be registered by adding Richtext.features with the at option @:<prefix>
*/
Richtext.features.mentioning = {};
Richtext.features.mentioning.atwho = function() {
// this is the widget instance.
var that = this;
return {
at: "@",
data: [{image: '', 'cssClass': 'hint', name: module.text('info.minInput')}],
insert_tpl: "<a href='${link}' class='atwho-user richtext-mention richtext-link' contenteditable='false' target='_blank' data-guid='${atwho-at}-${type}${guid}'>${atwho-data-value}&#x200b;</a>",
tpl: "<li class='hint' data-value=''>${name}</li>",
limit: 10,
highlight_first: false,
callbacks: {
matcher: function(flag, subtext, should_start_with_space) {
var match, regexp;
regexp = new RegExp(/(\s+|^)@([\u00C0-\u1FFF\u2C00-\uD7FF\w\s\-\']*$)/);
match = regexp.exec(subtext);
this.setting.tpl = "<li class='hint' data-value=''>${name}</li>";
if(match && typeof match[2] !== 'undefined') {
return match[2];
}
return null;
},
remote_filter: function(query, callback) {
this.setting.highlight_first = false;
// check the char length and data-query attribute for changing plugin settings for showing results
if(query.length >= 3) {
// Render loading user feedback.
this.setting.tpl = "<li class='hint' data-value=''>${name}</li>";
this.view.render([{"type": "test", "cssClass": "hint", "name": module.text('info.loading'), "image": "", "link": ""}]);
// set plugin settings for showing results
this.setting.highlight_first = true;
this.setting.tpl = '<li class="${cssClass}" data-value="@${name}">${image} ${name}</li>';
$.getJSON(that.options.mentioningUrl, {keyword: query}, function(data) {
callback(data);
});
// reset query count
query.length = 0;
}
}
}
};
};
Richtext.features.mentioning.init = function(feature, options) {
var widget = this;
//This is a workaround for mobile browsers especially for Android Chrome which is not able to remove contenteditable="false" nodes.
if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|Opera Mini/i.test(navigator.userAgent)) {
this.$.on('contextmenu', 'a, img', function() {
var $this = $(this);
if($this.parent().is('span')) {
$this.parent().remove();
} else {
$this.remove();
}
widget.checkForEmptySpans();
return false;
});
}
};
/**
* Used to parse the feature elements.
*
* @param {type} $clone
* @param {type} widget
* @returns {undefined}
*/
Richtext.features.mentioning.parse = function($clone, widget) {
$clone.find('.atwho-user, .atwho-space').each(function() {
$(this).text($(this).data('guid'));
});
};
module.export({
Richtext: Richtext
});
});

View File

@ -1,178 +0,0 @@
/*
* FlatElements v0.2 by @andystrobel
* Copyright 2014 HumHub
*
* Modified standard checkboxes and radio buttons
*/
//
// create closure
//
(function ($) {
//
// plugin definition
//
$.fn.flatelements = function (options) {
// build main options before element iteration
var opts = $.extend({}, $.fn.flatelements.defaults, options);
//
// check if an element follow the bootstrap html construction
//
function checkBootstrapStructure($obj) {
//alert($obj.parent().parent().attr('class'));
if ($obj.attr('type') == "checkbox" && $obj.parent().prop("tagName") == "LABEL") {
return true;
} else if ($obj.attr('type') == "radio" && $obj.parent().prop("tagName") == "LABEL") {
return true
} else {
return false;
}
}
// iterate and reformat each matched element
return this.each(function () {
// save object in a variable
var $this = $(this);
// Only modify this element, if it follow the bootstrap html construction
if (checkBootstrapStructure($this) == true) {
// modify elements for checkboxes
if ($this.attr('type') == "checkbox") {
// make checkbox to a slider element
if ($this.attr('data-view') == 'slider') {
// check if the standard bootstrap container <div> and <label> exists
if ($this.parent().parent().attr('class') == "checkbox" && $this.parent().prop("tagName") == "LABEL") {
// remove existing container class
$this.parent().parent().removeClass('checkbox');
// add new container class
$this.parent().parent().addClass('onoffswitch');
// add new input class
$this.addClass('onoffswitch-checkbox');
// save label text
var _label = $.trim($this.parent().parent().text());
// remove label text
$this.parent().html($this.parent().find('input'));
// build new slider construct
var _newHTML = '<label class="onoffswitch-label" for="' + $this.attr('id') + '">' +
'<div class="onoffswitch-inner"></div>' +
'<div class="onoffswitch-switch"></div>' +
'</label>';
// add new slider construckt
$this.parent().append(_newHTML);
// build closing slider construct
_newHTML = '<label class="onoffswitch-label" for="' + $this.attr('id') + '">' + _label + '</label>' +
'<div class="onoffswitch-clear"></div>';
// add closing slider contruct
$this.parent().parent().after(_newHTML);
// remove the enclosing label tag
$this.parent().replaceWith($this.parent().html());
}
} else {
// check if the standard bootstrap container <div> exists
if ($this.parent().parent().attr('class') == "checkbox") {
// add new class
$this.parent().parent().addClass('regular-checkbox-container');
// add a new <div> at the end to clear floats
$this.parent().parent().append('<div class="regular-checkbox-clear"></div>');
}
// check if the standard bootstrap <label> exists
if ($this.parent().prop("tagName") == "LABEL") {
// if there is no assignment
if ($this.parent().attr('for') == undefined) {
// assign label to checkbox
$this.parent().attr('for', $this.attr('id'));
var $checkbox = $('<div class="regular-checkbox-box"></div>').attr('style', $this.attr('style'));
if ($this.is(':disabled')) {
$checkbox.addClass('disabled');
}
// add new checkbox element
$this.parent().append($checkbox);
}
}
// add new class to checkbox
$this.addClass('regular-checkbox');
}
// modify elements for radio buttons
} else if ($this.attr('type') == "radio") {
// check if the standard bootstrap container <div> exists
if ($this.parent().parent().attr('class') == "radio") {
// add new class
$this.parent().parent().addClass('regular-radio-container');
}
// check if the standard bootstrap <label> exists
if ($this.parent().prop("tagName") == "LABEL") {
// if there is no assignment
if ($this.parent().attr('for') == undefined) {
// assign label to radio element
$this.parent().attr('for', $this.attr('id'));
var $radio = $('<div class="regular-radio-button"></div>');
if ($this.is(':disabled')) {
$radio.addClass('disabled');
}
// add new radio element
$this.parent().append($radio);
}
}
// add new class to radio element
$this.addClass('regular-radio');
}
}
});
};
//
// plugin defaults
//
$.fn.flatelements.defaults = {};
//
// end of closure
//
})(jQuery);

View File

@ -40,7 +40,6 @@ class CoreApiAsset extends AssetBundle
* @inheritdoc
*/
public $js = [
'js/humhub/legacy/jquery.flatelements.js',
'js/humhub/legacy/jquery.loader.js',
'js/humhub/legacy/app.js',
'js/humhub/humhub.core.js',
@ -48,6 +47,7 @@ class CoreApiAsset extends AssetBundle
'js/humhub/humhub.log.js',
//'js/humhub/humhub.scripts.js',
'js/humhub/humhub.ui.additions.js',
'js/humhub/humhub.ui.form.elements.js',
'js/humhub/humhub.ui.loader.js',
'js/humhub/humhub.action.js',
'js/humhub/humhub.ui.widget.js',

View File

@ -29,10 +29,8 @@ use yii\bootstrap\Html
<?php foreach ($model->targets() as $target): ?>
<td class="text-center">
<label style="margin:0px;">
<?php $disabled = !$target->isEditable($model->user) || $category->isFixedSetting($target)?>
<?= Html::checkbox($model->getSettingFormname($category, $target), $target->isCategoryEnabled($category, $model->user), ['style' => 'margin:0px;', 'disabled' => $disabled]) ?>
</label>
<?php $disabled = !$target->isEditable($model->user) || $category->isFixedSetting($target) ?>
<?= Html::checkbox($model->getSettingFormname($category, $target), $target->isCategoryEnabled($category, $model->user), ['style' => 'margin:0px;', 'disabled' => $disabled]) ?>
</td>
<?php endforeach; ?>

View File

@ -18,7 +18,7 @@ use \yii\helpers\Url;
* And the following methods:
*
* - getItemText for retrieving the option text for an item
* - getItemImage for terieving the option image (if required)
* - getItemImage for retrieving the option image (if required)
*
*
* The json result of a picker search query should return an array of items with the following key/values:
@ -45,7 +45,7 @@ abstract class BasePickerField extends JsWidget
public $jsWidget = 'ui.picker.Picker';
/**
* Disabled
* Disabled items
*/
public $disabledItems;
@ -127,14 +127,6 @@ abstract class BasePickerField extends JsWidget
*/
public $model;
/**
* Input form name.
* This can be provided if no form and model is provided for custom input field setting.
*
* @var type
*/
public $formName;
/**
* Model attribute which holds the picker value. The referenced model attribute has to be an
* array.
@ -143,6 +135,14 @@ abstract class BasePickerField extends JsWidget
*/
public $attribute;
/**
* Input form name.
* This can be set if no form and model is provided for custom input field setting.
*
* @var type
*/
public $formName;
/**
* Can be used to overwrite the default placeholder.
* @var string
@ -311,8 +311,8 @@ abstract class BasePickerField extends JsWidget
}
/**
* Returns an array of texts configurations for this picker isntance.
* Following texts can be configured:
* Returns an array of data attributes for this picker isntance.
* Following data attributes can be configured by default:
*
* - data-placeholder: Placeholder text if no value is set.
* - data-placeholder-more: Placeholder text displayed if at least one item is set.