Exemplo n.º 1
0
 /**
  * Method to generate HTML content for shortcode
  * in pagebuilder layout
  * 
  * @return string
  */
 public function generateHolder()
 {
     // Using $_POST instead JRequest::getVar() because getVar() can't get tinyMCE content has img tag
     $params = $_POST['params'];
     $params = urldecode($params);
     $shortcode = JRequest::getVar('shortcode');
     $element_title = JRequest::getVar('el_title');
     $class = JSNPagebuilderHelpersShortcode::getShortcodeClass($shortcode);
     $instance = null;
     global $JSNPbElements;
     $elements = $JSNPbElements->getElements();
     $instance = isset($elements[strtolower($class)]) ? $elements[strtolower($class)] : null;
     if (!is_object($instance)) {
         $instance = new $class();
     }
     // Process icon prepend title
     if (isset($instance->items)) {
         $items = array_shift($instance->items);
         foreach ($items as $i => $item) {
             if (isset($item['role']) && isset($item['role_type']) && ($item['role'] == 'title_prepend' && $item['role_type'] == 'icon')) {
                 $arr_params = JSNPagebuilderHelpersShortcode::shortcodeParseAtts($params);
                 $element = JSNPagebuilderHelpersShortcode::shortcodeAtts($instance->config['params'], $arr_params);
                 if (isset($element['icon'])) {
                     $element_title = '<i class="' . $element['icon'] . '"></i>' . $element_title;
                 }
             }
         }
     }
     $content = $instance->element_in_pgbldr('', $params, $element_title);
     echo $content;
     exit;
 }
Exemplo n.º 2
0
 /**
  * DEFINE shortcode content
  *
  * @param array|null $atts
  * @param array|null $content
  *
  * @return string
  */
 public function element_shortcode($atts = null, $content = null)
 {
     $document = JFactory::getDocument();
     $document->addStyleSheet(JSNPB_ELEMENT_URL . '/tab/assets/css/tab.css', 'text/css');
     $arr_params = JSNPagebuilderHelpersShortcode::shortcodeAtts($this->config['params'], $atts);
     extract($arr_params);
     $initial_open = intval($initial_open);
     $tab_position = $tab_position;
     $random_id = JSNPagebuilderHelpersShortcode::generateRandomString();
     $tab_navigator = array();
     $tab_navigator[] = '<ul class="nav nav-tabs">';
     // extract icons of tab items
     $sub_sc_data = JSNPagebuilderHelpersShortcode::extractSubShortcode($content);
     $sub_sc_data = $sub_sc_data[$this->config['has_subshortcode']];
     $items_data = array('icons' => array(), 'heading' => array());
     foreach ($sub_sc_data as $idx => $shortcode) {
         $extract_params = JSNPagebuilderHelpersShortcode::shortcodeParseAtts($shortcode);
         $items_data['icons'][] = !empty($extract_params['icon']) ? "<i class='{$extract_params['icon']}'></i>&nbsp;" : '';
         $items_data['heading'][] = isset($extract_params['heading']) ? $extract_params['heading'] : '';
     }
     $sub_shortcode = empty($content) ? JSNPagebuilderHelpersShortcode::removeAutop($content) : JSNPagebuilderHelpersBuilder::generateShortCode($content, false, 'frontend', true);
     $items = explode('<!--seperate-->', $sub_shortcode);
     $items = array_filter($items);
     $initial_open = $initial_open > count($items) ? 1 : $initial_open;
     if ($fade_effect == 'yes') {
         $fade_effect = 'fade in';
     } else {
         $fade_effect = '';
     }
     foreach ($items as $idx => $item) {
         $active = $idx + 1 == $initial_open ? 'active' : '';
         $item = str_replace('{index}', $random_id . '_' . $idx, $item);
         $item = str_replace('{active}', $active, $item);
         $item = str_replace('{fade_effect}', $fade_effect, $item);
         $items[$idx] = $item;
         $active_li = $idx + 1 == $initial_open ? "class='active'" : '';
         $href = "#pane_" . $random_id . '_' . $idx;
         $tab_navigator[] = "<li {$active_li}><a href='{$href}' data-toggle='tab'>{$items_data['icons'][$idx]}{$items_data['heading'][$idx]}</a></li>";
     }
     $sub_shortcode = implode('', $items);
     $tab_content = "<div class='tab-content'>{$sub_shortcode}</div>";
     // update min-height of each tab content in case tap position is left/right
     if (in_array($tab_position, array('left', 'right'))) {
         $min_height = 36 * count($items);
         $tab_content = str_replace('STYLE', "style='min-height: {$min_height}px'", $tab_content);
     }
     $tab_navigator[] = '</ul>';
     $tab_positions = array('top' => '', 'left' => 'tabs-left', 'right' => 'tabs-right', 'bottom' => 'tabs-below');
     $extra_class = $tab_positions[$tab_position];
     if ($tab_position == 'bottom') {
         $tab_content .= implode('', $tab_navigator);
     } else {
         $tab_content = implode('', $tab_navigator) . $tab_content;
     }
     $html_element = "<div class='tabbable {$extra_class}' id='tab_{ID}'>{$tab_content}</div>";
     $html_element = str_replace('{ID}', "{$random_id}", $html_element);
     return $this->element_wrapper($html_element, $arr_params);
 }
Exemplo n.º 3
0
 /**
  * DEFINE shortcode content
  *
  * @param type $atts
  * @param type $content
  * 
  * @return string
  */
 public function element_shortcode($atts = null, $content = null)
 {
     $document = JFactory::getDocument();
     $document->addStyleSheet(JSNPB_ELEMENT_URL . '/accordion/assets/css/accordion.css', 'text/css');
     $arr_params = JSNPagebuilderHelpersShortcode::shortcodeAtts($this->config['params'], $atts);
     $initial_open = intval($arr_params['initial_open']);
     $multi_open = $arr_params['multi_open'];
     $filter = $arr_params['filter'];
     $random_id = JSNPagebuilderHelpersShortcode::generateRandomString();
     $script = "";
     $scriptFilter = "";
     if ($multi_open == "yes") {
         $script .= "<script type='text/javascript'>( function (\$) {\n\t\t\t\t\t\$( document ).ready( function ()\n\t\t\t\t\t{\n\t\t\t\t\t\t\$( '#accordion_{$random_id} .panel-title a' ).click( function(e ){\n\t\t\t\t\t\t\tvar collapse_item = \$( '#accordion_{$random_id} '+this.hash )\n\t\t\t\t\t\t\tcollapse_item.collapse( 'toggle' )\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t} )( JoomlaShine.jQuery );</script>";
     } else {
         // some case the collapse doesn't work, need this code
         $script .= "<script type='text/javascript'>( function (\$) {\n\t\t\t\t\t\$( document ).ready( function ()\n\t\t\t\t\t{\n\t\t\t\t\t\t\$( '#accordion_{$random_id} .panel-collapse' ).click( function(e ){\n\t\t\t\t\t\t\tvar collapse_item = \$( '#accordion_{$random_id} '+this.hash )\n\t\t\t\t\t\t\t\$( '#accordion_{$random_id} .panel-body' ).each(function(){\n\t\t\t\t\t\t\t\t\$( this ).addClass( 'panel-collapse' );\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tcollapse_item.removeClass( 'panel-collapse' );\n\t\t\t\t\t\t\tcollapse_item.attr( 'style', '' );\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t} )( JoomlaShine.jQuery );</script>";
     }
     $sub_shortcode = empty($content) ? JSNPagebuilderHelpersShortcode::removeAutop($content) : JSNPagebuilderHelpersBuilder::generateShortCode($content, false, 'frontend', true);
     $items = explode("<!--seperate-->", $sub_shortcode);
     // remove empty element
     $items = array_filter($items);
     $initial_open = $initial_open > count($items) ? 1 : $initial_open;
     foreach ($items as $idx => $item) {
         $open = $idx + 1 == $initial_open ? "in" : "";
         $item = str_replace("{index}", $random_id . $idx, $item);
         $item = str_replace("{show_hide}", $open, $item);
         $items[$idx] = $item;
     }
     $sub_shortcode = implode("", $items);
     $filter_html = "";
     if ($filter == "yes") {
         $sub_sc_data = JSNPagebuilderHelpersShortcode::extractSubShortcode($content);
         $sub_sc_data = $sub_sc_data[$this->config['has_subshortcode']];
         $tags = array();
         $tags[] = 'all';
         foreach ($sub_sc_data as $shortcode) {
             $extract_params = JSNPagebuilderHelpersShortcode::shortcodeParseAtts($shortcode);
             $tags[] = isset($extract_params["tag"]) ? $extract_params["tag"] : '';
         }
         $tags = array_filter($tags);
         if (count($tags) > 1) {
             $tags = implode(",", $tags);
             $tags = explode(",", $tags);
             $tags = array_unique($tags);
             $filter_html = "<ul id='filter_{$random_id}' class='nav nav-pills elementFilter' style='margin-bottom:2px;'>";
             foreach ($tags as $idx => $value) {
                 $active = $idx == 0 ? "active" : "";
                 $filter_html .= "<li class='{$active}'><a href='#' class='" . str_replace(" ", "_", $value) . "'>" . ucfirst($value) . "</a></li>";
             }
             $filter_html .= "</ul>";
             // remove "All" tag
             array_shift($tags);
             $inner_tags = implode(',', $tags);
             $scriptFilter .= "<script type='text/javascript'>( function (\$) {\n\t\t\t\t\$( document ).ready( function ()\n\t\t\t\t\t{\n\t\t\t\t\t\twindow.parent.jQuery.noConflict()( '#jsn_view_modal').contents().find( 'data-tag' ).text( '{$inner_tags}')\n\t\t\t\t\t\tvar parent_criteria = '#filter_{$random_id}'\n\t\t\t\t\t\tvar clientsClone = \$( '#accordion_{$random_id}' );\n\t\t\t\t\t\tvar tag_to_filter = 'div';\n\t\t\t\t\t\tvar class_to_filter = '.panel-default';\n\t\n\t\t\t\t\t\t\$( parent_criteria + ' a' ).click( function(e ) {\n\t\t\t\t\t\t\t// stop running filter\n\t\t\t\t\t\t\t\$( class_to_filter ).each(function(){\n\t\t\t\t\t\t\t\t\$( this ).stop( true )\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\te.preventDefault();\n\t\n\t\t\t\t\t\t\t//active clicked criteria\n\t\t\t\t\t\t\t\$( parent_criteria + ' li' ).removeClass( 'active' );\n\t\t\t\t\t\t\t\$( this ).parent().addClass( 'active' );\n\t\n\t\t\t\t\t\t\tvar filterData = \$( this ).attr( 'class' );\n\t\t\t\t\t\t\tvar filters;\n\t\t\t\t\t\t\tif( filterData == 'all' ){\n\t\t\t\t\t\t\t\tfilters = clientsClone.find( tag_to_filter );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tfilters = clientsClone.find( tag_to_filter + '[data-tag~='+ filterData +']' );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tclientsClone.find( class_to_filter ).each(function(){\n\t\t\t\t\t\t\t\t\$( this ).fadeOut();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tfilters.each(function(){\n\t\t\t\t\t\t\t\t\$( this ).fadeIn();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t} )( jQuery )</script>";
         }
     }
     $html = '<div class="panel-group" id="accordion_{ID}">' . $sub_shortcode . '</div>';
     $html = str_replace("{ID}", "{$random_id}", $html);
     $html .= $script . $scriptFilter;
     return $this->element_wrapper($filter_html . $html, $arr_params);
 }
Exemplo n.º 4
0
 /**
  * Return html structure of shortcode in Page Builder area
  * 
  * @param string $shortcode_name
  * @param string $content
  * @param string $shortcode_data
  * @param array $shortcode_params
  * 
  * @return string
  */
 public static function transformShortcodeToPagebuilder($shortcode_name, $content = '', $shortcode_data = '', $shortcode_params = '', $client = 'backend')
 {
     $class = JSNPagebuilderHelpersShortcode::getShortcodeClass($shortcode_name);
     if (class_exists($class)) {
         global $JSNPbElements;
         $JSNPbElements->setGeneratedStatus(true);
         $elements = $JSNPbElements->getElements();
         $instance = isset($elements[strtolower($class)]) ? $elements[strtolower($class)] : null;
         if (!is_object($instance)) {
             $instance = new $class();
         }
         $el_title = "";
         // extract param of shortcode (now for column)
         if (isset($instance->config['extract_param'])) {
             parse_str(trim($shortcode_params), $output);
             foreach ($instance->config['extract_param'] as $param) {
                 if (isset($output[$param])) {
                     $instance->params[$param] = JSNPagebuilderHelpersFunctions::removeQuotes($output[$param]);
                 }
             }
         }
         // get content in pagebuilder of shortcode: Element Title must always first option of Content tab
         if (isset($instance->items["content"]) && isset($instance->items["content"][0])) {
             $title = $instance->items["content"][0];
             if (@$title["role"] == "title") {
                 $params = JSNPagebuilderHelpersShortcode::shortcodeParseAtts($shortcode_params);
                 $el_title = !empty($params[$title["id"]]) ? $params[$title["id"]] : "";
             }
         }
         if ($client === 'backend') {
             $shortcode_view = $instance->element_in_pgbldr($content, $shortcode_data, $el_title);
         } else {
             // Render the shortcode frontend HTML
             $params = JSNPagebuilderHelpersShortcode::shortcodeParseAtts($shortcode_params);
             $shortcode_view = $instance->element_shortcode($params, $content);
         }
         return $shortcode_view;
     }
 }
Exemplo n.º 5
0
        /**
         * Generate HTML in Pagebuilder for Table type
         * 
         * @param sub_item_type $element
         * 
         * @return type
         */
        static function table($element)
        {
            $sub_items = $element["sub_items"];
            $sub_item_type = $element['sub_item_type'];
            $items_html = array();
            $element_name = $element['name'];
            // Get HTML of Each Cell
            $shortcode_data_arr = array();
            foreach ($sub_items as $idx => $item) {
                $element = new $sub_item_type();
                $shortcode_data = "";
                $content = "&nbsp;";
                // don't leave it empty
                if (!empty($item["std"])) {
                    // keep shortcode data as it is
                    $shortcode_data = $item["std"];
                    // reassign params for shortcode base on std string
                    $extract_params = JSNPagebuilderHelpersShortcode::extractParams($item["std"]);
                    $params = JSNPagebuilderHelpersShortcode::generateShortcodeParams($element->items, NULL, $extract_params, TRUE, FALSE, $content);
                    $element->shortcode_data();
                    if (!empty($params["assign_title"])) {
                        $content = $params["assign_title"];
                        $shortcode_data = $element->config['shortcode_structure'];
                    }
                    $shortcode_data_arr[$idx] = $shortcode_data;
                }
                $items_html[] = $element->element_in_pgbldr($content, $shortcode_data);
            }
            // Wrap cell to a Table to display in Pagebuilder
            $row = 0;
            $updated_html = array();
            $columns_count = array();
            foreach ($items_html as $idx => $cell) {
                if (!isset($columns_count[$row])) {
                    $columns_count[$row] = 0;
                } else {
                    $columns_count[$row]++;
                }
                $cell_html = "";
                $cell_wrap = $row == 0 ? "th" : "td";
                if (strpos($cell, '[pb_table_item tagname="tr_start" ][/pb_table_item]') !== false) {
                    $cell_html .= "<tr>";
                } else {
                    if (strpos($cell, '[pb_table_item tagname="tr_end" ][/pb_table_item]') !== false) {
                        // Delete button on right side of table
                        $action_html = $row == 0 ? "" : "<a href='#' title='" . JText::_('JSN_PAGEBUILDER_LIB_SHORTCODE_HTML_DELETE') . "' onclick='return false;' data-target='row_table' class='element-delete'><i class='icon-trash'></i></a>";
                        $cell_html .= "<{$cell_wrap} valign='middle' class='pb-delete-column-td'><div class='jsn-iconbar'>{$action_html}</div></{$cell_wrap}>";
                        $cell_html .= "</tr>";
                        $row++;
                    } else {
                        extract(JSNPagebuilderHelpersShortcode::shortcodeParseAtts($shortcode_data_arr[$idx]));
                        $width = !empty($width_value) ? "width='{$width_value}{$width_type}'" : "";
                        $cell_html .= "<{$cell_wrap} rowspan='{$rowspan}' colspan='{$colspan}' {$width}>{$cell}</{$cell_wrap}>";
                    }
                }
                $updated_html[] = $cell_html;
            }
            // Delete button below the table
            $bottom_row = "<tr class='pb-row-of-delete'>";
            for ($i = 0; $i < max($columns_count) - 1; $i++) {
                $bottom_row .= "<td><div class='jsn-iconbar'><a href='#' title='" . JText::_('JSN_PAGEBUILDER_LIB_SHORTCODE_HTML_DELETE') . "' onclick='return false;' data-target='column_table' class='element-delete'><i class='icon-trash'></i></a></div></td>";
            }
            $bottom_row .= "</tr>";
            $updated_html[] = $bottom_row;
            $items_html = "<table class='table table-bordered' id='table_content'>" . implode("", $updated_html) . "</table>";
            // end Wrap
            $buttons = '<button class="btn table_action" data-target="table_row">' . JText::_('JSN_PAGEBUILDER_LIB_SHORTCODE_HTML_ADD_ROW') . '</button>
						<button class="btn table_action" data-target="table_column">' . JText::_('JSN_PAGEBUILDER_HELPER_ROW_ADD_COLUMN') . '</button>';
            return "<div class='item-container has_submodal table_element'>\n                            <input type='hidden' id='param-el_table' value='table'>\n\t\t\t\t\t\t\t<label for='control-label'>{$element_name}</label>\n\t\t\t\t\t\t\t<div class='jsn-fieldset-filter'><div class='btn-toolbar clearafter'>{$buttons}</div></div>\n\t\t\t\t\t\t\t<div class='ui-sortable item-container-content'>\n\t\t\t\t\t\t\t\t{$items_html}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>";
        }
Exemplo n.º 6
0
    /**
     * Get html item
     *
     * @param array $data
     *
     * @return string
     */
    public static function getElementItemHtml($data)
    {
        $default = array('element_wrapper' => '', 'modal_title' => '', 'element_type' => '', 'name' => '', 'shortcode' => '', 'shortcode_data' => '', 'content_class' => '', 'content' => '', 'action_btn' => '', 'exclude_gen_shortcode' => '', 'has_preview' => true, 'this_' => '');
        $data = array_merge($default, $data);
        extract($data);
        $input_html = '';
        $preview_html = '';
        if ($has_preview) {
            $preview_html = '<div class="shortcode-preview-container" style="display: none">
					<div class="shortcode-preview-fog"></div>
					<div class="jsn-overlay jsn-bgimage image-loading-24"></div>
				</div>';
        }
        $extra_class = 'EXTRA_CLASS';
        $custom_style = 'STYLE';
        $other_class = '';
        if (!empty($this_)) {
            $match = preg_match("/\\[{$shortcode}" . '\\s' . '([^\\]])*' . 'disabled="yes"' . '([^\\]])*' . '\\]/', $shortcode_data);
            if ($match) {
                $other_class = 'disabled';
            }
        }
        $buttons = array('edit' => '<a href="#" onclick="return false;" title="' . JText::_('JSN_PAGEBUILDER_HELPER_BUILDER_EDIT_ELEMENT') . '" data-shortcode="' . $shortcode . '" class="element-edit"><i class="icon-pencil"></i></a>', 'clone' => '<a href="#" onclick="return false;" title="' . JText::_('JSN_PAGEBUILDER_HELPER_BUILDER_DUPLICATE_ELEMENT') . '" data-shortcode="' . $shortcode . '" class="element-clone"><i class="icon-copy"></i></a>', 'delete' => '<a href="#" onclick="return false;" title="' . JText::_('JSN_PAGEBUILDER_HELPER_BUILDER_DELETE_ELEMENT') . '" class="element-delete"><i class="icon-trash"></i></a>');
        if (!empty($other_class)) {
            $buttons = array_merge($buttons, array('deactivate' => '<a href="#" onclick="return false;" title="' . JText::_('JSN_PAGEBUILDER_HELPER_BUILDER_REACTIVE_ELEMENT') . '" data-shortcode="' . $shortcode . '" class="element-deactivate"><i class="icon-checkmark"></i></a>'));
        }
        // Add drag handle
        if ($shortcode === 'pb_table_item') {
            $drag_handle_html = "";
        } else {
            $drag_handle_html = "<div class='heading'><a class='element-drag'></a></div>";
        }
        $action_btns = empty($action_btn) ? implode('', $buttons) : $buttons[$action_btn];
        if (!empty($shortcode_data) && $shortcode == 'pb_pricingtable_item_item') {
            $attrs = JSNPagebuilderHelpersShortcode::shortcodeParseAtts($shortcode_data);
            $matchtype = preg_match("/\\[{$shortcode}" . '\\s' . '([^\\]])*' . 'prtbl_item_attr_type="checkbox"' . '([^\\]])*' . '\\]/', $shortcode_data);
            if ($matchtype == 1) {
                $check_value = isset($attrs['prtbl_item_attr_value']) && $attrs['prtbl_item_attr_value'] != '' ? $attrs['prtbl_item_attr_value'] : 'no';
                $option = array('id' => 'prtbl_item_attr_type_' . $attrs['prtbl_item_attr_id'], 'type' => 'radio', 'std' => $check_value, 'options' => array('yes' => JText::_('JSN_PAGEBUILDER_HELPER_BUILDER_YES'), 'no' => JText::_('JSN_PAGEBUILDER_HELPER_BUILDER_NO')), 'parent_class' => 'no-hover-subitem prtbl_item_attr_type');
                $content = IG_Pb_Helper_Html::radio($option);
                return "<{$element_wrapper} class='jsn-item jsn-element ui-state-default shortcode-container radio-type ' {$element_type} data-name='{$name}' {$custom_style}>\n\t\t\t<textarea class='hidden {$exclude_gen_shortcode} shortcode-content' shortcode-name='{$shortcode}' data-sc-info='shortcode_content' name='shortcode_content[]' >{$shortcode_data}</textarea>\n\t\t\t{$content}\n\t\t\t</{$element_wrapper}>";
            }
        }
        // 		if (strpos($shortcode_data,'system-readmore') !== false) {
        // 		    return "<$element_wrapper id='read-more' class='jsn-item jsn-element ui-state-default jsn-iconbar-trigger shortcode-container $extra_class $other_class' $modal_title $element_type data-name='Read more' $custom_style>
        // 			<textarea class='hidden $exclude_gen_shortcode shortcode-content' shortcode-name='$shortcode' data-sc-info='shortcode_content' name='shortcode_content[]' >$shortcode_data</textarea>
        // 	        <div class='pb-plg-element'>Read more</div>
        // 			</$element_wrapper>";
        // 		} else {
        return "<{$element_wrapper} class='jsn-item jsn-element ui-state-default jsn-iconbar-trigger shortcode-container {$extra_class} {$other_class}' {$modal_title} {$element_type} data-name='{$name}' {$custom_style}>\n\n\t\t\t\t<textarea class='hidden {$exclude_gen_shortcode} shortcode-content' shortcode-name='{$shortcode}' data-sc-info='shortcode_content' name='shortcode_content[]' >{$shortcode_data}</textarea>\n\t\t\t\t{$drag_handle_html}\n\t\t        <div class='{$content_class}'>{$content}</div>\n\t\t        {$input_html}\n\t\t\t\t<div class='jsn-iconbar'>{$action_btns}</div>\n\t\t\t\t{$preview_html}\n\t\t\t\t</{$element_wrapper}>";
        //}
    }
Exemplo n.º 7
0
 /**
  * Filter sub shortcodes content
  *
  * @param array        $sub_sc_data        The array of (sub shortcodes content) attributes of a pricing option
  * @param string       $shortcode          The shortcode name
  * @param string|array $attributes_content The Attributes list of Pricing Table
  */
 public static function _sub_items_filter($sub_sc_data, $shortcode, $attributes_content)
 {
     if ($shortcode != 'pb_pricingtable_item') {
         return $sub_sc_data;
     }
     // Get array of "pricing Attributes"
     if (is_string($attributes_content)) {
         $attributes_content = stripslashes($attributes_content);
         $attributes = explode('--[pb_seperate_sc]--', $attributes_content);
     } else {
         if (is_array($attributes_content)) {
             $attributes = $attributes_content;
         }
     }
     // Key parameter to check relationship between "Attribute in Pricing Item" and "pricing Attribute"
     $key_parameter = 'prtbl_item_attr_id';
     // List of parameter id to sync between "Attribute in Pricing Item" and "pricing Attribute"
     $param_to_sync = array($key_parameter, 'prtbl_item_attr_title', 'prtbl_item_attr_type');
     // Store updated shortcode content
     $result = array();
     // Start updating shortcode content
     foreach ($sub_sc_data as $sc_class => $sub_sc_data_) {
         // Update array of Attributes in this Pricing Item, add value of $key_parameter as key
         $sub_sc_data_new = array();
         foreach ($sub_sc_data_ as $value) {
             $params = JSNPagebuilderHelpersShortcode::shortcodeParseAtts($value);
             $id = $params[$key_parameter];
             $sub_sc_data_new[$id] = $value;
         }
         // Save all exist/new attributes
         $updated_sc_attrs = array();
         foreach ($attributes as $attribute) {
             $attr_params = JSNPagebuilderHelpersShortcode::shortcodeParseAtts($attribute);
             $id = $attr_params[$key_parameter];
             // Get "Attribute in Pricing Item" relates to this "pricing Attribute"
             $is_new_attr = 0;
             if (isset($sub_sc_data_new[$id])) {
                 $related_attr = $sub_sc_data_new[$id];
             } else {
                 // if attribute is not existed, get the first attribute in $sub_sc_data_
                 $related_attr = reset($sub_sc_data_);
                 $is_new_attr = 1;
             }
             // Extract parameters
             $params_of_attr = JSNPagebuilderHelpersShortcode::shortcodeParseAtts($related_attr);
             // Get real attributes ( remove first & last element in array: [0] => "[shortcode_tag" ; [1] => "][/shortcode_tag]" )
             $params_of_attr_real = $params_of_attr;
             if (is_array($params_of_attr_real)) {
                 unset($params_of_attr_real[0]);
                 unset($params_of_attr_real[1]);
             }
             // Update parameter's value from "pricing Attribute" to "Attribute in Pricing Item"
             foreach ($param_to_sync as $parameter) {
                 $params_of_attr_real[$parameter] = isset($attr_params[$parameter]) ? $attr_params[$parameter] : '';
             }
             // Reset parameters of new Attribute which is not in array $param_to_sync
             if ($is_new_attr) {
                 foreach ($params_of_attr_real as $parameter_name => $value) {
                     if (!in_array($parameter_name, $param_to_sync)) {
                         $params_of_attr_real[$parameter_name] = '';
                     }
                 }
             }
             // Join parametes to creating shortcode content
             $sc_content = $params_of_attr[0];
             foreach ($params_of_attr_real as $parameter_name => $value) {
                 $sc_content .= " {$parameter_name}=\"{$value}\"";
             }
             $sc_content .= $params_of_attr[1];
             $updated_sc_attrs[] = $sc_content;
         }
         $result[$sc_class] = $updated_sc_attrs;
     }
     return $result;
 }