From d0ebe496d1e128883f949ed4f271103d0766d861 Mon Sep 17 00:00:00 2001 From: MatthewKosloski Date: Mon, 26 Jun 2017 01:31:11 -0500 Subject: [PATCH] added repeater block toggle header --- metabox_constructor_class.php | 151 +++++++++++++++++++++++----------- script.js | 10 ++- style.css | 53 +++++++++++- 3 files changed, 158 insertions(+), 56 deletions(-) diff --git a/metabox_constructor_class.php b/metabox_constructor_class.php index f5d7341..a9647d3 100644 --- a/metabox_constructor_class.php +++ b/metabox_constructor_class.php @@ -6,6 +6,7 @@ class Metabox_Constructor { const BLOCK_NAMESPACE = 'mcc-box'; // (A.K.A "Metabox Constructor Class") const REPEATER_INDEX_PLACEHOLDER = 'CurrentCounter'; + const REPEATER_ITEM_NUMBER_PLACEHOLDER = 'ItemNumber'; /** * Stores the metabox config that @@ -122,15 +123,39 @@ public function save() { } } + public function column($width, $contents) { + if(isset($width, $contents)) { + return sprintf( + '
%s
', + esc_attr( $this->get_element_class_with_namespace('col') ), + esc_attr( $this->get_element_class_with_namespace(sprintf('col-%d', $width)) ), + esc_html( $contents ) + ); + } + } + /** - * Returns a formatted string for a class name of a field element - * or non-field element. + * Returns a formatted string for a block-element (block__element) class name. + * + * @param string $block + * @param string $element + * @return string + */ + public function get_block_element_class($block, $element) { + if(isset($block, $element)) { + return trim(sprintf('%s__%s', $block, $element)); + } + } + + /** + * Returns a formatted string for a block-element (block__element) class name + * of a field element or non-field element prefixed with the namespace. * * @param string $element * @param boolean $isField * @return string */ - public function get_block_element_class($element, $isField = true) { + public function get_block_element_class_with_namespace($element, $isField = true) { if(isset($element)) { return trim(sprintf( '%s %s%s', @@ -144,6 +169,23 @@ public function get_block_element_class($element, $isField = true) { } } + /** + * Returns a formatted string for a class name prefixed with + * the namespace. + * + * @param string $suffix + * @return string + */ + public function get_element_class_with_namespace($suffix) { + if(isset($suffix)) { + return trim(sprintf( + '%s-%s', + self::BLOCK_NAMESPACE, + $suffix + )); + } + } + /** * Echos some HTML that preceeds a field (container, label, description, etc.) * @@ -153,14 +195,14 @@ public function get_block_element_class($element, $isField = true) { public function before_field($field, $meta = null) { echo sprintf( '
', - esc_attr( $this->get_block_element_class('field-container', false) ), - esc_attr( $this->get_block_element_class($field['type'].'-container', false) ) + esc_attr( $this->get_block_element_class_with_namespace('field-container', false) ), + esc_attr( $this->get_block_element_class_with_namespace($field['type'].'-container', false) ) ); if(isset($field['label'])) { echo sprintf( '', - esc_attr( $this->get_block_element_class('label', false) ), + esc_attr( $this->get_block_element_class_with_namespace('label', false) ), esc_attr( $field['id'] ), esc_html( $field['label'] ) ); @@ -189,7 +231,7 @@ public function after_field($field = null) { public function get_field_description($desc) { echo sprintf( '

%s

', - esc_attr( $this->get_block_element_class('description', false) ), + esc_attr( $this->get_block_element_class_with_namespace('description', false) ), esc_html( $desc ) ); } @@ -206,7 +248,7 @@ public function get_image_preview($field, $meta) { echo sprintf( '%s', esc_attr( sprintf('js-%s-image-preview', $field['id']) ), - esc_attr( sprintf('%s %s', $this->get_block_element_class('image-preview', false), empty($meta) ? 'is-hidden' : '') ), + esc_attr( sprintf('%s %s', $this->get_block_element_class_with_namespace('image-preview', false), empty($meta) ? 'is-hidden' : '') ), esc_attr( $meta ), esc_attr( '' ) ); @@ -270,7 +312,7 @@ public function show_field_text($field, $meta) { $this->before_field($field); echo sprintf( '', - esc_attr( $this->get_block_element_class($field['type']) ), + esc_attr( $this->get_block_element_class_with_namespace($field['type']) ), esc_attr( $field['id'] ), esc_attr( $meta ) ); @@ -281,7 +323,7 @@ public function show_field_textarea($field, $meta) { $this->before_field($field); echo sprintf( '', - esc_attr( $this->get_block_element_class($field['type']) ), + esc_attr( $this->get_block_element_class_with_namespace($field['type']) ), esc_attr( $field['id'] ), esc_html( $meta ) ); @@ -292,7 +334,7 @@ public function show_field_checkbox($field, $meta) { $this->before_field($field); echo sprintf( '', - esc_attr( $this->get_block_element_class($field['type']) ), + esc_attr( $this->get_block_element_class_with_namespace($field['type']) ), esc_attr( $field['id'] ), checked(!empty($meta), true, false) ); @@ -328,7 +370,7 @@ public function show_field_repeater($field, $meta) { echo sprintf( '
', esc_attr( sprintf('js-%s-repeated-blocks', $field['id']) ), - esc_attr( $this->get_block_element_class('repeated-blocks', false) ) + esc_attr( $this->get_block_element_class_with_namespace('repeated-blocks', false) ) ); $count = 0; @@ -350,7 +392,7 @@ public function show_field_repeater($field, $meta) { %s ', esc_attr( sprintf('js-%s-add', $field['id']) ), - esc_attr( $this->get_block_element_class('add', false) ), + esc_attr( $this->get_block_element_class_with_namespace('add', false) ), esc_html( sprintf('Add %s', $field['single_label']) ) ); @@ -374,7 +416,9 @@ public function show_field_repeater($field, $meta) { var count = '.$count.'; $("#js-'. $field['id'] .'-add").on("click", function() { - var repeater = \''.$js_code.'\'.replace(/'. self::REPEATER_INDEX_PLACEHOLDER .'/g, count); + var repeater = \''.$js_code.'\' + .replace(/'. self::REPEATER_INDEX_PLACEHOLDER .'/g, count) + .replace(/'. self::REPEATER_ITEM_NUMBER_PLACEHOLDER .'/g, count + 1); $("#js-'. $field['id'] .'-repeated-blocks").append(repeater); count++; return false; @@ -384,49 +428,58 @@ public function show_field_repeater($field, $meta) { } public function get_repeated_block($field, $meta, $index, $isTemplate = false) { + echo sprintf( '
', - esc_attr( $this->get_block_element_class('repeated', false) ) + esc_attr( $this->get_block_element_class_with_namespace('repeated', false) ) ); - echo sprintf('%s %d', $field['single_label'], $index + 1); - - foreach($field['fields'] as $child_field) { - $old_id = $child_field['id']; - - $child_field['id'] = sprintf( - '%s[%s][%s]', - $field['id'], - ($isTemplate ? self::REPEATER_INDEX_PLACEHOLDER : $index), - $child_field['id'] - ); + // block header + echo sprintf( + '
+

%s

+ +
', + esc_attr( $this->get_element_class_with_namespace('repeated-header', false) ), + esc_attr( $this->get_element_class_with_namespace('clearfix') ), + esc_attr( sprintf('%s %s %s', $this->get_block_element_class('repeated-header', 'title'), $this->get_element_class_with_namespace('col'), $this->get_element_class_with_namespace('col-6')) ), + esc_html( sprintf('%s '.($isTemplate ? '%s' : '%d'), $field['single_label'], ($isTemplate ? self::REPEATER_ITEM_NUMBER_PLACEHOLDER : $index + 1)) ), + esc_attr( sprintf('%s %s %s', $this->get_block_element_class('repeated-header', 'nav'), $this->get_element_class_with_namespace('col'), $this->get_element_class_with_namespace('col-6')) ), + esc_attr( $this->get_block_element_class_with_namespace('repeater-button', false) ), + esc_attr( $this->get_block_element_class_with_namespace('remove', false) ), + esc_attr( sprintf('Remove %s', $field['single_label']) ), + esc_attr( $this->get_block_element_class_with_namespace('repeater-button', false) ), + esc_attr( sprintf('js-%s-sort', self::BLOCK_NAMESPACE) ) + ); - $child_meta = isset($meta[$old_id]) && !$isTemplate ? $meta[$old_id] : ''; + echo sprintf(''; + call_user_func( array($this, 'show_field_' . $child_field['type']), $child_field, $child_meta ); + } + echo '
'; } } diff --git a/script.js b/script.js index 3f706b3..2ee521e 100644 --- a/script.js +++ b/script.js @@ -21,21 +21,25 @@ image_frame.on('select', function() { var attachment = image_frame.state().get('selection').first().toJSON(); - $('#image-' + id).val(attachment.url); + $('#image-'+id).val(attachment.url); $('#js-'+id+'-image-preview').removeClass('is-hidden').attr('src', attachment.url); $('.js-mcc-box-image-upload-button').text('Change Image'); - $('#' + id).css({background: 'red'}); + $('#'+id).css({background: 'red'}); }); image_frame.open(); }); + $('.mcc-box__field-container').on('click', '.mcc-box-repeated-header', function(){ + $(this).siblings('.mcc-box__repeated-content').toggleClass('is-hidden'); + }); + $('.mcc-box__repeated-blocks').on('click', '.mcc-box__remove', function() { - $(this).parent().remove(); + $(this).siblings('.mcc-box__repeated').remove(); return false; }); diff --git a/style.css b/style.css index 81cf3fb..161cf0b 100644 --- a/style.css +++ b/style.css @@ -2,6 +2,12 @@ margin-bottom: 16px; } +.mcc-box-clearfix:after { + content: ""; + display: table; + clear: both; +} + .mcc-box__label { display: block; margin-bottom: 4px; @@ -41,21 +47,60 @@ display: none; } +.mcc-box-repeated-header { + background-color: #008ec2; + color: #fff; + padding: 8px 12px; + cursor: pointer; +} + +.repeated-header__title, +.repeated-header__nav { + margin: 5px 0 0 0; +} + +.mcc-box-repeated-header a { + color: #fff; + cursor: pointer; + padding: 5px; +} + +.mcc-box-repeated-header a:hover { + color: #ddd; +} + +.repeated-header__nav { + text-align: right; +} + +.repeated-header__nav li { + display: inline-block; +} + .mcc-box__repeated { + margin-bottom: 12px; +} + +.mcc-box__repeated-content { border: 1px solid #ddd; background-color: #f5f5f5; padding: 12px; margin: 0 0 12px 0; } +.mcc-box__repeated-content.is-hidden { + display: none; +} + .mcc-box__add span { margin-top: 4px; } -.mcc-box__repeater-button span { - margin-top: 3px; +.mcc-box-col { + display: block; + float: left; } -.mcc-box__repeated .mcc-box__remove { - margin-right: 12px; +.mcc-box-col-6 { + width: 50%; }