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 + + Team member +
+
+
+
+
+
+
+ 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