diff --git a/README.md b/README.md
index 7afedc7..773f86a 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,93 @@
MBlock
======
-Beliebig viele Datenblöcke innerhalb eines Moduls, per Drag & Drop verschiebbar.
+Mit MBlock ist es möglich, innerhalb eines Moduls beliebig viele Datenblöcke zu erzeugen. Diese können dann einfach per Button oder Drag & Drop sortiert werden.
+
+_English:_ MBlock lets you create an unlimited number of data blocks within a single module. These data blocks can be sorted per click or drag & drop.
+
+![Screenshot](https://raw.githubusercontent.com/FriendsOfREDAXO/mblock/assets/mblock.png)
+
+## Modulbeispiele / Module examples
+
+MBlock enthält einige Modulbeispiele. Diese findest du auf der MBlock-Seite im REDAXO-Backend. An dieser Stelle möchten wir nur zwei Beispiele auflisten — mit Unterstützung durch [MForm](https://github.com/FriendsOfREDAXO/mform) und ohne —, um zu zeigen, wie MBlock funktioniert.
+
+_English:_ MBlock contains several module examples. You’ll find them on the MBlock page within the REDAXO backend. At this point, we want to show two examples only — one with [MForm](https://github.com/FriendsOfREDAXO/mform) support and another one without — to demonstrate how MBlock works.
+
+### Example 1: team members (requires [MForm](https://github.com/FriendsOfREDAXO/mform) addon)
+
+__Input:__
+
+```php
+addFieldset('Team member');
+
+// textinput
+$mform->addTextField("$id.0.name", array('label'=>'Name')); // use string for x.0 json values
+
+// media button
+$mform->addMediaField(1, array('label'=>'Avatar')); // mblock will auto set the media file as json value
+
+// parse form
+echo MBlock::show($id, $mform->show(), array('min'=>2,'max'=>4)); // add settings min and max
+```
+
+__Output:__
+
+```php
+';
+print_r(rex_var::toArray("REX_VALUE[1]"));
+echo '';
+```
+
+### Example 2: team members (without [MForm](https://github.com/FriendsOfREDAXO/mform))
+
+__Input:__
+
+```php
+
+
+
+
+
+
+
+
+
+ REX_MEDIA[id="1" widget="1"]
+
+
+
+EOT;
+
+// parse form
+echo MBlock::show($id, $form);
+```
+
+__Output:__
+
+```php
+';
+print_r(rex_var::toArray("REX_VALUE[1]"));
+echo '';
+``
+
-![Screenshot](https://raw.githubusercontent.com/FriendsOfREDAXO/mblock/assets/mblock.png)
\ No newline at end of file
diff --git a/assets/mblock.js b/assets/mblock.js
index a908a7c..0837214 100644
--- a/assets/mblock.js
+++ b/assets/mblock.js
@@ -3,12 +3,12 @@
*/
$(function () {
mblock_init();
- $(document).on('pjax:end', function() {
+ $(document).on('pjax:end', function () {
mblock_init();
});
});
-var mblock_module = (function(){
+var mblock_module = (function () {
var callbacks = {
add_item_start: [],
reindex_end: [],
@@ -19,13 +19,13 @@ var mblock_module = (function(){
// @input evnt string name of the event
// @input f function callback
// @output void
- mod.registerCallback = function(evnt, f) {
+ mod.registerCallback = function (evnt, f) {
callbacks[evnt].push(f);
}
// @input evnt string name of the event
// @output []function
- mod.getRegisteredCallbacks = function(evnt) {
+ mod.getRegisteredCallbacks = function (evnt) {
if (typeof callbacks[evnt] === 'undefined') {
return [];
}
@@ -36,9 +36,9 @@ var mblock_module = (function(){
// @input evnt string name of the event
// @output void
- mod.executeRegisteredCallbacks = function(evnt) {
+ mod.executeRegisteredCallbacks = function (evnt) {
var list = mod.getRegisteredCallbacks(evnt);
- for (var i=0;i= element.data('max')) {
element.find('.addme').prop('disabled', true);
} else {
@@ -92,7 +92,7 @@ function mblock_remove(element) {
}
}
- if(element.data().hasOwnProperty('min')) {
+ if (element.data().hasOwnProperty('min')) {
if (finded.length <= element.data('min')) {
element.find('.removeme').prop('disabled', true);
} else {
@@ -100,17 +100,17 @@ function mblock_remove(element) {
}
}
- finded.each(function(index){
+ finded.each(function (index) {
// min removeme hide
- if ((index+1)==element.data('min') && finded.length == element.data('min')) {
+ if ((index + 1) == element.data('min') && finded.length == element.data('min')) {
$(this).find('.removeme').prop('disabled', true);
}
- if (index==0) {
+ if (index == 0) {
$(this).find('.moveup').prop('disabled', true);
} else {
$(this).find('.moveup').prop('disabled', false);
}
- if ((index + 1)== finded.length) { // if max count?
+ if ((index + 1) == finded.length) { // if max count?
$(this).find('.movedown').prop('disabled', true);
} else {
$(this).find('.movedown').prop('disabled', false);
@@ -135,19 +135,35 @@ function mblock_reindex(element) {
var initredactor = false,
initmarkitup = false;
- element.find('> div').each(function(index) {
+ element.find('> div').each(function (index) {
// find input elements
- $(this).find('input,textarea,select,button').each(function(key) {
+ $(this).find('input,textarea,select,button').each(function (key) {
var attr = $(this).attr('name');
eindex = key + 1;
sindex = index + 1;
// For some browsers, `attr` is undefined; for others,
// `attr` is false. Check for both.
if (typeof attr !== typeof undefined && attr !== false) {
- var value = $(this).attr('name').replace($(this).attr('name').match(/\]\[\d+\]\[/g), '][' + index + '][');
+ var value = attr.replace($(this).attr('name').match(/\]\[\d+\]\[/g), '][' + index + '][').replace('mblock_new_','');
$(this).attr('name', value);
}
+ // checkbox problem fix
+ if ($(this).attr('type') == 'checkbox') {
+ $(this).unbind().bind('change', function () {
+ if ($(this).is(':checked')) {
+ $(this).val(1);
+ } else {
+ $(this).val(0);
+ }
+ });
+ }
+
+ // radio problem fix
+ if ($(this).attr('type') == 'radio' && $(this).attr('data-value')) {
+ $(this).val($(this).attr('data-value'));
+ }
+
// select rex button
if ($(this).prop("nodeName") == 'SELECT' && $(this).attr('id') && (
$(this).attr('id').indexOf("REX_MEDIALIST_SELECT_") >= 0 ||
@@ -194,7 +210,7 @@ function mblock_reindex(element) {
// button
$(this).parent().find('a.btn-popup').each(function () {
- if($(this).attr('onclick')) {
+ if ($(this).attr('onclick')) {
$(this).attr('onclick', $(this).attr('onclick').replace(/\(\d+/, '(' + sindex + '00' + eindex));
$(this).attr('onclick', $(this).attr('onclick').replace(/_\d+/, '_' + sindex + '00' + eindex));
}
@@ -208,41 +224,41 @@ function mblock_reindex(element) {
mform_multiple_select(mselect);
}
- $(this).find('.custom-link').each(function(key){
+ $(this).find('.custom-link').each(function (key) {
eindex = key + 1;
sindex = index + 1;
customlink = $(this);
- $(this).find('input').each(function(){
- if($(this).attr('id')) {
+ $(this).find('input').each(function () {
+ if ($(this).attr('id')) {
$(this).attr('id', $(this).attr('id').replace(/\d+/, sindex + '00' + eindex));
}
});
- $(this).find('a.btn-popup').each(function(){
- if($(this).attr('id')) {
+ $(this).find('a.btn-popup').each(function () {
+ if ($(this).attr('id')) {
$(this).attr('id', $(this).attr('id').replace(/\d+/, sindex + '00' + eindex));
}
});
customlink.attr('data-id', sindex + '00' + eindex);
- if(typeof mform_custom_link === 'function') mform_custom_link(customlink);
+ if (typeof mform_custom_link === 'function') mform_custom_link(customlink);
});
- $(this).find('.redactor-box').each(function(key){
+ $(this).find('.redactor-box').each(function (key) {
initredactor = true;
eindex = key + 1;
sindex = index + 1;
- $(this).find('textarea').each(function(){
- if($(this).attr('id')) {
+ $(this).find('textarea').each(function () {
+ if ($(this).attr('id')) {
$(this).attr('id', $(this).attr('id').replace(/\d+/, sindex + '00' + eindex));
}
});
});
- $(this).find('.markitup_markdown, .markitup_textile').each(function(key){
+ $(this).find('.markitup_markdown, .markitup_textile').each(function (key) {
initmarkitup = true;
eindex = key + 1;
sindex = index + 1;
- $(this).find('textarea').each(function(){
- if($(this).attr('id')) {
+ $(this).find('textarea').each(function () {
+ if ($(this).attr('id')) {
$(this).attr('id', $(this).attr('id').replace(/\d+/, sindex + '00' + eindex));
}
})
@@ -252,7 +268,7 @@ function mblock_reindex(element) {
if (initredactor) {
- $('.redactor-box').each(function(){
+ $('.redactor-box').each(function () {
var area;
var content = '';
$(this).find('div.redactor-in').each(function () {
@@ -260,11 +276,11 @@ function mblock_reindex(element) {
content = $(this).html();
}
});
- $(this).find('textarea').each(function(){
+ $(this).find('textarea').each(function () {
var attr = $(this).attr('class');
if (typeof attr !== typeof undefined && attr !== false) {
if ($(this).attr('class').indexOf("redactor") >= 0) {
- area = $(this).clone().css('display','block');
+ area = $(this).clone().css('display', 'block');
}
}
});
@@ -277,14 +293,14 @@ function mblock_reindex(element) {
}
});
- if(typeof redactorInit === 'function') redactorInit();
+ if (typeof redactorInit === 'function') redactorInit();
}
if (initmarkitup) {
- $('.markitup_markdown, .markitup_textile').each(function(){
+ $('.markitup_markdown, .markitup_textile').each(function () {
var area;
- $(this).find('textarea').each(function(){
+ $(this).find('textarea').each(function () {
area = $(this).clone();
});
if (typeof area === 'object') {
@@ -295,7 +311,7 @@ function mblock_reindex(element) {
}
});
- if(typeof markitupInit === 'function' && typeof autosize === 'function') {
+ if (typeof markitupInit === 'function' && typeof autosize === 'function') {
markitupInit();
autosize($("textarea[class*=\'markitupEditor-\']"));
}
@@ -308,30 +324,24 @@ function mblock_reindex(element) {
}
function mblock_replace_for(element) {
-
- element.find(' > div').each(function(index) {
- var mblock = $(this);
- mblock.find('input,textarea,select').each(function(key) {
- var el = $(this);
- var id = el.attr('id');
- if (typeof id !== typeof undefined && id !== false) {
- if (!(id.indexOf("REX_MEDIA") >= 0 ||
- id.indexOf("REX_LINK") >= 0 ||
- id.indexOf("redactor") >= 0 ||
- id.indexOf("markitup") >= 0)
- ) {
- var label = mblock.find('label[for="'+id+'"]');
- el.attr('id', el.attr('name'));
- label.attr('for', el.attr('name'));
- }
- }
- });
- });
-}
-function mblock_replace_checkbox_for(element) {
- element.find('input:checkbox').each(function() {
- $(this).parent().find('label').attr('for', $(this).attr('id'));
+ element.find(' > div').each(function (index) {
+ var mblock = $(this);
+ mblock.find('input,textarea,select').each(function (key) {
+ var el = $(this);
+ var id = el.attr('id');
+ if (typeof id !== typeof undefined && id !== false) {
+ if (!(id.indexOf("REX_MEDIA") >= 0 ||
+ id.indexOf("REX_LINK") >= 0 ||
+ id.indexOf("redactor") >= 0 ||
+ id.indexOf("markitup") >= 0)
+ ) {
+ var label = mblock.find('label[for="' + id + '"]');
+ el.attr('id', el.attr('name'));
+ label.attr('for', el.attr('name'));
+ }
+ }
+ });
});
}
@@ -340,25 +350,46 @@ function mblock_add_item(element, item) {
if (item.parent().hasClass(element.attr('class'))) {
// unset sortable
element.mblock_sortable("destroy");
- // add element
- item.after(item.clone());
- if(element.data().hasOwnProperty('input_delete')) {
+ // item.after(item[0].outerHTML);
+ // item.after(item.clone());
+
+ var iClone = item.clone();
+
+ // fix for checkbox and radio bug
+ iClone.find('input:radio, input:checkbox').each(function(){
+ $(this).parent().removeAttr('for');
+ });
+
+ // fix radio bug
+ iClone.find('input:radio, input:checkbox').each(function(){
+ // fix lost checked from parent item
+ $(this).attr('name', 'mblock_new_' + $(this).attr('name'));
+ // fix lost value
+ $(this).attr('data-value', $(this).val());
+ });
+
+ // add clone
+ item.after(iClone);
+
+ // delete values
+ if (element.data().hasOwnProperty('input_delete')) {
if (element.data('input_delete') == true) {
item.next().find('div.redactor-in').html('');
- item.next().find('input, textarea').val('');
+ item.next().find('input:not(.not_delete), textarea').val('');
item.next().find('textarea').html('');
item.next().find('option:selected').removeAttr("selected");
item.next().find('input:checked').removeAttr("checked");
item.next().find('select').each(function () {
if ($(this).attr('id') && ($(this).attr('id').indexOf("REX_MEDIALIST") >= 0
- || $(this).attr('id').indexOf("REX_LINKLIST") >= 0
- )) {
+ || $(this).attr('id').indexOf("REX_LINKLIST") >= 0
+ )) {
$(this).find('option').remove();
}
});
}
}
+
mblock_set_unique_id(item.next(), true);
// set count
mblock_set_count(element, item);
@@ -371,9 +402,9 @@ function mblock_add_item(element, item) {
}
function mblock_set_unique_id(item, input_delete) {
- item.find('input').each(function() {
+ item.find('input').each(function () {
var unique_id = Math.random().toString(16).slice(2),
- unique_int = parseInt(Math.random()*1000000000000);
+ unique_int = parseInt(Math.random() * 1000000000000);
if ($(this).attr('data-unique-int') == 1) {
unique_id = unique_int;
@@ -403,7 +434,7 @@ function mblock_set_count(element, item) {
function mblock_remove_item(element, item) {
- if(element.data().hasOwnProperty('delete_confirm')) {
+ if (element.data().hasOwnProperty('delete_confirm')) {
if (!confirm(element.data('delete_confirm'))) {
return false;
}
@@ -430,34 +461,34 @@ function mblock_remove_item(element, item) {
function mblock_moveup(element, item) {
var prev = item.prev();
if (prev.length == 0) return;
- prev.css('z-index', 99).addClass('mblock_animate').css({ 'position': 'relative', 'top': item.outerHeight(true) });
- item.css('z-index', 100).addClass('mblock_animate').css({ 'position': 'relative', 'top': - prev.outerHeight(true) });
+ prev.css('z-index', 99).addClass('mblock_animate').css({'position': 'relative', 'top': item.outerHeight(true)});
+ item.css('z-index', 100).addClass('mblock_animate').css({'position': 'relative', 'top': -prev.outerHeight(true)});
- setTimeout(function(){
- prev.removeClass('mblock_animate').css({ 'z-index': '', 'top': '', 'position': '' });
- item.removeClass('mblock_animate').css({ 'z-index': '', 'top': '', 'position': '' });
+ setTimeout(function () {
+ prev.removeClass('mblock_animate').css({'z-index': '', 'top': '', 'position': ''});
+ item.removeClass('mblock_animate').css({'z-index': '', 'top': '', 'position': ''});
item.insertBefore(prev);
mblock_reindex(element);
- },150);
+ }, 150);
}
function mblock_movedown(element, item) {
var next = item.next();
if (next.length == 0) return;
- next.css('z-index', 99).addClass('mblock_animate').css({ 'position': 'relative', 'top': - item.outerHeight(true) });
- item.css('z-index', 100).addClass('mblock_animate').css({ 'position': 'relative', 'top': next.outerHeight(true) });
+ next.css('z-index', 99).addClass('mblock_animate').css({'position': 'relative', 'top': -item.outerHeight(true)});
+ item.css('z-index', 100).addClass('mblock_animate').css({'position': 'relative', 'top': next.outerHeight(true)});
- setTimeout(function(){
- next.removeClass('mblock_animate').css({ 'z-index': '', 'top': '', 'position': '' });
- item.removeClass('mblock_animate').css({ 'z-index': '', 'top': '', 'position': '' });
+ setTimeout(function () {
+ next.removeClass('mblock_animate').css({'z-index': '', 'top': '', 'position': ''});
+ item.removeClass('mblock_animate').css({'z-index': '', 'top': '', 'position': ''});
item.insertAfter(next);
mblock_reindex(element);
- },150);
+ }, 150);
}
function mblock_scroll(element, item) {
- if(element.data().hasOwnProperty('smooth_scroll')) {
+ if (element.data().hasOwnProperty('smooth_scroll')) {
if (element.data('smooth_scroll') == true) {
$.mblockSmoothScroll({
scrollTarget: item,
@@ -468,25 +499,25 @@ function mblock_scroll(element, item) {
}
function mblock_add(element) {
- element.find('> div .addme').unbind().bind('click', function() {
+ element.find('> div .addme').unbind().bind('click', function () {
if (!$(this).prop('disabled')) {
mblock_add_item(element, $(this).closest('div[class^="sortitem"]'));
}
return false;
});
- element.find('> div .removeme').unbind().bind('click', function() {
+ element.find('> div .removeme').unbind().bind('click', function () {
if (!$(this).prop('disabled')) {
mblock_remove_item(element, $(this).closest('div[class^="sortitem"]'));
}
return false;
});
- element.find('> div .moveup').unbind().bind('click', function() {
+ element.find('> div .moveup').unbind().bind('click', function () {
if (!$(this).prop('disabled')) {
mblock_moveup(element, $(this).closest('div[class^="sortitem"]'));
}
return false;
});
- element.find('> div .movedown').unbind().bind('click', function() {
+ element.find('> div .movedown').unbind().bind('click', function () {
if (!$(this).prop('disabled')) {
mblock_movedown(element, $(this).closest('div[class^="sortitem"]'));
}
diff --git a/help.php b/help.php
deleted file mode 100644
index 1a62888..0000000
--- a/help.php
+++ /dev/null
@@ -1,11 +0,0 @@
-getAttribute('id');
+
+ if (!$domId) {
+ return true;
+ }
if (strpos($domId, 'REX_MEDIA') !== false
or strpos($dom->getAttribute('class'), 'redactorEditor') !== false
@@ -252,4 +256,4 @@ public static function getName(DOMElement $dom)
// return $html;
// }
-}
\ No newline at end of file
+}
diff --git a/lib/classes/MBlock.php b/lib/classes/MBlock.php
index 705894f..f5a3160 100644
--- a/lib/classes/MBlock.php
+++ b/lib/classes/MBlock.php
@@ -74,6 +74,9 @@ public static function show($id, $form, $settings = array())
$item->setForm(MBlockSystemButtonReplacer::replaceCustomLinkText($item));
}
+ // set only checkbox block holder
+ $item->setForm(MBlockCheckboxReplacer::replaceCheckboxesBlockHolder($item, ($count+1)));
+
// parse form item
$element = new MBlockElement();
$element->setForm($item->getForm());
diff --git a/lib/classes/Replacer/MBlockCheckboxReplacer.php b/lib/classes/Replacer/MBlockCheckboxReplacer.php
new file mode 100644
index 0000000..1cb6729
--- /dev/null
+++ b/lib/classes/Replacer/MBlockCheckboxReplacer.php
@@ -0,0 +1,32 @@
+getForm());
+ $holderInput = false;
+ $holderName = "REX_INPUT_VALUE[{$item->getValueId()}][{$item->getId()}][checkbox_block_hold]";
+
+ // find input group
+ if ($matches = $document->find('input')) {
+ /** @var DOMElement $match */
+ foreach ($matches as $key => $match) {
+ switch ($match->getAttribute('type')) {
+ case 'checkbox':
+ $holderInput = true;
+ break;
+ }
+ }
+ }
+
+ // return the manipulated html output
+ return ($holderInput) ? '' . $document->htmlOuter() : $document->htmlOuter();
+ }
+}
\ No newline at end of file