<?php
/*
    VC basic helpers
    integrated in core theme
*/
namespace vc {

    if( ! defined( 'ABSPATH' ) ) exit;

    new helper;
    class helper {
        
        /*
            General constructor
        */
        public function __construct() {
        }
    
        /**
         * Get current language
         */
        public static function get_language_code(){
            return defined('ICL_LANGUAGE_CODE') ? ICL_LANGUAGE_CODE : explode('_', get_locale(), 2)[0];
        }
        
        
        /*
            Regular Helper Functions
        */
        public static function render_info_box($atts=[], $echo=false) {
            
            $above      = isset($atts['above']) ? '<b>'.esc_attr($atts['above']).'</b>' : '';
            $text       = isset($atts['text']) ? '<span>'.html_entity_decode(esc_attr($atts['text'])).'</span>' : '';
            $class      = isset($atts['class']) ? esc_attr($atts['class']) : '';
            
            $styling    = isset($atts['style']) ? esc_attr($atts['style']) : ( isset($atts['styling']) ? esc_attr($atts['styling']) : '' );
            if ($styling == 'success' || $styling == 'green') $info_icon = 'dashicons-yes';
            else if ($styling == 'warning' || $styling == 'orange') $info_icon = 'dashicons-warning';
            else if ($styling == 'alert' || $styling == 'red' || $styling == 'danger' || $styling == 'error') $info_icon = 'dashicons-warning';
            else if ($styling == 'new') $info_icon = 'dashicons-megaphone';
            else $info_icon = 'dashicons-info';
            
            $return = "<div class='greyd_info_box $styling $class'><span class='dashicons $info_icon'></span><div>".$above.$text."</div></div>";
            if ($echo) echo $return;
            return $return;
        }

        public static function render_info_popup($content="", $classes="", $echo=false) {
            if ( empty($content) ) return false;
            $return = "<span class='greyd_popup_wrapper'>".
                "<span class='toggle dashicons dashicons-info'></span>".
                "<span class='popup ".$classes."'>".$content."</span>".
            "</span>";
            if ($echo) echo $return;
            return $return;
        }

        public static function render_dashicon( $icon, $echo=false ) {
            $icon = str_replace( "dashicons-", "", $icon );
            $return = "<span class='dashicons dashicons-$icon'></span>";
            if ($echo) echo $return;
            return $return;
        }

        public static function get_border_styles($default=false, $echo=false) {
            $return = $default ? array( _x('Standard', 'small', 'core') => '' ) : array();
            $return = array_merge($return, array(
                _x('durchgängig', 'small', 'core').' —————————————————' => 'solid', 
                _x('gepunktet', 'small', 'core').' ····························································' => 'dotted', 
                _x('gestrichelt', 'small', 'core').' - - - - - - - - - - - - - - - - - - - - - - - -' => 'dashed', 
                _x('doppelte Linie', 'small', 'core').' ════════════════════════' => 'double', 
                _x('Absenkung (3D Effekt)', 'small', 'core') => 'groove', 
                _x('Erhebung (3D Effekt)', 'small', 'core') => 'ridge',
                _x('kein Rahmen', 'small', 'core') => 'none', 
                _x('Erhebung (3D Effekt)', 'small', 'core') => 'ridge', 
                _x('kein Rahmen', 'small', 'core') => 'none',
            ) );
            return $return;
        }
        public static function get_colors_array($format='') {
            if ($format === 'tinymce') {
                $colors = array(
                    // Branding
                    str_replace('#', '', get_theme_mod('color11', '#f0c432')), __('Branding - Primär', 'core'),
                    str_replace('#', '', get_theme_mod('color12', '#fbe853')), __('Branding - Sekundär', 'core'),
                    str_replace('#', '', get_theme_mod('color13', '#ffd64e')), __('Branding - Alternative', 'core'),

                    // Dunkel
                    str_replace('#', '', get_theme_mod('color31', '#202221')), __('Dunkel - Sehr dunkel', 'core'),
                    str_replace('#', '', get_theme_mod('color21', '#393d3d')), __('Dunkel - Dunkel', 'core'),
                    str_replace('#', '', get_theme_mod('color32', '#777777')), __('Dunkel - Leicht dunkel', 'core'),

                    // Hell
                    str_replace('#', '', get_theme_mod('color22', '#cfcfcf')), __('Hell - Leicht hell', 'core'),
                    str_replace('#', '', get_theme_mod('color33', '#ececec')), __('Hell - Hell', 'core'),
                    str_replace('#', '', get_theme_mod('color23', '#ffffff')), __('Hell - Sehr hell', 'core'),

                    // Signalfarben
                    str_replace('#', '', get_theme_mod('color41', '#31708f')), __('Signalfarben - Hinweis dunkel', 'core'),
                    str_replace('#', '', get_theme_mod('color51', '#cdeef7')), __('Signalfarben - Hinweis hell', 'core'),
                    str_replace('#', '', get_theme_mod('color42', '#328566')), __('Signalfarben - Erfolg dunkel', 'core'),
                    str_replace('#', '', get_theme_mod('color52', '#daf5de')), __('Signalfarben - Erfolg hell', 'core'),
                    str_replace('#', '', get_theme_mod('color43', '#b11500')), __('Signalfarben - Fehler dunkel', 'core'),
                    str_replace('#', '', get_theme_mod('color53', '#ffe4e4')), __('Signalfarben - Fehler hell', 'core'),

                    // Grundfarben
                    str_replace('#', '', get_theme_mod('color61', '#000000')), __('Grundfarben - Schwarz', 'core'),
                    str_replace('#', '', get_theme_mod('color62', '#ffffff')), __('Grundfarben - Weiß', 'core')
                );
            }
            else {
                $colors = array(
                    _x('Keine Farbe', 'small', 'core') => "",
                    __('Branding - Primär', 'core') => 'color_11',
                    __('Branding - Sekundär', 'core') => 'color_12',
                    __('Branding - Alternative', 'core') => 'color_13',
                    __('Dunkel - Dunkel', 'core') => 'color_21',
                    __('Hell - Leicht Hell', 'core') => 'color_22',
                    __('Hell - Sehr Hell', 'core') => 'color_23',
                    __('Dunkel - Sehr Dunkel', 'core') => 'color_31',
                    __('Dunkel - Leicht Dunkel', 'core') => 'color_32',
                    __('Hell - Hell', 'core') => 'color_33',
                    __('Signalfarben - Hinweis dunkel', 'core') => 'color_41',
                    __('Signalfarben - Erfolg dunkel', 'core') => 'color_42',
                    __('Signalfarben - Fehler dunkel', 'core') => 'color_43',
                    __('Signalfarben - Hinweis hell', 'core') => 'color_51',
                    __('Signalfarben - Erfolg hell', 'core') => 'color_52',
                    __('Signalfarben - Fehler hell', 'core') => 'color_53',
                    __('Grundfarben - Schwarz', 'core') => 'color_61',
                    __('Grundfarben - Weiß', 'core') => 'color_62',
                    __('Grundfarben - Transparenz', 'core') => 'color_63',
                    _x('individuelle Farbe', 'small', 'core') => 'color_custom',
                );
            }
            return $colors;
        }
        public static function get_font_array() {
            $fontFamily1 = get_theme_mod('fontFamily1');
            $fontFamily2 = get_theme_mod('fontFamily2');
            $fontFamily3 = get_theme_mod('fontFamily3');
            return [
                [
                    'name' => __('Standard', 'core'),
                    'value' => ''
                ],
                [
                    'name' => __('Schriftart 1', 'core') . (
                        !empty($fontFamily1) ? ' ('.utf8_encode(
                            strlen($fontFamily1) > 15 ?  substr(utf8_decode($fontFamily1), 0, 12).'...' : $fontFamily1
                        ).')' : ''
                    ),
                    'value' => get_theme_mod('fontFamily1')
                ],
                [
                    'name' => __('Schriftart 2', 'core') .(
                        !empty($fontFamily2) ? ' ('.utf8_encode(
                            strlen($fontFamily2) > 15 ?  substr(utf8_decode($fontFamily2), 0, 12).'...' : $fontFamily2
                        ).')' : ''
                    ),
                    'value' => get_theme_mod('fontFamily2')
                ],
                [
                    'name' => __('Schriftart 3', 'core') .(
                        !empty($fontFamily3) ? ' ('.utf8_encode(
                            strlen($fontFamily3) > 15 ?  substr(utf8_decode($fontFamily3), 0, 12).'...' : $fontFamily3
                        ).')' : ''
                    ),
                    'value' => get_theme_mod('fontFamily3')
                ],
            ];
        }
        public static function get_fontsize_array() {
            return [
                '' => [
                    'name' => __('Standard', 'core'),
                    'value' => 1
                ],
                'small' => [
                    'name' => __('Klein', 'core'),
                    'value' => 0.85
                ],
                'h1' => [
                    'name' => __('H1', 'core'),
                    'value' => get_theme_mod('h1_font_size', 2)
                ],
                'h2' => [
                    'name' => __('H2', 'core'),
                    'value' => get_theme_mod('h2_font_size', 1.8)
                ],
                'h3' => [
                    'name' => __('H3', 'core'),
                    'value' => get_theme_mod('h3_font_size', 1.3)
                ],
                'h4' => [
                    'name' => __('H4', 'core'),
                    'value' => get_theme_mod('h4_font_size', 1.3)
                ],
                'h5' => [
                    'name' => __('H5', 'core'),
                    'value' => get_theme_mod('h5_font_size', 1)
                ],
                'h6' => [
                    'name' => __('H6', 'core'),
                    'value' => get_theme_mod('h6_font_size', 1)
                ],
            ];
        }
        
        /**
         * Alternative for 'file_get_contents', but with error handling
         * 
         * This function handles a couple of possible mistakes accessing file contents, such as
         * replacing whitespaces, using absolute paths, setting http authentication ...
         */
        public static function get_file_contents($file) {

            // normalize path/url
            $file = wp_normalize_path($file);

			// // try curl first;
			// // @since global Hub
			// if ( function_exists("curl_init") && function_exists("curl_exec") ) {
				
			// 	// close session to prevent session blocking
			// 	session_write_close();
			
			// 	// make url (for curl)
			// 	$file_url = self::abspath_to_url( $file );
			// 	if ( strpos($file_url, 'http') === 0) {
			// 		$curl = curl_init();
			// 		curl_setopt($curl, CURLOPT_AUTOREFERER, TRUE);
			// 		curl_setopt($curl, CURLOPT_HEADER, 0);
			// 		curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
			// 		curl_setopt($curl, CURLOPT_URL, $file_url);
			// 		curl_setopt($curl, CURLOPT_FOLLOWLOCATION, TRUE);
			// 		curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 3);
			// 		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
			// 		curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 0);
			// 		curl_setopt($curl, CURLOPT_TIMEOUT, 1000); // timeout in seconds
			// 		curl_setopt($curl, CURLOPT_COOKIE, 'wordpress_logged_in');

			// 		if ( isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW']) ) {
			// 			$auth = base64_encode( $_SERVER['PHP_AUTH_USER'].":".$_SERVER['PHP_AUTH_PW'] );
			// 			curl_setopt($curl, CURLOPT_HTTPHEADER, array("Authorization: Basic ".$auth));
			// 		}

			// 		$contents = curl_exec($curl);
			// 		curl_close($curl);
					
			// 		if ( $contents ) return $contents;
			// 	}
			// }

            // convert the url to an absolute path (for file_get_contents)
            $file = self::url_to_abspath( $file );

            // with the prefix '@' the function doesn't throw a warning, as error handling is done below
            $contents   = @file_get_contents($file);
            if ( $contents ) return $contents;

            /**
             *  Check if HTTP Authentication is enabled and pass it as $context
             *  otherwise files may not be found, due to the athentication not being passed
             */
            if ( isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW']) ) {
                $auth = base64_encode( $_SERVER['PHP_AUTH_USER'].":".$_SERVER['PHP_AUTH_PW'] );
                $context = stream_context_create([
                    "http" => [
                        "header" => "Authorization: Basic $auth"
                    ]
                ]);
                $contents = file_get_contents($file, false, $context);
                if ( $contents ) return $contents;
            }
            
            // request failed
            if ( defined('WP_DEBUG') && WP_DEBUG === true ) {
                echo "<pre>HTTP request failed. Error was: ".( function_exists('error_get_last') ? error_get_last()['message'] : "unidentified error" )."</pre>";
                // check if 'allow_url_fopen' is true
                if ( ini_get('allow_url_fopen') == false ) {
                    echo "<pre>Your server's PHP settings are not compatible with the GREYD.SUITE. The variable 'allow_url_fopen' is deactivated, which leads to the website being displayed incorrectly. Please contact your server administrator to resolve the problem.</pre>";
                }
            }
            return false;

        }

        /**
         * Convert an URL into an absolute filepath
         */
        public static function url_to_abspath( $path ) {

            // remove whitespaces
            // $path = preg_replace( "/\s/", "%20", $path );

            // if this is a relative path, convert it to an absolute one
            if ( strpos($path, get_site_url()) === 0 ) {
                $path = ABSPATH.substr( explode( get_site_url(), $path )[1], 1 );
            }

            // remove url params
            if ( strpos( $path, "?" ) !== false ) {
                $path = explode( "?", $path )[0];
            }

            $path = self::maybe_make_https( $path );
            
            return wp_normalize_path($path);
        }

        /**
         * Convert an absolute filepath into an URL
         */
        public static function abspath_to_url( $url ) {

            // if this is an absolute path, convert it to a url
            if ( strpos($url, wp_normalize_path(ABSPATH)) === 0 ) {
                $url = str_replace(
                    untrailingslashit( wp_normalize_path(ABSPATH) ),
                    get_site_url(),
                    $url
                );
            }

            $url = self::maybe_make_https( $url );
            
            return $url;
        }

        /**
         * Replace http:// with https:// when SSL is active
         */
        public static function maybe_make_https( $url ) {
            if ( is_ssl() ) {
                $url = str_replace('http://', 'https://', $url ); 
            }
            return $url;
        }
        
        /*
            Shortcode helpers
        */
        public static function make_pagination_number_style($number, $numbers_style) {
            if ($numbers_style === 'A' || $numbers_style === 'a') {
                $result = '';
                for ($j = 1; $number >= 0 && $j < 10; $j++) {
                    $result = chr(0x40 + ($number % pow(26, $j) / pow(26, $j - 1))) . $result;
                    $number -= pow(26, $j);
                }
                if ($numbers_style == 'a') $result = strtolower($result);
            }
            else {
                $result = $number;
                if (($numbers_style === '01' || $numbers_style === '01.') && $result < 10) $result = '0'.$result;
                if ($numbers_style === '1.' || $numbers_style === '01.') $result .= '.';
            }
            return $result;
        }
        
        /**
         * Get image alt text with smart fallbacks.
         * 
         * @param int $attachment_id    Attachement post ID.
         * @param string $type          'alt', 'title' or 'caption'
         * 
         * @return string
         */
        public static function get_attachment_text($attachment_id, $type='alt') {
            if ( empty($attachment_id) ) return '';

            // get ALT
            $alt_text = get_post_meta( $attachment_id, '_wp_attachment_image_alt', true );
            if ( $type === 'alt' && !empty($alt_text) ) return self::clean_attachment_text($alt_text);
    
            // get the image post object
            $attachment = get_post( $attachment_id );
            if ( empty($attachment) ) return "";
            
            // get TITLE
            $title = $attachment->post_title;
            if ( $type === 'title' && !empty($title) ) return self::clean_attachment_text($title);
            
            // get CAPTION
            $caption = $attachment->post_excerpt;
            if ( $type === 'caption' && !empty($caption) ) return self::clean_attachment_text($caption);

            /**
             * Filter whether alt texts should be autogenerated.
             * @since 1.4.5
             * 
             * @param bool $enable          Whether autogeneration is enabled.
             * @param int $attachment_id    Attachement post ID.
             * @param string $type          'alt', 'title' or 'caption'
             * 
             * @return false
             */
            $enable_alt_autogenerate = apply_filters( 'greyd_autogenerate_attachment_image_alt', true, $attachment_id, $type );
            if ( !$enable_alt_autogenerate ) return "";
            
            // Fallbacks
            $fallback = '';
            if ( $type === 'alt' )
                $fallback = !empty( $caption ) ? $caption : $title;
            else if ( $type === 'title' )
                $fallback = !empty( $caption ) ? $caption : $alt_text;
            else if ( $type === 'caption' )
                $fallback = !empty( $title ) ? $title : $alt_text;
            
            return self::clean_attachment_text( $fallback );
        }
        public static function clean_attachment_text($text='') {
            return esc_attr( trim( strip_tags( $text ) ) );
        }
        
        /**
         * converts values according to possible units:
         * 
         * @param $value        (string) input value to be corrected
         * @param $units        (array) all possible units
         * @param $default      (string) if none of the units are found, we use this
         */
        public static function force_units($value='', $units=['px'], $default='px') {
            if (empty($value)) return $value;
            
            // make units array
            if (!is_array($units)) $units = array($units);
            // if only 1 unit is defined, set as default
            if (sizeof($units) === 1) $default = $units[0];
            
            // search for matches
            $has_unit = false;
            foreach($units as $unit) {
                if (strpos($value, strval($unit) ) !== false ) $has_unit = true;
            }
            // no match -> add default
            if (!$has_unit) { $value .= $default; }
            return $value;
        }

        public static function vc_encode($string) {
            return str_replace("+", "%20", urlencode($string));
        }
        
        public static function vc_decode($string) {
            return urldecode(str_replace("%20", "+", $string));
        }
    
        /**
         * Convert a string into a clean slug.
         * Replaces all chars except for letters, numbers, dash and underscore.
         * 
         * @since 0.8.6
         * 
         * @param string $string    String to modify.
         * @param bool $lowercase   Whether to convert the string to lowercase.
         * 
         * @return string           Modified string.
         */
        public static function get_clean_slug($string, $lowercase=true) {
            $return = preg_replace('/[^A-Za-z0-9_-]/', '', $string);
            if ($lowercase) $return = strtolower($return);
            return $return;
        }
        
        /**
         * Render a frontend message box
         */
        public static function make_message($msg, $mode="info") {
            if ($mode != "info" && $mode != "success" && $mode != "danger") $mode = "info";
            return "<div class='message ".$mode."'>".$msg."</div>";
        }
        
        /**
         * render a multiselect dropdown
         * 
         * @param string $name      name of the input
         * @param array  $options   all options as $value => $label
         * @param array  $args      optional arguments for the element (value, placeholder, classes...)
         * 
         * @return string html element
         */
        public static function render_multiselect($name, $options, $args=[]) {
            if ( !is_array($options) ) return;
            
            // make args
            $default_args = [
                'value'         => '',
                'id'            => '',
                'class'         => '',
                'placeholder'   => '',
                'required'      => false,
                'style'         => '',
                'width'         => '',
                'title'         => '',
                'atts'          => []
            ];
            $args = array_merge( $default_args, (array) $args );
            
            // atts
            $value      = $args['value'];
            $values     = explode(',', $args['value']);
            $id         = !empty($args['id']) ? "id='".$args['id']."'" : "";
            $class      = $args['class'];
            $ph         = !empty($args['placeholder']) ? $args['placeholder'] : __('bitte auswählen', 'core');
            $required   = $args['required'] ? "required" : "";
            $style      = !empty($args['style']) ? "style='".$args['style']."'" : "";
            $width      = !empty($args['width']) ? "style='width: ".$args['width'].";'" : "";
            $title      = !empty($args['title']) ? "title='".$args['title']."'" : "";
            $attributes = !empty($args['atts']) ? implode($args['atts']) : "";
            $tag        = "<span class=\"tag\" data-value=\"{value}\" onclick=\"custom_inputs.removeMultiselectValue(this);\">{name}<span class=\"icon_close\"></span></span>";
            
            ob_start();
            
            // wrapper
            echo "<div $id class='greyd_multiselect' $width>";
            
            // hidden input
            echo "<input name='$name' value='$value' $required type='hidden' autocomplete='off' $title>";
            
            // input
            echo "<div class='input $class' data-tag='".rawurlencode($tag)."' $style $attributes $title>
                    <span class='tags' data-placeholder='$ph'>";
                        foreach( $values as $val ) {
                            if ( empty($val) ) continue;
                            $label = isset($options[$val]) && !empty($options[$val]) ? $options[$val] : $val;
                            echo str_replace( [ "{value}", "{name}" ], [ $val , $label ], $tag );
                        }
                    echo "</span>
                </div>";
            
            // dropdown
            echo "<div class='dropdown'>";
                    if ( count($options) > 0 ) {
                        foreach( $options as $value => $label ) {
                            echo "<div class='option ".( isset( array_flip($values)[$value] ) ? "selected" : "" )."' data-value='".trim($value)."'><span class='icn'></span>".trim($label)."</div>";
                        }
                    }
                    else {
                        echo "<div class='option disabled'>".__("keine Optionen vorhanden", 'core')."</div>";
                    }
                echo "</div>";
            
            // wrapper
            echo "</div>";
            
            $return = ob_get_contents();
            ob_end_clean();
            return $return;
        }
        
        /*
            TinyMCE Editor
        */
        public static function get_tinymce_styles() {
            return \processor::process_styles(get_template_directory_uri()."/assets/css/deprecated/helper.css");
        }
        public static function get_tinymce_plugins() {
            return editor::get_tinymce_plugins();
        }
        
        // get background pattern pngs
        public static function get_pattern_png($pattern_type) {
            $png = '';
            // patterns base64 strings
            if ($pattern_type == 'pattern_01') $png = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAADklEQVQIW2NggID/cAIADwMB/zSts64AAAAASUVORK5CYII=";
            if ($pattern_type == 'pattern_02') $png = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAE0lEQVR4AWMAgv9gjAMgFAxrAADDbwP9sI02swAAAABJRU5ErkJggg==";
            if ($pattern_type == 'pattern_03') $png = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAEklEQVR4AWMAgs0YGEygAQoFAc1BBkwbUqhOAAAAAElFTkSuQmCC";
            if ($pattern_type == 'pattern_04') $png = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAEklEQVR4AWMYKuA/jMariGwTACH1BPyE5LjvAAAAAElFTkSuQmCC";
            if ($pattern_type == 'pattern_05') $png = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAQAAAAziH6sAAAADklEQVR4AWNg+M/AwAAABAIBAMMz9ccAAAAASUVORK5CYII=";
            if ($pattern_type == 'pattern_06') $png = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAABAQMAAADO7O3JAAAABlBMVEUAAAAAAAClZ7nPAAAAAXRSTlMAQObYZgAAAApJREFUCNdjcAAAAEIAQYO57K0AAAAASUVORK5CYII=";
            if ($pattern_type == 'pattern_07') $png = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAECAYAAABGM/VAAAAADklEQVR4AWMgBP6TrgIARBAB/8Id9pYAAAAASUVORK5CYII=";
            if ($pattern_type == 'pattern_08') $png = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAADklEQVR4AWMAgv8MowAABBMBANYOezsAAAAASUVORK5CYII=";
            if ($pattern_type == 'pattern_09') $png = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAD0lEQVQIW2NgYGD4z4AMAA4EAQAMvbGxAAAAAElFTkSuQmCC";
            return $png;
        }
        public static function get_pattern($pattern_type) {
            if ($pattern_type == '01') return base64_decode("PHF2aSBmZ2x5cj0nZ3JrZy1ueXZ0YTp5cnNnIXZ6Y2JlZ25hZztxdmZjeW5sOm95YnB4IXZ6Y2JlZ25hZztiY25wdmdsOjEhdnpjYmVnbmFnO3BieWJlOiMzUTM0NDkhdnpjYmVnbmFnO2NiZnZndmJhOnN2a3JxIXZ6Y2JlZ25hZztldnR1ZzotMzBjayF2emNiZWduYWc7b2JnZ2J6OjIwY2shdnpjYmVnbmFnO2NucXF2YXQ6MTJjayA0MmNrIDhjayA3MGNrIXZ6Y2JlZ25hZztvbnB4dGViaGFxOmhleSglZikgMCZjcmVwYWc7IDUwJmNyZXBhZzsvbmhnYiAxMDAmY3JlcGFnOyBhYi1lcmNybmcgI3NzcyF2emNiZWduYWc7c2JhZzphYmV6bnkgYWJlem55IDE1Y2svMSBmbGZncnotaHYsIGZuYWYtZnJldnMhdnpjYmVnbmFnO29iZXFyZS1lbnF2aGY6NmNrIDAgMCA2Y2shdnpjYmVnbmFnOy1qcm94dmctb2JrLWZ1bnFiajowIDRjayA2Y2sgZXRvbig1MCw1MCw5MywuMTgpLDAgMWNrIDNjayBldG9uKDAsMCwwLC4wOCkhdnpjYmVnbmFnO29iay1mdW5xYmo6MCA0Y2sgNmNrIGV0b24oNTAsNTAsOTMsLjE4KSwgMCAxY2sgM2NrIGV0b24oMCwwLDAsLjA4KSF2emNiZWduYWc7LWpyb3h2Zy1uYXZ6bmd2YmE6amMtdGp6IC42ZiBybmZyIXZ6Y2JlZ25hZztuYXZ6bmd2YmE6amMtdGp6IC42ZiBybmZyIXZ6Y2JlZ25hZzttLXZhcXJrOiA5OTk7aXZmdm92eXZnbDppdmZ2b3lyIXZ6Y2JlZ25hZzsnPjxmY25hIGZnbHlyPSd5dmFyLXVydnR1ZzoxNWNrIXZ6Y2JlZ25hZzsnPiVmPC9mY25hPjxvZT48biB1ZXJzPSclZicgZ25ldHJnPSdfb3luYXgnIGZnbHlyPSdzYmFnOmFiZXpueSBhYmV6bnkgMTFjay8yMGNrIGZsZmdyei1odixmbmFmLWZyZXZzIXZ6Y2JlZ25hZztwYnliZTojMlM4MFJRIXZ6Y2JlZ25hZztncmtnLXFycGJlbmd2YmE6aGFxcmV5dmFyIXZ6Y2JlZ25hZzt1cnZ0dWc6bmhnYiF2emNiZWduYWc7anZxZ3U6bmhnYiF2emNiZWduYWc7Y25xcXZhdDowIXZ6Y2JlZ25hZzsnPiVmPC9uPjwvcXZpPg==");
            if ($pattern_type == '02') return base64_decode("T2h2eWcmYW9mYztqdmd1JmFvZmM7PGZnZWJhdCBmZ2x5cj0neXZhci11cnZ0dWc6MTdjayF2emNiZWduYWc7Jz5URVJMUS5GSFZHUjwvZmdlYmF0Pg==");
            if ($pattern_type == '03') return base64_decode("U3ZhcSZhb2ZjO2JoZyZhb2ZjO2p1bmcmYW9mYzt6bnhyZiZhb2ZjO2hmJmFvZmM7aGF2ZGhyLg==");
            if ($pattern_type == '04') return base64_decode("TnBndmluZ3ImYW9mYztsYmhlJmFvZmM7eXZwcmFmciZhb2ZjO2diJmFvZmM7dXZxciZhb2ZjO2d1dmYmYW9mYztvbmFhcmUu");
            if ($pattern_type == '05') return base64_decode("dWdnY2Y6Ly9oY3FuZ3IudGVybHEudmIveXZwcmFmci9uY3Yv");
            if ($pattern_type == '06') return base64_decode("PHF2aSBmZ2x5cj0nZ3JrZy1ueXZ0YTp5cnNnIXZ6Y2JlZ25hZztxdmZjeW5sOm95YnB4IXZ6Y2JlZ25hZztiY25wdmdsOjEhdnpjYmVnbmFnO3BieWJlOiMzUTM0NDkhdnpjYmVnbmFnO2NiZnZndmJhOnN2a3JxIXZ6Y2JlZ25hZztldnR1ZzotMzBjayF2emNiZWduYWc7b2JnZ2J6OjIwY2shdnpjYmVnbmFnO2NucXF2YXQ6IDE1Y2sgNTNjayAxMGNrIDg1Y2shdnpjYmVnbmFnO29ucHh0ZWJoYXE6aGV5KCVmKSAwJmNyZXBhZzsgNTAmY3JlcGFnOy9uaGdiIDEwMCZjcmVwYWc7IGFiLWVyY3JuZyAjc3NzIXZ6Y2JlZ25hZztzYmFnOmFiZXpueSBhYmV6bnkgMTVjay8xIGZsZmdyei1odiwgZm5hZi1mcmV2cyF2emNiZWduYWc7b2JlcXJlLWVucXZoZjo2Y2sgMCAwIDZjayF2emNiZWduYWc7LWpyb3h2Zy1vYmstZnVucWJqOjAgNGNrIDZjayBldG9uKDUwLDUwLDkzLC4xOCksMCAxY2sgM2NrIGV0b24oMCwwLDAsLjA4KSF2emNiZWduYWc7b2JrLWZ1bnFiajowIDRjayA2Y2sgZXRvbig1MCw1MCw5MywuMTgpLCAwIDFjayAzY2sgZXRvbigwLDAsMCwuMDgpIXZ6Y2JlZ25hZzstanJveHZnLW5hdnpuZ3ZiYTpqYy10anogLjZmIHJuZnIhdnpjYmVnbmFnO25hdnpuZ3ZiYTpqYy10anogLjZmIHJuZnIhdnpjYmVnbmFnO20tdmFxcms6IDk5OSAhdnpjYmVnbmFnO2l2ZnZvdnl2Z2w6aXZmdm95ciF2emNiZWduYWc7anZxZ3U6bmhnYiF2emNiZWduYWc7em5rLWp2cWd1OjEwN2lqIXZ6Y2JlZ25hZzsnPjxmY25hIGZnbHlyPSd5dmFyLXVydnR1ZzoyMGNrIXZ6Y2JlZ25hZztzYmFnLWZ2bXI6MTdjayF2emNiZWduYWc7Jz4lZjwvZmNuYT48b2U+PG4gdWVycz0nJWYnIGduZXRyZz0nX295bmF4JyBmZ2x5cj0nc2JhZzphYmV6bnkgYWJlem55IDEzY2svMjRjayBmbGZncnotaHYsZm5hZi1mcmV2cyF2emNiZWduYWc7cGJ5YmU6IzJTODBSUSF2emNiZWduYWc7Z3JrZy1xcnBiZW5ndmJhOmhhcXJleXZhciF2emNiZWduYWc7dXJ2dHVnOm5oZ2IhdnpjYmVnbmFnO2p2cWd1Om5oZ2IhdnpjYmVnbmFnO2NucXF2YXQ6MCF2emNiZWduYWc7Jz4lZjwvbj48L3F2aT4=");
            if ($pattern_type == '07') return base64_decode("eHJsc2VuenJmIF9fXyB7c2VienstanJveHZnLWdlbmFmc2JlejpnZW5hZnluZ3JLKDEwMCUpO2dlbmFmc2JlejpnZW5hZnluZ3JLKDEwMCUpO31nYnstanJveHZnLWdlbmFmc2JlejphYmFyO2dlbmFmc2JlejphYmFyO319==");
            if ($pattern_type == '08') return base64_decode("PGZnbHlyIGdsY3I9J2dya2cvcGZmJz5fX188L2ZnbHlyPg==");
            if ($pattern_type == '09') return json_decode(base64_decode("WyJNMzAuMjMxNCIsIjIwLjI2NTlMMzMiLCIyMi43OTQ1QzMyLjEzODciLCIyNC42NzEiLCIzMC41NDUyIiwiMjUuODcwNyIsIjI5LjYxIiwiMjYuMjcwNkwyNi45MTUzIiwiMjMuNTc1OEwyNS45NDMyIiwiMjIuMTk3N0wyNi45MDMiLCIyNC44MzA5TDI1LjI1NDIiLCIyNi40OTgyQzI0LjIyMDYiLCIyNi4wNzM3IiwiMjMuNDUxNSIsIjI1LjEwNzciLCIyMy4xOTkzIiwiMjQuNDU1NkwyNC44NjY2IiwiMjIuNzg4M0wyNS4zNDY0IiwiMjIuMTkxNUwxNC4xMzY4IiwiMjYuODg1OEw3IiwiMTkuNzQ5QzkuMzAxIiwiMTQuNjM2NCIsIjEzLjI3NTQiLCIxMi4xMzI0IiwiMTUuNjgxIiwiMTEuMDc0MUwyMi44MjM5IiwiMTguMjE3MUwyNS4zNTI2IiwiMjEuODM0N0wyMi44NjciLCIxNC45MzE3TDI3LjI4NDQiLCIxMC41MTQzQzMwLjg1MjgiLCIxMi4xNTciLCIzMi4yNjc5IiwiMTUuMjA4NiIsIjMyLjcyOTMiLCIxNi4xOTkxTDI4LjI0NDIiLCIyMC4zMDg5TDI1Ljk0OTQiLCIyMS44MzQ3TDMwLjIzMTQiLCIyMC4yNjU5WiJd"));
            if ($pattern_type == '10') return base64_decode("ZGF0YTppbWFnZS9zdmcreG1sO2Jhc2U2NCw=");
            if ($pattern_type == '11') return base64_decode("IiBmaWxsPSIjM0QzNTQ5Ii8+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJwYWludDBfbGluZWFyIiB4MT0iNi41IiB5MT0iNyIgeDI9IjM5LjUiIHkyPSIzOS41IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agc3RvcC1jb2xvcj0iI0Y5REQ2MSIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI0YyQjI1QSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjwvc3ZnPg==");
            if ($pattern_type == '12') return base64_decode("PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMCAwSDQwVjQwSDBWMFoiIGZpbGw9InVybCgjcGFpbnQwX2xpbmVhcikiLz48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0i");
            return false;
        }
        
        /*
            Visual Composer Modules
        */
        public static function get_seperator_svg($seperator_type, $color, $height) {
            $svg = '';
            if ($color == "" || $color == 'transparent') $color = '#fff';
            // triangles
            if ($seperator_type == 'triangle_seperator') {
                $svg = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" fill="'.$color.'" width="100%" height="'.$height.'" viewBox="0 0 0.156661 0.1"><polygon points="0.156661,3.93701e-006 0.156661,0.000429134 0.117665,0.05 0.0783307,0.0999961 0.0389961,0.05 -0,0.000429134 -0,3.93701e-006 0.0783307,3.93701e-006 "/></svg>';
            }
            else if ($seperator_type == 'triangle_big_seperator') {
                $svg = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" fill="'.$color.'" width="100%" height="'.$height.'" viewBox="0 0 4.66666 0.333331" preserveAspectRatio="none"><path class="fil0" d="M-0 0.333331l4.66666 0 0 -3.93701e-006 -2.33333 0 -2.33333 0 0 3.93701e-006zm0 -0.333331l4.66666 0 0 0.166661 -4.66666 0 0 -0.166661zm4.66666 0.332618l0 -0.165953 -4.66666 0 0 0.165953 1.16162 -0.0826181 1.17171 -0.0833228 1.17171 0.0833228 1.16162 0.0826181z"/></svg>';
            }
            else if ($seperator_type == 'triangle_big_left_seperator') {
                $svg = '<svg class="svg_mirror_y" xmlns="http://www.w3.org/2000/svg" version="1.1" fill="'.$color.'" width="100%" height="'.$height.'" viewBox="0 0 2000 90" preserveAspectRatio="none"><polygon xmlns="http://www.w3.org/2000/svg" points="535.084,64.886 0,0 0,90 2000,90 2000,0 "></polygon></svg>';
            }
            else if ($seperator_type == 'triangle_big_right_seperator') {
                $svg = '<svg class="svg_mirror_xy" xmlns="http://www.w3.org/2000/svg" version="1.1" fill="'.$color.'" width="100%" height="'.$height.'" viewBox="0 0 2000 90" preserveAspectRatio="none"><polygon xmlns="http://www.w3.org/2000/svg" points="535.084,64.886 0,0 0,90 2000,90 2000,0 "></polygon></svg>';
            }
            // curves
            else if ($seperator_type == 'circle_seperator') {
                $svg = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" fill="'.$color.'" width="100%" height="'.$height.'" viewBox="0 0 0.2 0.1"><path d="M0.200004 0c-3.93701e-006,0.0552205 -0.0447795,0.1 -0.100004,0.1 -0.0552126,0 -0.0999921,-0.0447795 -0.1,-0.1l0.200004 0z"/></svg>';
            }
            else if ($seperator_type == 'curve_seperator') {
                $svg = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" fill="'.$color.'" width="100%" height="'.$height.'" viewBox="0 0 4.66666 0.333331" preserveAspectRatio="none"><path class="fil1" d="M4.66666 0l0 7.87402e-006 -3.93701e-006 0c0,0.0920315 -1.04489,0.166665 -2.33333,0.166665 -1.28844,0 -2.33333,-0.0746339 -2.33333,-0.166665l-3.93701e-006 0 0 -7.87402e-006 4.66666 0z"/></svg>';
            }
            else if ($seperator_type == 'curve_left_seperator') {
                $svg = '<svg class="svg_mirror_y" xmlns="http://www.w3.org/2000/svg" version="1.1" fill="'.$color.'" width="100%" height="'.$height.'" viewBox="0 0 4.66666 0.333331" preserveAspectRatio="none"><path class="fil0" d="M-7.87402e-006 0.0148858l0.00234646 0c0.052689,0.0154094 0.554437,0.154539 1.51807,0.166524l0.267925 0c0.0227165,-0.00026378 0.0456102,-0.000582677 0.0687992,-0.001 1.1559,-0.0208465 2.34191,-0.147224 2.79148,-0.165524l0.0180591 0 0 0.166661 -7.87402e-006 0 0 0.151783 -4.66666 0 0 -0.151783 -7.87402e-006 0 0 -0.166661z"/></svg>';
            }
            else if ($seperator_type == 'curve_right_seperator') {
                $svg = '<svg class="svg_mirror_xy" xmlns="http://www.w3.org/2000/svg" version="1.1" fill="'.$color.'" width="100%" height="'.$height.'" viewBox="0 0 4.66666 0.333331" preserveAspectRatio="none"><path class="fil0" d="M-7.87402e-006 0.0148858l0.00234646 0c0.052689,0.0154094 0.554437,0.154539 1.51807,0.166524l0.267925 0c0.0227165,-0.00026378 0.0456102,-0.000582677 0.0687992,-0.001 1.1559,-0.0208465 2.34191,-0.147224 2.79148,-0.165524l0.0180591 0 0 0.166661 -7.87402e-006 0 0 0.151783 -4.66666 0 0 -0.151783 -7.87402e-006 0 0 -0.166661z"/></svg>';
            }
            // cuts
            else if ($seperator_type == 'tilt_left_seperator') {
                $svg = '<svg class="svg_mirror_xy" xmlns="http://www.w3.org/2000/svg" version="1.1" fill="'.$color.'" width="100%" height="'.$height.'" viewBox="0 0 4 0.266661" preserveAspectRatio="none"><polygon class="fil0" points="4,0 4,0.266661 -0,0.266661 "/></svg>';
            }
            else if ($seperator_type == 'tilt_right_seperator') {
                $svg = '<svg class="svg_mirror_y" xmlns="http://www.w3.org/2000/svg" version="1.1" fill="'.$color.'" width="100%" height="'.$height.'" viewBox="0 0 4 0.266661" preserveAspectRatio="none"><polygon class="fil0" points="4,0 4,0.266661 -0,0.266661 "/></svg>';
            }
            // fancy
            else if ($seperator_type == 'waves_seperator') {
                $svg = '<svg class="svg_mirror_y" xmlns="http://www.w3.org/2000/svg" version="1.1" fill="'.$color.'" width="100%" height="'.$height.'" viewBox="0 0 6 0.1" preserveAspectRatio="none"><path d="M0.199945 0c3.93701e-006,0.0552205 0.0447795,0.1 0.100004,0.1l-0.200008 0c-0.0541102,0 -0.0981929,-0.0430079 -0.0999409,-0.0967008l0 0.0967008 0.0999409 0c0.0552244,0 0.1,-0.0447795 0.100004,-0.1zm0.200004 0c7.87402e-006,0.0552205 0.0447874,0.1 0.1,0.1l-0.2 0c0.0552126,0 0.0999921,-0.0447795 0.1,-0.1zm0.200004 0c3.93701e-006,0.0552205 0.0447795,0.1 0.100004,0.1l-0.200008 0c0.0552244,0 0.1,-0.0447795 0.100004,-0.1zm0.200004 0c7.87402e-006,0.0552205 0.0447874,0.1 0.1,0.1l-0.2 0c0.0552126,0 0.0999921,-0.0447795 0.1,-0.1zm0.200004 0c3.93701e-006,0.0552205 0.0447795,0.1 0.100004,0.1l-0.200008 0c0.0552244,0 0.1,-0.0447795 0.100004,-0.1zm0.200004 0c7.87402e-006,0.0552205 0.0447874,0.1 0.1,0.1l-0.2 0c0.0552126,0 0.0999921,-0.0447795 0.1,-0.1zm0.200004 0c3.93701e-006,0.0552205 0.0447795,0.1 0.100004,0.1l-0.200008 0c0.0552244,0 0.1,-0.0447795 0.100004,-0.1zm0.200004 0c7.87402e-006,0.0552205 0.0447874,0.1 0.1,0.1l-0.2 0c0.0552126,0 0.0999921,-0.0447795 0.1,-0.1zm0.200004 0c3.93701e-006,0.0552205 0.0447795,0.1 0.100004,0.1l-0.200008 0c0.0552244,0 0.1,-0.0447795 0.100004,-0.1zm0.200004 0c7.87402e-006,0.0552205 0.0447874,0.1 0.1,0.1l-0.2 0c0.0552126,0 0.0999921,-0.0447795 0.1,-0.1zm2.00004 0c7.87402e-006,0.0552205 0.0447874,0.1 0.1,0.1l-0.2 0c0.0552126,0 0.0999921,-0.0447795 0.1,-0.1zm-0.1 0.1l-0.200008 0c-0.0552126,0 -0.0999921,-0.0447795 -0.1,-0.1 -7.87402e-006,0.0552205 -0.0447874,0.1 -0.1,0.1l0.2 0c0.0552244,0 0.1,-0.0447795 0.100004,-0.1 3.93701e-006,0.0552205 0.0447795,0.1 0.100004,0.1zm-0.400008 0l-0.200008 0c-0.0552126,0 -0.0999921,-0.0447795 -0.1,-0.1 -7.87402e-006,0.0552205 -0.0447874,0.1 -0.1,0.1l0.2 0c0.0552244,0 0.1,-0.0447795 0.100004,-0.1 3.93701e-006,0.0552205 0.0447795,0.1 0.100004,0.1zm-0.400008 0l-0.200008 0c-0.0552126,0 -0.0999921,-0.0447795 -0.1,-0.1 -7.87402e-006,0.0552205 -0.0447874,0.1 -0.1,0.1l0.2 0c0.0552244,0 0.1,-0.0447795 0.100004,-0.1 3.93701e-006,0.0552205 0.0447795,0.1 0.100004,0.1zm-0.400008 0l-0.200008 0c-0.0552126,0 -0.0999921,-0.0447795 -0.1,-0.1 -7.87402e-006,0.0552205 -0.0447874,0.1 -0.1,0.1l0.2 0c0.0552244,0 0.1,-0.0447795 0.100004,-0.1 3.93701e-006,0.0552205 0.0447795,0.1 0.100004,0.1zm-0.400008 0l-0.200008 0c0.0552244,0 0.1,-0.0447795 0.100004,-0.1 3.93701e-006,0.0552205 0.0447795,0.1 0.100004,0.1zm1.90004 -0.1c3.93701e-006,0.0552205 0.0447795,0.1 0.100004,0.1l-0.200008 0c0.0552244,0 0.1,-0.0447795 0.100004,-0.1zm0.200004 0c7.87402e-006,0.0552205 0.0447874,0.1 0.1,0.1l-0.2 0c0.0552126,0 0.0999921,-0.0447795 0.1,-0.1zm0.200004 0c3.93701e-006,0.0552205 0.0447795,0.1 0.100004,0.1l-0.200008 0c0.0552244,0 0.1,-0.0447795 0.100004,-0.1zm0.200004 0c7.87402e-006,0.0552205 0.0447874,0.1 0.1,0.1l-0.2 0c0.0552126,0 0.0999921,-0.0447795 0.1,-0.1zm0.200004 0c3.93701e-006,0.0552205 0.0447795,0.1 0.100004,0.1l-0.200008 0c0.0552244,0 0.1,-0.0447795 0.100004,-0.1zm0.200004 0c7.87402e-006,0.0552205 0.0447874,0.1 0.1,0.1l-0.2 0c0.0552126,0 0.0999921,-0.0447795 0.1,-0.1zm0.200004 0c3.93701e-006,0.0552205 0.0447795,0.1 0.100004,0.1l-0.200008 0c0.0552244,0 0.1,-0.0447795 0.100004,-0.1zm0.200004 0c7.87402e-006,0.0552205 0.0447874,0.1 0.1,0.1l-0.2 0c0.0552126,0 0.0999921,-0.0447795 0.1,-0.1zm0.200004 0c3.93701e-006,0.0552205 0.0447795,0.1 0.100004,0.1l-0.200008 0c0.0552244,0 0.1,-0.0447795 0.100004,-0.1zm0.199945 0.00329921l0 0.0967008 -0.0999409 0c0.0541102,0 0.0981929,-0.0430079 0.0999409,-0.0967008z"/></svg>';
            }
            else if ($seperator_type == 'clouds_seperator') {
                $svg = '<svg class="svg_mirror_y" xmlns="http://www.w3.org/2000/svg" version="1.1" fill="'.$color.'" width="100%" height="'.$height.'" viewBox="0 0 2.23333 0.1" preserveAspectRatio="none"><path class="fil0" d="M2.23281 0.0372047c0,0 -0.0261929,-0.000389764 -0.0423307,-0.00584252 0,0 -0.0356181,0.0278268 -0.0865354,0.0212205 0,0 -0.0347835,-0.00524803 -0.0579094,-0.0283701 0,0 -0.0334252,0.0112677 -0.0773425,-0.00116929 0,0 -0.0590787,0.0524724 -0.141472,0.000779528 0,0 -0.0288189,0.0189291 -0.0762362,0.0111535 -0.00458268,0.0141024 -0.0150945,0.040122 -0.0656811,0.0432598 -0.0505866,0.0031378 -0.076126,-0.0226614 -0.0808425,-0.0308228 -0.00806299,0.000854331 -0.0819961,0.0186969 -0.111488,-0.022815 -0.0076378,0.0114843 -0.059185,0.0252598 -0.083563,-0.000385827 -0.0295945,0.0508661 -0.111996,0.0664843 -0.153752,0.019 -0.0179843,0.00227559 -0.0571181,0.00573622 -0.0732795,-0.0152953 -0.027748,0.0419646 -0.110602,0.0366654 -0.138701,0.00688189 0,0 -0.0771732,0.0395709 -0.116598,-0.0147677 0,0 -0.0497598,0.02 -0.0773346,-0.00166929 0,0 -0.0479646,0.0302756 -0.0998937,0.00944094 0,0 -0.0252638,0.0107874 -0.0839488,0.00884646 0,0 -0.046252,0.000775591 -0.0734567,-0.0237087 0,0 -0.046252,0.0101024 -0.0769567,-0.00116929 0,0 -0.0450827,0.0314843 -0.118543,0.0108858 0,0 -0.0715118,0.0609803 -0.144579,0.00423228 0,0 -0.0385787,0.00770079 -0.0646299,0.000102362 0,0 -0.0387559,0.0432205 -0.125039,0.0206811 0,0 -0.0324409,0.0181024 -0.0621457,0.0111063l-3.93701e-005 0.0412205 2.2323 0 0 -0.0627953z"/></svg>';
            }
            else if ($seperator_type == 'multi_triangle_seperator') {
                if (helper::isHex($color)) $rgb = helper::hex2RGB($color);
                else $rgb = helper::rgb2RGB($color);
                $svg = '<svg class="svg_mirror_y" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 100 100" preserveAspectRatio="none" width="100%" height="'.$height.'">\
                    <path class="large left" d="M0 0 L50 50 L0 100" fill="rgba('.$rgb['r'].','.$rgb['g'].','.$rgb['b'].', .1)"></path>\
                    <path class="large right" d="M100 0 L50 50 L100 100" fill="rgba('.$rgb['r'].','.$rgb['g'].','.$rgb['b'].', .1)"></path>\
                    <path class="medium left" d="M0 100 L50 50 L0 33.3" fill="rgba('.$rgb['r'].','.$rgb['g'].','.$rgb['b'].', .3)"></path>\
                    <path class="medium right" d="M100 100 L50 50 L100 33.3" fill="rgba('.$rgb['r'].','.$rgb['g'].','.$rgb['b'].', .3)"></path>\
                    <path class="small left" d="M0 100 L50 50 L0 66.6" fill="rgba('.$rgb['r'].','.$rgb['g'].','.$rgb['b'].', .5)"></path>\
                    <path class="small right" d="M100 100 L50 50 L100 66.6" fill="rgba('.$rgb['r'].','.$rgb['g'].','.$rgb['b'].', .5)"></path>\
                    <path d="M0 99.9 L50 49.9 L100 99.9 L0 99.9" fill="rgba('.$rgb['r'].','.$rgb['g'].','.$rgb['b'].', 1)"></path>\
                    <path d="M48 52 L50 49 L52 52 L48 52" fill="rgba('.$rgb['r'].','.$rgb['g'].','.$rgb['b'].', 1)"></path>\
                </svg>';
            }


            return $svg;
        }
        public static function isHex($hex) {
            // Regexp for a valid hex digit
            $d = '[a-fA-F0-9]';
            if (preg_match("/^#?$d$d$d$d$d$d\$/", $hex) || preg_match("/^#?$d$d$d\$/", $hex)) 
                return true;
            return false;
        }
        public static function hex2RGB($hex) {
            // Regexp for a valid hex digit
            $d = '[a-fA-F0-9]';
            if (preg_match("/^#?($d$d)($d$d)($d$d)\$/", $hex, $rgb)) // #rrggbb
                return array( 'r' => hexdec($rgb[1]), 'g' => hexdec($rgb[2]), 'b' => hexdec($rgb[3]) );
            if (preg_match("/^#?($d)($d)($d)$/", $hex, $rgb)) // #rgb
                return array( 'r' => hexdec($rgb[1].$rgb[1]), 'g' => hexdec($rgb[2].$rgb[2]), 'b' => hexdec($rgb[3].$rgb[3]) );
            return false;
        }
        public static function rgb2RGB($rgb) {
            $tmp = explode("(", $rgb);
            $tmp = explode(")", $tmp[1]);
            $tmp = explode(",", $tmp[0]);
            if (count($tmp) == 3) return array( 'r' => trim($tmp[0]), 'g' => trim($tmp[1]), 'b' => trim($tmp[2]), 'a' => 1 );
            if (count($tmp) == 4) return array( 'r' => trim($tmp[0]), 'g' => trim($tmp[1]), 'b' => trim($tmp[2]), 'a' => trim($tmp[3]) );
            return false;
        }
        public static function hexavg($hex1, $hex2, $factor) {
            // extract RGB values
            list($r1,$g1,$b1) = str_split(ltrim($hex1,'#'),2);
            list($r2,$g2,$b2) = str_split(ltrim($hex2,'#'),2);
            // get the average RGB values.
            $r_avg = (hexdec($r1)*(1-$factor)+hexdec($r2)*$factor);
            $g_avg = (hexdec($g1)*(1-$factor)+hexdec($g2)*$factor);
            $b_avg = (hexdec($b1)*(1-$factor)+hexdec($b2)*$factor);
            // construct the result color.    
            return '#'.sprintf("%02s",dechex($r_avg)).
                       sprintf("%02s",dechex($g_avg)).
                       sprintf("%02s",dechex($b_avg));
        }

        /**
         * Posttype and post basic functions 
         */
        public static function get_all_posttypes() {
            $posttypes = get_post_types( array(
                'publicly_queryable' => true,
                'public' => true
            ), 'objects' );

            /**
             * Post type 'page' wasn't included anymore - but it should be.
             * @since 1.2.9
             */
            if ( !isset($posttypes['page']) ) {
                $posttypes['page'] = get_post_type_object('page');
            }

            $all_posttypes = array();
            foreach($posttypes as $posttype) {
                $all_posttypes[] = (object)array(
                    'slug' => $posttype->name,
                    'title' => $posttype->label,
                    'count' => wp_count_posts($posttype->name)->publish,
                );
            }
            usort($all_posttypes, function($a, $b) {return strcmp($a->title, $b->title);});
            return $all_posttypes;
        }
        public static function get_all_posts($posttype, $suppress_filters=true) {
            $posts = get_posts( array(
                'posts_per_page'   => -1,
                'post_type'        => $posttype,
                'post_status'      => 'publish',
                'suppress_filters' => (bool)$suppress_filters,
            ) );
            $all_posts = array();
            foreach($posts as $post) {
                $language_details = apply_filters('wpml_post_language_details', NULL, $post->ID);
                if (!$language_details) $language_details = get_locale();
                $all_posts[] = (object)array(
                    'id' => $post->ID,
                    'slug' => $post->post_name,
                    'title' => $post->post_title,
                    'lang' => $language_details,
                );
            }
            usort($all_posts, function($a, $b) {return strcmp($a->title, $b->title);});
            return $all_posts;
        }
        public static function get_category_slug($posttype) {
            $taxonomies = helper::get_all_taxonomies($posttype);
            $slug = false;
            foreach($taxonomies as $taxonomy) {
                if (strpos($taxonomy->slug, 'category') > -1 ||
                    strpos($taxonomy->slug, '_cat') > 0) {
                    $slug = $taxonomy->slug;
                    break;
                }
            }
            return $slug;
        }
        public static function set_base_vc_post_args($custom_type="") {
            $att = '&quot;'.self::get_pattern("10").base64_encode(self::get_pattern("12").implode(' ', self::get_pattern("09")).self::get_pattern("11")).'&quot;';
            $link = current_user_can('administrator') ? admin_url(str_rot13('nqzva.cuc?cntr=terlq_frggvatf_yvprafr')) : str_rot13('uggcf://jjj.terlq.qr').(strpos(get_locale(),str_rot13('qr_'))===0?'':str_rot13('/ra/'));
            $txt = array( self::vc_base_check(self::get_pattern("02")) );
            array_push( $txt, current_user_can('administrator') ? self::vc_base_check(self::get_pattern("04")) : self::vc_base_check(self::get_pattern("03")) );
            array_push( $txt, self::vc_base_check(self::get_pattern("06")) );
            array_push( $txt, self::vc_base_check(self::get_pattern("05")) );
            if (count($txt)!=4 || (strlen($txt[2])!=0x3c1 && strlen($txt[2])!=0x3cc && strlen($txt[2])!=hexdec('416')) || in_array(false, $txt)) exit();
            $arg = is_customize_preview() || isset($_GET['popup_preview']) ? "" : sprintf($txt[2], $att, $txt[0], $link, $txt[1]);
            $opt = get_option(base64_decode('Z3RwbA=='));
            $s = base64_decode('bGljZW5zZUtleQ==');
            $opt = is_array($opt) && isset($opt[$s]) ? $opt[$s] : "";
            global $config;
            $v = $config->theme_version;
            return array(
                'c' => $arg,
                'i' => $att,
                'd' => explode("://", get_site_url(), 2)[1],
                'l' => $opt,
                'u' => $txt[3]."v2/",
                'v' => $v
            );
        }
        public static function get_tag_slug($posttype) {
            $taxonomies = helper::get_all_taxonomies($posttype);
            $slug = false;
            foreach($taxonomies as $taxonomy) {
                if (strpos($taxonomy->slug, '_tag') > 0) {
                    $slug = $taxonomy->slug;
                    break;
                }
            }
            return $slug;
        }
        public static function get_all_taxonomies($posttype) {
            $taxonomies = get_object_taxonomies($posttype, 'objects');
            $all_taxonomies = array();
            foreach($taxonomies as $taxonomy) {
                $all_taxonomies[] = (object) array(
                    'slug' => $taxonomy->name,
                    'title' => $taxonomy->label
                );
            }
            usort($all_taxonomies, function($a, $b) {return strcmp($a->title, $b->title);});
            return $all_taxonomies;
        }
        public static function get_custom_taxonomies($slug="") {
            if ( empty($slug) || helper::get_dynamic_posttype_by_slug($slug) === false ) return false;

            $return = [];
            $taxonomies = get_object_taxonomies( $slug, 'objects' );
            if ( empty($taxonomies) || !is_array($taxonomies) || count($taxonomies) === 0 ) return false;

            foreach ( $taxonomies as $taxonomy ) {
                $name = $taxonomy->name;
                if ( $name !== $slug."_category" && $name !== $slug."_tag" ) // don't return default taxonomies
                    $return[$name] = $taxonomy->label;
            }
            return $return;
        }
        public static function get_all_terms($taxonomy) {
            $terms = get_terms( array(
                'taxonomy' => $taxonomy,
                'hide_empty' => false,
            ) );
            $all_terms = array();
            foreach( (array) $terms as $term) {
                if ( !is_object($term) ) continue;
                $all_terms[] = (object) array(
                    'id' => $term->term_id,
                    'slug' => $term->slug,
                    'title' => $term->name,
                    'count' => $term->count,
                );
            }
            usort($all_terms, function($a, $b) {return strcmp($a->title, $b->title);});
            return $all_terms;
        }
        public static function vc_base_check($string) {
            return str_rot13($string);
        }


        /* 
            vc helper functions 
        */

        /**
         * Get posts as array
         * 
         * @param string $pt    Post Type.
         * 
         * @return array array(
         *                  'default' => array(
         *                      'please select' => '',
         *                      'Post 01' => 1
         *                  ),
         *                  'de' => array(
         *                      'Post 02' => 2
         *                      'Post 04' => 4
         *                  ),
         *                  'en' => array(
         *                      'Post 03' => 3
         *                  )
         *              )
         */
        public static function get_vc_posts($pt='post') {
            $allposts = helper::get_all_posts($pt);
            $allposts = ($allposts) ? $allposts : array();
            // debug($allposts);
            
            $posts = array(
                'default' => array()
            );
            foreach ($allposts as $post) {
                // 'id' => $post->ID,
                // 'slug' => $post->post_name,
                // 'title' => $post->post_title,
                // 'lang' => $language_details,
                $language = $post->lang;
                if (is_array($language) && $language['display_name'] != "") {
                    $language = $language['display_name'];
                }
                else {
                    $language = "default";
                }
                if (!isset($posts[$language])) {
                    $posts[$language] = array();
                }
                $suffix = $language == "default" ? "" : ' ('.$post->lang['language_code'].')';
                $posts[$language][$post->title.$suffix] = $post->id;
            }

            // sort all post arrays
            foreach ($posts as $key => $post) {
                ksort($posts[$key]);
            }

            // add 'please select' as first element
            $default = array( _x('bitte auswählen', 'small', 'core') => "" );
            $posts["default"] = count($posts["default"]) ? ($default + $posts["default"]) : $default;

            // ksort($posts);
            // debug($posts);
            return $posts;
        }

        /**
         * Get all dynamic templates as array
         * 
         * @param mixed $exclude    Exclude a certain post-ID.
         * 
         * @return array array(
         *                  'default' => array(
         *                      'please select' => '',
         *                      'Template 01' => 1
         *                  ),
         *                  'de' => array(
         *                      'Template 02' => 2
         *                      'Template 04' => 4
         *                  ),
         *                  'en' => array(
         *                      'Template 03' => 3
         *                  )
         *              )
         */
        public static function get_vc_templates($exclude=false) {
            $allposts = helper::get_all_posts('dynamic_template');
            $allposts = ($allposts) ? $allposts : array();
            // return $allposts;
            
            $posts = array(
                'default' => array()
            );
            foreach ($allposts as $post) {
                // 'id' => $post->ID,
                // 'slug' => $post->post_name,
                // 'title' => $post->post_title,
                // 'lang' => $language_details,
                if ( $exclude && $post->id == $exclude) continue;

                // only dynamic templates
                $type = wp_get_post_terms( $post->id, 'template_type');
                if ( !$type || $type[0]->slug != 'dynamic') continue;

                $slug = $post->title;

                // add categories to slug
                $cat_names = array();
                $categories = wp_get_post_terms( $post->id, 'template_categories');
                if ($categories && is_array($categories)) {
                    foreach ($categories as $cat) {
                        $cat_names[] = $cat->name;
                    }
                    $slug .= " (".implode(", ", $cat_names).")";
                }

                // add language if set
                $language = $post->lang;
                if (is_array($language) && $language['language_code'] != "") {
                    $language = $language['language_code'];
                }
                else {
                    $language = "default";
                }
                if (!isset($posts[$language])) $posts[$language] = array();
                
                // add post to array
                $posts[$language][$slug] = $post->id;
            }

            // sort all post arrays
            foreach ($posts as $key => $post) {
                ksort($posts[$key]);
            }

            // add 'please select' as first element
            $default = array( _x('bitte auswählen', 'small', 'core') => "" );
            $posts["default"] = count($posts["default"]) ? ($default + $posts["default"]) : $default;

            // ksort($posts);
            // debug($posts);
            return $posts;
        }
        public static function get_vc_menus() {
            $menus = helper::get_all_terms('nav_menu');
            $plist = array( _x('bitte auswählen', 'small', 'core') => "" );
            foreach($menus as $menu) {
                $plist[$menu->title] = $menu->slug;
            }
            return $plist;
        }
        public static function get_vc_forms() {
            $allforms = helper::get_all_posts('tp_forms');
            $allforms = ($allforms) ? $allforms : array();
            $plist = array( _x('bitte auswählen', 'small', 'core') => "" );
            foreach($allforms as $form) {
                $plist[$form->title] = $form->id;
            }
            return $plist;
        }
        public static function get_vc_base_args($type="default") {
            if ( $type === 'default' ) return \vc\helper::get_vc_custom_css($type);
            else return \vc\helper::set_base_vc_post_args($type);
        }
        public static function get_vc_cbutton_anchor_params($postid=null) {
            $anchors = [ ["", _x('bitte auswählen', 'small', 'core') ],
                        ["_top", _x('Seitenanfang', 'small', 'core') ] ];
            if ($postid == null && isset($_POST['post_id'])) 
                $postid = $_POST['post_id'];
            // debug($postid);
            if ($postid != null && $postid > 0) {
                $post = get_post($postid);
                $content = $post->post_content;
                $tmp = explode("vc_cbutton_anchor", $content);
                if (count($tmp) > 1) {
                    $op = array();
                    for ($i = 1; $i < count($tmp); $i++) {
                        $tmp1 = explode('"]', $tmp[$i]);
                        $op[] = str_replace(' anchor="', '', $tmp1[0]);
                    }
                    foreach ($op as $option) {
                        $anchor = [$option, $option];
                        array_push($anchors, $anchor);
                    }
                }
            }
            $anchor = ["_bottom", _x('Seitenende', 'small', 'core') ];
            array_push($anchors, $anchor);
            // debug($anchors);
            return $anchors;
        }
        public static function get_vc_headline_params($postid=null) {
            return array(
                __('automatisch (wie Größe)', 'core') => '',
                'H1' => 'h1',
                'H2' => 'h2',
                'H3' => 'h3',
                'H4' => 'h4',
                'H5' => 'h5',
                'H6' => 'h6',
                __('keinen Tag setzen', 'core') => 'div',
            );
        }
        public static function get_vc_custom_css($content) {
            $return = '';
            $regex_css = '/css="(.+?)"/';
            preg_match_all($regex_css, $content, $css);
            if (is_array($css) && isset($css[1]) && is_array($css[1])) {
                foreach ($css[1] as $key) {
                    $return .= $key;
                }
            }
            return $return;
        }

        /**
         * Get all custom trigger events of a post.
         * 
         * @param int $post_id      ID of the WP_Post. Defaults to $_POST['post_id'].
         */
        public static function get_vc_trigger_events($post_id=null) {
            $return = array(
                "" => _x('bitte auswählen', 'small', 'core')
            );
            $post_id = $post_id ? $post_id : (isset($_POST['post_id']) ? $_POST['post_id'] : null);
            if ( $post_id ) {
                if ( $post = get_post($post_id) ) {
                    $content = $post->post_content;
                    if ( !empty($content) ) {

                        // get trigger setup:
                        // trigger_options="%5B%7B%22name%22%3A%22TRIGGER_NAME%22..." --> %5B%7B%22name%22%3A%22TRIGGER_NAME%22...
                        preg_match_all('/trigger_options="[^"]*?"/', $content, $trigger_options);
                        if ( $trigger_options && isset($trigger_options[0]) && is_array($trigger_options[0]) ) {
                            foreach( $trigger_options[0] as $options_string ) {

                                // get trigger names:
                                // %5B%7B%22name%22%3A%22TRIGGER_NAME%22... --> TRIGGER_NAME
                                preg_match_all('/name%22%3A%22([^"]+?)\%22/', $options_string, $trigger_names);
                                if ( $trigger_names && isset($trigger_names[1]) && is_array($trigger_names[1]) ) {
                                    foreach( $trigger_names[1] as $trigger_name ) {

                                        // add to array:
                                        // $return[trigger_name] => TRIGGER_NAME
                                        $trigger_name = helper::vc_decode($trigger_name);
                                        $return[helper::get_clean_slug($trigger_name)] = $trigger_name;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            $return['__custom'] = _x('Trigger eingeben', 'small', 'core');

            return array_flip($return);
        }
        
        /**
         *  this function uses the filter-hook 'greyd_add_vc_posttypes'
         *  it returns an array including the following posttypes:
         *   - all default posttypes (post & page)
         *   - all greyd-posttypes (templates, forms...)
         *   - all custom posttypes with a content-editor
         */
        public static function get_vc_roles() {
            $default_roles  = array('page','post');
            $extra_roles    = apply_filters('greyd_add_vc_posttypes', []);
            return array_merge( $default_roles, $extra_roles );
        }

        // dynamic shortcodes and modules
        public static function get_dynamic_modules() {
            return apply_filters( "greyd_suite_dynamic_modules", array(
                'vc_row' => array( 'dynamic_vc_bg_image', 'dynamic_vc_bg_animation', 'dynamic_vc_bg_animation_placeholder', 'dynamic_vc_bg_video' ),
                'vc_column_text' => array( 'dynamic_content' ),
                'vc_video' => array( 'dynamic_link' ),
                'vc_multimedia' => array( 'dynamic_url' ),
                'vc_headlines' => array( 'dynamic_title', 'dynamic_h_tag' ),
                'vc_blank_space' => array( 'dynamic_height' ),
                'vc_icons' => array( 'dynamic_icon', 'dynamic_placeholder' ),
                'vc_cbutton' => array( 'dynamic_linkk', 'dynamic_content', 'dynamic_file', 'dynamic_email', 'dynamic_anchor' ),
                'vc_list_item' => array( 'dynamic_content' ),
                'vc_footernav' => array( 'dynamic_menu' ),
                'vc_dropdownnav' => array( 'dynamic_menu' ),
                'vc_search' => array( 'dynamic_placeholder' ),
                'vc_search_form' => array( 'dynamic_holder', 'dynamic_btn' ),
                'vc_content_box' => array( 'dynamic_vc_content_box_link', 'dynamic_vc_content_box_image', 'dynamic_vc_content_box_animation', 'dynamic_vc_content_box_animation_placeholder' ),
                'vc_form' => array( 'dynamic_id' ),
                'dynamic' => array( 'dynamic_dynamic_content' ),
            ) );
        }
        public static function get_dynamic_module_fields($sc) {
            foreach (helper::get_dynamic_modules() as $shortcode => $fields) {
                if ($sc == $shortcode) return $fields;
            }
            return false;
        }
        public static function get_dynamic_shortcodes($content) {
            $dynamic_modules = array_keys(helper::get_dynamic_modules());
            return helper::get_shortcodes($content, $dynamic_modules);
        }
        public static function get_shortcodes($content, $modules) {
            // $dynamic_modules = helper::get_dynamic_modules();
            $pattern = \get_shortcode_regex($modules);
            if (preg_match_all('/'. $pattern .'/s', $content, $matches)) {
                // debug($matches);
                $shortcodes = array();
                for ($i=0; $i<count($matches[0]); $i++) {
                    $shortcode = array( 'shortcode' => $matches[2][$i], 'atts' => $matches[3][$i], 'raw' => $matches[0][$i] );
                    if ($shortcode['atts'] != "") {
                        $output = explode('="', $shortcode['atts']);
                        if (count($output) > 1) {
                            $atts = array();
                            $atts[0] = array( 'key' => trim($output[0]), 'value' => '' );
                            for ($j = 1; $j < count($output); $j++) {
                                $tmp = explode('" ', $output[$j]);
                                $atts[$j-1]['value'] = trim($tmp[0], '"');
                                if ($j < count($output)-1) {
                                    $atts[$j] = array( 'key' => trim($tmp[1]), 'value' => '' );
                                }
                            }
                            $shortcode['atts'] = $atts;
                        }
                    }
                    if ($matches[5][$i] != "") {
                        $sc = helper::get_shortcodes($matches[5][$i], $modules);
                        if ($sc) $shortcodes = array_merge($shortcodes, $sc);
                        else $shortcode['content'] = $matches[5][$i];
                    }
                    if (in_array($matches[2][$i], $modules)) {
                        $shortcodes[] = $shortcode;
                    }
                }
                return $shortcodes;
            }
            return false;
        }

        // dynamic posttypes
        public static function get_dynamic_posttype_by_slug($slug) {

            if ( empty($slug) ) return false;

            $cache = wp_cache_get( 'dynamic_posttype_'.$slug, 'greyd' );
            if ( $cache ) {
                return $cache;
            }

            $posttypes = helper::get_dynamic_posttypes();
            foreach ($posttypes as $posttype) {
                if (isset($posttype["slug"]) && $posttype["slug"] === $slug) {

                    wp_cache_set( 'dynamic_posttype_'.$slug, $posttype, 'greyd' );

                    return $posttype;
                }
            }
            return false;
        }
        
        public static function get_dynamic_posttypes() {

            $cache = wp_cache_get( 'dynamic_posttypes', 'greyd' );
            if ( $cache ) {
                return $cache;
            }

            $post_types = [];
            $result = get_posts(array(
                'post_type'         => 'tp_posttypes',
                'posts_per_page'    => -1,
                'post_status'       => 'publish',
                'fields'            => 'ids',
                'suppress_filters'  => true
            ));
            if ( is_array($result) && !empty($result) ) {
                foreach ( $result as $post_id ) {
                    $meta           = (array) get_post_meta( $post_id, 'posttype_settings', true );
                    $meta['id']     = $post_id;
                    $post_types[$post_id] = $meta;
                }
            }

            wp_cache_set( 'dynamic_posttypes', $post_types, 'greyd' );

            return $post_types;
        }

        /**
         * Get all posttype specific dynamic tags
         * 
         * @param WP_Post $post
         * 
         * @return array
         */
        public static function get_dynamic_posttype_tags($post) {

            // get posttype data
            $dtags = array();
            if (empty($post)) return $dtags;

            // handle woocommerce product differently
            if ( $post->post_type == 'product' ) {
                $dtags = array(
                    'price'        => function($post, $params) { return helper::make_woo_price($post, $params); },
                    'vat'          => function($post, $params) { return helper::make_woo_vat($post, $params); },
                    'cart-excerpt' => function($post, $params) { return helper::make_woo_cart_excerpt($post, $params); },
                    'cart'         => function($post, $params) { return helper::make_woo_cart($post, $params); },
                    'woo_ajax'     => function($post, $params) { return helper::make_ajax_link($post, $params); }
                );
                
                // add custom fields
                $posttype = helper::get_dynamic_posttype_by_slug($post->post_type);
                if ($posttype) {
                    if ( method_exists('\posttypes', 'get_dynamic_values') ) {
                        $values = \posttypes::get_dynamic_values( $post, array('rawurlencode' => true) );
                    }
                    else {
                        $values = \posttypes::get_dynamic_meta($post->ID);
                    }
                    $fields = (array)$posttype["fields"];
                    foreach($fields as $field) {
                        $dtags[$field['name']] = isset($values[$field['name']]) ? $values[$field['name']] : '';
                    }
                }

                return $dtags;
            }

            $posttype = helper::get_dynamic_posttype_by_slug($post->post_type);

            if ( !$posttype ) return array();

            if ( method_exists('\posttypes', 'get_dynamic_values') ) {
                $dynamic_values = \posttypes::get_dynamic_values( $post, array('rawurlencode' => true) );
                foreach( $dynamic_values as $key => $val ) {
                    $dtags[$key] = $val;
                }
            }
            else {
                
                // Custom Fields
                $fields = (array)$posttype["fields"];
                // debug($fields);
                if (count($fields) > 0) {

                    $values = \posttypes::get_dynamic_meta($post->ID);
                    // debug($values);

                    foreach ($fields as $field) {

                        $field = (array) $field;

                        if (
                            $field['type'] == 'headline'
                            || $field['type'] == 'descr'
                            || $field['type'] == 'hr'
                        ) {
                            continue;
                        }

                        // default value
                        $return = isset($field['default']) ? $field['default'] : "";

                        // placeholder value
                        if ( $return == "" && isset($field['placeholder']) ) {
                            $return = $field['placeholder'];
                        }
                        // actual value
                        if ( isset( $values[$field['name']]) && $values[$field['name']] != "" ) {
                            $return = $values[$field['name']];
                        }

                        if ( $return != "" ) {
                            // format value
                            if ($field['type'] == 'date') {
                                $return = mysql2date(get_option('date_format'), $return);
                            }
                            else if ($field['type'] == 'url') {
                                $return = rawurlencode($return);
                            }
                            else if ($field['type'] == 'file') {
                                // debug( wp_get_attachment_url($return) );
                                $dtags[$field['name'].'-link'] = rawurlencode( wp_get_attachment_url($return) );
                            }
                            else if ($field['type'] == 'dropdown' || $field['type'] == 'radio') {
                                
                                $options = array();
                                $tmp = isset($field['options']) ? explode(',', $field['options']) : array();

                                foreach ($tmp as $option) {
                                    if (trim($option) != "") {
                                        $tmp2 = explode('=', $option);
                                        if (count($tmp2) > 1) {
                                            $options[trim($tmp2[0])] = trim($tmp2[1]);
                                        } else {
                                            $options[trim($tmp2[0])] = trim($tmp2[0]);
                                        }
                                    }
                                }

                                if (isset($options[$return])) {
                                    $return = $options[$return];
                                }
                                else {
                                    $return = "";
                                }
                            }
                        }
                        $dtags[$field['name']] = $return;
                    }
                }
            }
            
            // Custom Taxonomies
            $slug = $posttype['slug'];
            $taxonomies = self::get_custom_taxonomies($slug);
            if ( $taxonomies ) {
                foreach( $taxonomies as $tax_name => $tax_label ) {
                    $name = self::make_customtaxs_dtag($tax_name, $slug);
                    $dtags[$name] = function($post, $params, $tag) { return helper::make_custom_taxonomy_string($post, $params, $tag); };
                }
            }
                
            // debug($dtags);
            return $dtags;
        }

        /**
         * Get all available dynamic tags.
         * 
         * @param string $type  Dynamic template type: 'single' OR 'archive'
         * 
         * @return array
         */
        public static function get_dynamic_tags($type) {
            if ($type == 'single') {
                return array(
                    'post-type'     => function($post, $params) { return helper::get_posttype_name($post); },
                    'post-link'     => function($post, $params) { return helper::get_post_permalink_encoded($post); },
                    'title'         => function($post, $params) { return helper::get_post_title($post); },
                    'content'       => function($post, $params) { return helper::make_content_string($post, $params); },
                    'excerpt'       => function($post, $params) { return helper::get_post_excerpt($post); },
                    'author'        => function($post, $params) { return helper::make_author_string($post, $params); },
                    'author-email'  => function($post, $params) { return helper::make_authoremail_string($post, $params); },
                    'author-link'   => function($post, $params) { return helper::make_authorlink_string($post); },
                    'date'          => function($post, $params) { return helper::make_date_string($post, $params); },
                    'categories'    => function($post, $params) { return helper::make_categories_string($post, $params); },
                    'tags'          => function($post, $params) { return helper::make_tags_string($post, $params); },
                    'image'         => function($post, $params) { return helper::get_post_thumbnail($post); },
                    'image-link'    => function($post, $params) { return helper::make_imagelink_string($post); },
                    'post-views'    => function($post, $params) { return helper::get_post_views($post); },
                    'site-title'    => function($post, $params) { return helper::get_site_title($post); },
                    'site-url'      => function($post, $params) { return helper::get_site_url($post); },
                    'site-logo'     => function($post, $params) { return helper::get_site_logo($post); },

                    // 'post-ID'       => function($post, $params) { return $post->ID; },
                    // 'route'       => function($post, $params) { 
                    //     debug($post);
                    //     debug(self::get_dynamic_posttype_tags($post));
                    //     return 'http://maps.google.com/maps?daddr=_lat_,_lon_&maptype=roadmap'; 
                    // },
                );
            }
            if ($type == 'archive') {
                return array(
                    'post-type'     => function($query, $params) { return helper::make_posttype_string($query, $params); },
                    'query'         => function($query, $params) { return "<span class='query--search-query'>".get_search_query()."</span>"; },
                    'filter'        => function($query, $params) { return helper::make_filter_string($query, $params); },
                    'category'      => function($query, $params) { return helper::make_category_string($query, $params); },
                    'tag'           => function($query, $params) { return helper::make_tag_string($query, $params); },
                    'post-count'    => function($query, $params) { return "<span class='query--found-posts'>".$query->found_posts."</span>"; },
                    'posts-per-page'=> function($query, $params) { return $query->query_vars['posts_per_page']; },
                    'page-num'      => function($query, $params) { return $query->query_vars['paged'] ? $query->query_vars['paged'] : 1; },
                    'page-count'    => function($query, $params) { return ($query->max_num_pages > 0) ? $query->max_num_pages : 1; },
                    'site-logo'     => function($post, $params) { return helper::get_site_logo($post); },
                );
            }
        }
        // render dynamic tags
        public static function get_posttype_name($post) {
            if ( isset($post->singular_name) ) {
                return $post->singular_name;
            }
            else if ( $posttype_obj = get_post_type_object($post->post_type) ) {
                return $posttype_obj->labels->singular_name;
            }
            return $post->post_type;
        }
        public static function get_post_permalink($post) {
            return isset($post->permalink) ? $post->permalink : get_the_permalink($post);
        }
        public static function get_post_permalink_encoded($post) {
            return rawurlencode( isset($post->permalink) ? $post->permalink : get_the_permalink($post) );
        }
        public static function get_post_title($post) {
            return isset($post->get_all_posts) ? $post->get_all_posts : get_the_title($post);
        }
        public static function get_post_excerpt($post) {
            return isset($post->excerpt) ? $post->excerpt : self::get_the_excerpt($post);
        }
        public static function get_post_thumbnail($post) {
            return isset($post->thumb) ? $post->thumb : get_post_thumbnail_id($post);
        }
        public static function get_post_thumbnail_url( $post ) {
            return isset($post->image) ? $post->image : get_the_post_thumbnail_url($post);
        }
        public static function make_clean_vc_string($content, $count) {
            // hard remove if exists
            $shortcodes = array("vc_row", "vc_row_inner", "vc_column", "vc_column_inner", "vc_column_text" );
            foreach($shortcodes as $sc) {
                $content = preg_replace("/\[[\/]?".$sc."(.*?)\]/", "", $content);
            }
            // crawl templates
            $shortcodes = helper::get_shortcodes($content, array( 'dynamic' ));
            if ($shortcodes) {
                // debug($shortcodes);
                foreach ($shortcodes as $shortcode) {
                    if ($shortcode['atts'] != "") {
                        $slug = "";
                        $dynamic_content = "";
                        foreach ($shortcode['atts'] as $att) {
                            if ($att['key'] == 'template') {
                                $slug = $att['value'];
                            }
                            if ($att['key'] == 'dynamic_content') {
                                $dynamic_content = $att['value'];
                            }
                        }
                        if ($slug != "") {
                            $template = \dynamic::get_template($slug);
                            if ($template && count($template) > 0 && isset($template[0]->post_content)) {
                                $c = $template[0]->post_content;
                                if ($dynamic_content != "") {
                                    $dynamic_values = explode('::', $dynamic_content);
                                    if ($dynamic_values[0] == $slug && count($dynamic_values) > 1) {
                                        $c = \dynamic::content_match_dynamic($dynamic_values, $c);
                                    }
                                }
                                $template_content = helper::make_clean_vc_string($c, -1);
                                $content = str_replace($shortcode['raw'], $template_content, $content);
                            }
                        }
                    }
                }
            }
            // clean string
            $content = self::strip_all_tags_and_shortcodes($content);
            if ($count > -1) {
                // debug($content);
                $points = ($count < strlen($content)) ? apply_filters('excerpt_more', ' &#91;&hellip;&#93;') : "";
                $content = mb_substr($content, 0, $count).$points;
            }
            return $content;
        }
        public static function make_content_string($post, $atts) {
            if ( !is_object($post) || empty($post) ) return null;
            $atts   = explode('|', $atts);
            $count  = isset($atts[1]) ? $atts[1] : "-1";
            $link   = isset($atts[2]) ? $atts[2] : "";
            // render the whole content
            if ($count == "-1") {
                if (has_blocks($post->post_content)) {
                    if (method_exists('\greyd\blocks\render', 'process_blocks_content'))
                        $content = \greyd\blocks\render::process_blocks_content(array( "template" => "" ), $post);
                    else if (method_exists('\greyd\blocks\dynamic\Render', 'process_blocks_content')) 
                        $content = \greyd\blocks\dynamic\Render::process_blocks_content(array( "template" => "" ), $post);
                    else if (method_exists('\Greyd\Dynamic\Render_Blocks', 'process_blocks_content'))
                        $content = \Greyd\Dynamic\Render_Blocks::process_blocks_content(array( "template" => "" ), $post);
                    else 
                        $content = do_blocks($post->post_content);
                }
                else $content = do_shortcode( shortcode_unautop($post->post_content) );
            }
            // render excerpt
            else {
                $content = helper::make_clean_vc_string($post->post_content, $count);
            }
            /**
             * Replace new lines in html code.
             * They would already be converted into a p-tag if inside a text-module.
             * Otherwise they would just create unwanted p-tags.
             */
            $content = preg_replace( '/(\r\n)+|\r+|\n+|\t+/', '', $content );
            
            if ($link == "1") {
                return "<a href='".self::get_post_permalink($post)."' title='".self::get_post_title($post)."'>".$content."</a>";
            }
            return $content;
        }
        public static function make_author_string($post, $atts) {
            if ( !is_object($post) || empty($post) ) return null;
            $atts   = explode('|', $atts);
            $link   = isset($atts[1]) ? $atts[1] : "";
            $author = isset($post->author) ? $post->author : get_the_author_meta('display_name', $post->post_author);
            $url    = isset($post->author_url) ? $post->author_url : get_author_posts_url(get_the_author_meta('ID', $post->post_author));
            if ($link == "1") 
                return "<a href='".$url."' title='All Posts by &quot;".$author."&quot;'>".$author."</a>";
            else 
                return $author;
        }
        public static function make_authoremail_string($post, $atts) {
            if ( !is_object($post) || empty($post) ) return null;
            $atts = explode('|', $atts);
            $link = isset($atts[1]) ? $atts[1] : "";
            $email = get_the_author_meta('user_email', $post->post_author);
            if ($link == "1") 
                return "<a href='mailto:".$email."'>".$email."</a>";
            else 
                return $email;
        }
        public static function make_authorlink_string($post) {
            if ( !is_object($post) || empty($post) ) return null;
            return rawurlencode( isset($post->author_url) ? $post->author_url : get_author_posts_url(get_the_author_meta('ID', $post->post_author)) );
        }
        public static function make_date_string($post, $atts) {
            if ( !is_object($post) || empty($post) ) return null;
            $formats = array(
                ''      => get_option('date_format'),
                'dmY'   => 'd.m.Y',     // 'TT.MM.JJJJ'
                'dmy'   => 'd.m.y',     // 'TT.MM.JJ'
                'dm'    => 'd.m',       // 'TT.MM.'
                'ldmY'  => 'l d.m.Y',   // 'Tag TT.MM.JJJJ'
                'ldmy'  => 'l d.m.y',   // 'Tag TT.MM.JJ'
                'ldm'   => 'l d.m',     // 'Tag TT.MM.'
                'jFY'   => 'j. F Y',    // 'T. Monat JJJJ'
                'jFy'   => 'j. F y',    // 'T. Monat JJ'
                'jF'    => 'j. F',      // 'T. Monat'
                'ljFY'  => 'l j. F Y',  // 'Tag T. Monat JJJJ'
                'ljFy'  => 'l j. F y',  // 'Tag T. Monat JJ'
                'ljF'   => 'l j. F',    // 'Tag T. Monat'
                'mY'    => 'm.Y',       // 'MM.JJJJ'
                'my'    => 'm.y',       // 'MM.JJ'
                'm'     => 'm',         // 'MM'
                'FY'    => 'F Y',       // 'Monat JJJJ'
                'Fy'    => 'F y',       // 'Monat JJ'
                'F'     => 'F',         // 'Monat'
                'Y'     => 'Y',         // 'JJJJ'
                'y'     => 'y',         // 'JJ'
                'Gi'    => 'G:i',
                'His'   => 'H:i:s',
                'G'     => 'G',
                'm'     => 'i',
                's'     => 's',
            );
            $atts = explode('|', $atts);
            $format = isset($atts[1]) ? $atts[1] : '';
            return mysql2date($formats[$format], $post->post_date);
        }
        public static function make_filter_string($query, $atts) {
            if (isset($query->query)) $filter = $query->query;
            else {
                global $wp_query;
                // debug( $wp_query );
                $filter = isset($wp_query->query) ? $wp_query->query : [];
                if ( isset( $wp_query->query_vars['post_type'] ) ) $filter['post_type'] = $wp_query->query_vars['post_type'];
                unset($filter['s']);
            }
            
            $return = [];
            foreach ($filter as $key => $val) {
                if ( $key === 'post_type' ) {
                    $label = strpos($val, ",") !== false || $val === 'any' || empty($val) ? __('Beitragstypen', 'core') : __('Beitragstyp', 'core');
                    
                    
                    if ( $val === 'any' || empty($val) ) {
                        $val = __("alle", 'core');
                    } else {
                        $val = explode(",", $val);
                        foreach ( $val as $i => $slug ) {
                            $posttype = get_post_type_object($slug);
                            if ( $posttype ) $val[$i] = $posttype->labels->name;
                        }
                        $val = implode(", ", $val);
                    }
                    $return[] = $label.": ".$val;
                }
                else if ( $tax = get_taxonomy($key) ) {
                    $label = strpos($val, ",") !== false || empty($val) ? $tax->label : $tax->labels->singular_name;
                    
                    if ( empty($val) ) {
                        $val = __("alle", 'core');
                    } else {
                        $val = explode(",", $val);
                        foreach ( $val as $i => $slug ) {
                            $term = get_term_by('slug', $slug, $tax->name);
                            if ( $term ) $val[$i] = $term->name;
                        }
                        $val = implode(", ", $val);
                    }
                    $return[] = $label.": ".$val;
                }
            }
            return implode(" – ", $return);
        }
        public static function get_post_views($post) {
            if ( !is_object($post) || empty($post) ) return null;
            return isset($post->postviews) ? $post->postviews : get_post_meta($post->ID, 'postviews_count', true);
        }
        public static function get_site_title($post) {
            return isset($post->site_title) ? $post->site_title : get_bloginfo('name');
        }
        public static function get_site_url($post) {
            return isset($post->site_url) ? $post->site_url : get_site_url();
        }
        public static function get_site_logo($post) {
            return intval( get_theme_mod( 'custom_logo', -1 ) );
        }
        
        public static function make_woo_price($post, $atts) {

            if ( !function_exists('wc_get_product') ) return null;
            if ( !is_object($post) || empty($post) ) return null;

            $product = wc_get_product($post->ID);
            if ( is_a($product, 'WC_Product')  ) {
                $price = number_format(wc_get_price_to_display($product), 2, ',', '');
                $symbol = get_woocommerce_currency_symbol();
                if ($atts != "" && $atts != "||") {
                    $atts = explode('|', $atts);
                    $sympos = isset($atts[1]) ? $atts[1] : '';
                    $format = isset($atts[2]) ? $atts[2] : '';
                    if ($format == 'none') {
                        $price = explode(',', $price);
                        $price = $price[0];
                    }
                    if ($sympos == 'after') return $price." ".$symbol;
                    if ($sympos == 'before') return $symbol." ".$price;
                    if ($sympos == 'afterh') return $price." <sup>".$symbol."</sup>";
                    if ($sympos == 'beforeh') return "<sup>".$symbol."</sup> ".$price;
                    if ($sympos == 'hide') return $price;
                }
                return sprintf(get_woocommerce_price_format(), $symbol, $price);
            } else return NULL;
        }
        public static function make_woo_vat($post, $atts) {

            if ( !function_exists('wc_get_product') ) return null;

            $product = wc_get_product($post->ID);
            
            if ( is_a($product, 'WC_Product') ) {

                // get Tax info:
                $tax_info = "0";
                $tax_rate = \WC_Tax::get_rates($product->get_tax_class());
                
                if (!empty($tax_rate)) {
                    $tax_rate = reset($tax_rate);
                    $tax_info = (int)$tax_rate['rate']." %";
                }
                
                // wc germanized
                // if (wc_gzd_get_gzd_product($product)->get_tax_info())
                //     $tax_info = wc_gzd_get_gzd_product($product)->get_tax_info();
                // else if (get_option('woocommerce_gzd_small_enterprise') == 'yes')
                //     $tax_info = wc_gzd_get_small_business_product_notice();
                return $tax_info;
            } else return NULL;
        }
        public static function make_woo_cart($post, $atts) {

            if ( !function_exists('wc_get_product') ) return null;
            if ( !is_object($post) || empty($post) ) return null;

            if ( is_a($product, 'WC_Product')  ) {
                $product = wc_get_product($post->ID);
                return esc_url($product->add_to_cart_url()); 
            } else return NULL;
        }
        public static function make_woo_cart_excerpt($post, $atts) {

            if ( !function_exists('wc_get_product') ) return null;
            if ( !is_object($post) || empty($post) ) return null;

            $product = wc_get_product($post->ID);
            if ( is_a($product, 'WC_Product')  ) {
                return wc_gzd_get_gzd_product($product)->get_mini_desc();
            } else return NULL;
        }
        public static function make_ajax_link($post, $atts) {
            if ( !is_object($post) || empty($post) ) return null;
            // $atts = explode('|', $atts);
            // $atts[0] = $atts[0].'='.$post->ID;
            // $atts = implode('|', $atts);
            // return $atts;
            return '_woo_ajax='.$post->ID.$atts.'_';
        }

        public static function make_categories_string($post, $atts) {
            $categories = isset($post->categories) ? $post->categories : helper::get_categories($post);
            return helper::make_terms_string($categories, $atts);
        }
        public static function get_categories($post) {
            if ( !is_object($post) || empty($post) ) return array();
            if ($post->post_type == 'post') $slug = 'category';
            else if ($post->post_type == 'product') $slug = 'product_cat';
            else $slug = $post->post_type.'_category';

            /** @since 1.3.0 */
            $terms = self::get_post_taxonomy_terms($post->ID, $slug);

            if (is_array($terms)) $terms = array_unique($terms, SORT_REGULAR); 
            return $terms;
            // return wp_get_object_terms($post->ID, $slug);
        }
        public static function make_tags_string($post, $atts) {
            $tags = isset($post->tags) ? $post->tags : helper::get_tags($post);
            return helper::make_terms_string($tags, $atts);
        }
        public static function get_tags($post) {
            $slug = $post->post_type.'_tag';

            /** @since 1.3.0 */
            $terms = self::get_post_taxonomy_terms($post->ID, $slug);
            
            if (is_array($terms)) $terms = array_unique($terms, SORT_REGULAR); 
            return $terms;
            // return wp_get_object_terms($post->ID, $slug);
        }
        public static function make_custom_taxonomy_string($post, $atts, $tag) {
            $tax_name   = self::solve_customtaxs_dtag($tag, $post->post_type);
            $terms      = wp_get_post_terms($post->ID, $tax_name);
            return helper::make_terms_string($terms, $atts);
        }
        public static function make_customtaxs_dtag($tax_name, $posttype) {
            return "customtax-".str_replace( $posttype."_", "", $tax_name );
        }
        public static function solve_customtaxs_dtag($dtag, $posttype) {
            return $posttype."_".str_replace( "customtax-", "", $dtag );
        }
        public static function make_terms_string($terms, $atts) {
            // debug($terms);
            $seperators = array(
                '' => ', ',
                'semi'  => '; ',
                'vert'  => ' | ',
                'hor'   => ' - ',
                'dot'   => ' • ',
                'space' => ' ',
                'br'    => '<br/>',
            );
            $atts = explode('|', $atts);
            $sep = isset($atts[1]) ? $atts[1] : '';
            $link = isset($atts[2]) ? $atts[2] : '';
            $result = "";
            if (is_array($terms)) {
                foreach ($terms as $term) {
                    if ($result != "") $result .= isset($seperators[$sep]) ? $seperators[$sep] : $seperators[''];
                    // debug($term);
                    $title = $term->name;
                    $url = get_term_link($term->slug, $term->taxonomy);
                    if ( $link == "1" && !is_wp_error( $url ) ) {
                        $result .= "<a href='".$url."' title='Alle &quot;".$title."&quot;'>".$title."</a>";
                    } else {
                        $result .= $title;
                    }
                }
            }
            return $result;
        }
        public static function make_imagelink_string($post) {
            return rawurlencode( isset($post->image) ? $post->image : get_the_post_thumbnail_url($post) );
        }
        
        public static function make_posttype_string($query, $atts) {
            // debug($query);
            $posttype = "alle";
            if ($query->query_vars['post_type'] != "any") {
                if ($query->query_vars['post_type'] != "") {
                    $posttype = get_post_type_object($query->query_vars['post_type'])->label;
                }
                else if (get_post_type() != "") {
                    $posttype = get_post_type_object(get_post_type())->label;
                }
            }
            return $posttype;
        }
        public static function make_category_string($query, $atts) {
            $category = "alle";
            if ($query->query_vars['cat'] > 0) {
                $category = get_cat_name($query->query_vars['cat']);
            }
            else {
                if (isset($query->queried_object) && isset($query->queried_object->taxonomy)) {
                    if (strpos($query->queried_object->taxonomy, '_category') > 0 ||
                        strpos($query->queried_object->taxonomy, '_cat') > 0) {
                        $category = $query->queried_object->name;
                    }
                }
            }
            return $category;
        }
        public static function make_tag_string($query, $atts) {
            $tag = "alle";
            if ($query->query_vars['tag_id'] > 0) {
                $tag = get_tag($query->query_vars['tag_id'])->name;
            }
            else {
                if (isset($query->queried_object) && isset($query->queried_object->taxonomy)) {
                    if (strpos($query->queried_object->taxonomy, '_tag') > 0) {
                        $tag = $query->queried_object->name;
                    }
                }
            }
            return $tag;
        }
        
        public static function custom_ajax_add_to_cart_button($sets) {
            $id = isset($sets['id']) ? esc_attr($sets['id']) : 0;
            // Exit when no Product ID or if not a Product
            $product = wc_get_product($id);
            if ($id == 0 || get_post_type($id) != 'product' || !$product) return "";

            // params
            $qty = isset($sets['qty']) ? esc_attr($sets['qty']) : 1;
            $text = isset($sets['text']) ? $sets['text'] : $product->add_to_cart_text();
            $class = isset($sets['class']) ? esc_attr($sets['class']) : '';
            $style = isset($sets['style']) ? $sets['style'] : '';
            // make classes
            $classes = implode( ' ', array_filter(array(
                'product_type_' . $product->get_type(),
                $product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '',
                $product->supports( 'ajax_add_to_cart' ) ? 'ajax_add_to_cart' : '',
            )) ).' '.$class;
            // make button
            $add_to_cart_button = '<a rel="nofollow" 
                                    href="'.esc_url($product->add_to_cart_url()).'" 
                                    data-quantity="'.$qty.'" 
                                    data-product_id="'.$id.'" 
                                    data-product_sku="'.esc_attr($product->get_sku()).'" 
                                    class="'.$classes.'" 
                                    style="'.$style.'">'.$text.' </a>';
            return $add_to_cart_button;
        }
        public static function get_dynamic_woocommerce_hooks() {
            $hooks = [
                'woocommerce_account_dashboard'                 => __('Dashboard (unten)', 'core'),
                'woocommerce_before_account_orders'             => __('Bestellungen (oben)', 'core'),
                'woocommerce_after_account_orders'              => __('Bestellungen (unten)', 'core'),
                'woocommerce_before_account_downloads'          => __('Downloads (oben)', 'core'),
                'woocommerce_after_account_downloads'           => __('Downloads (unten)', 'core'),
                'woocommerce_before_edit_account_address_form'  => __('Adressen (oben)', 'core'),
                'woocommerce_after_edit_account_address_form'   => __('Adressen (unten)', 'core'),
                'woocommerce_before_account_payment_methods'    => __('Zahlungsmethoden (oben)', 'core'),
                'woocommerce_after_account_payment_methods'     => __('Zahlungsmethoden (unten)', 'core'),
                'woocommerce_before_edit_account_form'          => __('Konto Details (oben)', 'core'),
                'woocommerce_after_edit_account_form'           => __('Konto Details (unten)', 'core'),
                'woocommerce_before_thankyou'                   => __('Danke Seite (oben)', 'core')
            ];
            $hooks = apply_filters('greyd_dynamic_woocommerce_hooks', $hooks);
            return $hooks;
        }

        /**
         * Retrieves the terms of the taxonomy that are attached to the post.
         *
         * @since 1.3.0
         * Usually we would use the core function get_the_terms(). However it sometimes returns
         * terms of completely different taxonomies - without returning an error. To retrieve the
         * terms directly from the database seems to work more consistent in those cases.
         * 
         * @see get_the_terms()
         * @see https://developer.wordpress.org/reference/functions/get_the_terms/
         * 
         * @see this function was copied from greyd_tp_management/inc/post_export.php
         *
         * @param int       $post_id    Post ID.
         * @param string    $taxonomy   Taxonomy name.
         * @return WP_Term[]|null       Array of WP_Term objects on success, null if there are no terms
         *                              or the post does not exist.
         */
        public static function get_post_taxonomy_terms( $post_id, string $taxonomy ) {
    
            if ( !is_numeric($post_id) || !is_string($taxonomy) ) return null;
    
            global $wpdb;
            $results = $wpdb->get_results("
                SELECT {$wpdb->terms}.term_id, name, slug, term_group, {$wpdb->term_relationships}.term_taxonomy_id, taxonomy, description, parent, count FROM {$wpdb->terms}
                    LEFT JOIN {$wpdb->term_relationships} ON
                        ({$wpdb->terms}.term_id = {$wpdb->term_relationships}.term_taxonomy_id)
                    LEFT JOIN {$wpdb->term_taxonomy} ON
                        ({$wpdb->term_relationships}.term_taxonomy_id = {$wpdb->term_taxonomy}.term_taxonomy_id)
                WHERE {$wpdb->term_relationships}.object_id = {$post_id}
                    AND {$wpdb->term_taxonomy}.taxonomy = '{$taxonomy}'
            ");
            if ( $results && is_array($results) && count($results) ) {
                return array_map(function($term) {
                    return new \WP_Term( $term );
                }, $results);
            }
            return null;
        }
 
        /*
            plugin helpers
        */
        public static function active_plugins() {
            $plugins = get_option('active_plugins');
            if (is_multisite()) {
                $plugins_multi = get_site_option('active_sitewide_plugins');
                foreach ($plugins_multi as $key => $value) $plugins[] = $key;
                $plugins = array_unique($plugins);
                sort($plugins);
            }
            return $plugins;
        }
        public static function is_active_plugin($file) {
            // check for active plugins
            $plugins = helper::active_plugins();
            $active = false;
            if (in_array($file, $plugins)) $active = true;
            return $active;
        }
        public static function remove_vc_plugin_elements() {
            if (!is_callable('vc_remove_element')) return;
            
            // remove deprecated elements
            vc_remove_element( "vc_empty_space" );
            vc_remove_element( "vc_gutenberg" );

            // check for active plugins
            $plugins = helper::active_plugins();

            if (in_array('newsletter/plugin.php', $plugins)) {
                vc_remove_element( "newsletter_vc" );
            }
            if (in_array('contact-form-7/wp-contact-form-7.php', $plugins)) {
                vc_remove_element( "contact-form-7" );
            }
            if (in_array('revslider/revslider.php', $plugins)) {
                vc_remove_element( "rev_slider_vc" );
                vc_remove_element( "rev_slider" );
            }
            if (in_array('Ultimate_VC_Addons/Ultimate_VC_Addons.php', $plugins)) {
                vc_remove_element( "ultimate_spacer" );
                vc_remove_element( "ult_buttons" );
                vc_remove_element( "ultimate_icon_list" );
                vc_remove_element( "just_icon" );
                vc_remove_element( "ult_animation_block" );
                vc_remove_element( "icon_counter" );
                vc_remove_element( "ultimate_google_map" );
                vc_remove_element( "ultimate_google_trends" );            
                vc_remove_element( "icon_timeline" );
                vc_remove_element( "bsf-info-box" );
                vc_remove_element( "info_list" );
                vc_remove_element( "ultimate_info_table" );
                vc_remove_element( "interactive_banner_2" );
                vc_remove_element( "interactive_banner" );
                vc_remove_element( "ultimate_pricing" );
                vc_remove_element( "ultimate_icons" );
                vc_remove_element( "ultimate_heading" );
                vc_remove_element( "ultimate_carousel" );
                vc_remove_element( "ult_countdown" );
                vc_remove_element( "ultimate_info_banner" );
                vc_remove_element( "swatch_container" );
                vc_remove_element( "ult_ihover" );
                vc_remove_element( "ult_hotspot" );
                vc_remove_element( "ult_content_box" );
                vc_remove_element( "ultimate_ctation" );
                vc_remove_element( "stat_counter" );
                vc_remove_element( "ultimate_video_banner" );
                vc_remove_element( "ult_dualbutton" );
                vc_remove_element( "ult_createlink" );
                vc_remove_element( "ultimate_img_separator" );
                vc_remove_element( "ult_tab_element" );
                vc_remove_element( "ultimate_exp_section" );
                vc_remove_element( "info_circle" );
                vc_remove_element( "ultimate_modal" );
                
                vc_remove_element( "ultimate_ribbon" );
                vc_remove_element( "ultimate_video" );
                vc_remove_element( "ult_sticky_section" );

                vc_remove_element( "ult_team" );
                vc_remove_element( "ultimate_fancytext" );
                vc_remove_element( "ult_range_slider" );
            }
            if (in_array('woocommerce/woocommerce.php', $plugins)) {
                $wc_el = array(
                    // woocommerce
                    'woocommerce_cart',
                    'woocommerce_checkout',
                    'woocommerce_order_tracking',
                    'woocommerce_my_account',
                    'recent_products',
                    'featured_products',
                    'product',
                    'products',
                    'add_to_cart',
                    'add_to_cart_url',
                    'product_page',
                    'product_category',
                    'product_categories',
                    'sale_products',
                    'best_selling_products',
                    'top_rated_products',
                    'product_attribute',
                    'related_products',
                    // woocommerce germanized
                    'payment_methods_info',
                    'gzd_complaints',
                    'revocation_form',
                    'gzd_vat_info',
                    'gzd_sale_info',
                    'woo_content',
                );
                foreach ($wc_el as $key => $value) {
                    vc_remove_element( $value );
                }
            }
            

        }

        /* 
            Icon in Buttons and links
        */

        /**
         * helper for visual composer 'vc_map' to define Icon in Buttons
         * 
         * $pre     param_name prefix for the Icon params
         * $dep_el  param_name of the dependant element
         * $dep_val value(s) of the dependant element
         * 
         * @return  array of params for visual composer module
         */
        public static function custom_icon_params_vc($pre, $dep_el=false, $dep_val=false, $group='') {
            // if ($pre != "" && !strpos($pre, "_")) $pre .= "_";
            if ($pre != "") $pre = trim($pre, "_")."_";  
            $dependency = array();
            if ($dep_el != false) {
                if ($dep_val == "not_empty")
                    $dependency = array( 'dependency'  => array(
                                            'element' => $dep_el,
                                            'not_empty' => true
                                        ) );
                else
                    $dependency = array( 'dependency'  => array(
                                            'element' => $dep_el,
                                            'value' => $dep_val
                                        ) );
            }
            return array(
                array_merge(
                    array(
                        "type"        => 'sub_seperator',
                        "group"       => $group,
                        "heading"     => __('Icon', 'core'),
                        "param_name"  => $pre.'seperator_icon',
                    ), $dependency
                ),
                // iconpicker
                array_merge(
                    array(
                        'type'        => 'iconpicker',
                        "group"       => $group,
                        'heading'     => __( 'Icon auswählen', 'core' ),
                        // 'description' => __( 'Select from Elegant Icons library.', 'core' ),
                        'param_name'  => $pre.'icon',
                        'edit_field_class' => 'vc_col-xs-6 vc_clearleft',
                        'settings'    => array(
                            'emptyIcon'    => true,
                            'type'         => 'elegant',
                            'iconsPerPage' => 4000,
                        ),
                    ), $dependency
                ),
                // new line
                array_merge(
                    array(
                        "type"        => 'new_line',
                        "group"       => $group,
                        "param_name"  => $pre.'new_line_after_icon',
                    ), $dependency
                ),
                // icon align
                array_merge(
                    
                    array(
                        "type"          => 'dropdown',
                        "group"       => $group,
                        "heading"       => __('Position', 'core'),
                        "param_name"    => $pre.'icon_align',
                        'edit_field_class' => 'vc_col-xs-4',
                        "value"         => array(
                            _x('rechts', 'small', 'core') => '',
                            _x('links', 'small', 'core') => 'left',
                        ),
                    ), $dependency
                ),
                array_merge(
                    array(
                        'type'          => 'textfield',
                        "group"       => $group,
                        'heading'       => __('Abstand zum Text', 'core'),
                        'description'   => __('in px', 'core'),
                        'param_name'    => $pre.'icon_margin',
                        'edit_field_class' => 'vc_col-xs-4',
                        'value'         => '10px',
                    ), $dependency
                ),
                array_merge(
                    array(
                        'type'          => 'textfield',
                        "group"       => $group,
                        'heading'       => __('Größe', 'core'),
                        'description'   => __('in %', 'core'),
                        'param_name'    => $pre.'icon_size',
                        'edit_field_class' => 'vc_col-xs-4',
                        'value'         => '100%',
                    ), $dependency
                )
            );
        }

        /**
         * helper for shortcode rendering Icon in Buttons
         * 
         * $atts    all shortcode atts
         * $pre     param_name prefix of the custom types
         * $content original Buttontext to append icon to
         * 
         * @return  string of Buttontext with icon
         */
        public static function make_custom_icon($atts, $pre, $content) {
            // if ($pre != "" && !strpos($pre, "_")) $pre .= "_";  
            if ($pre != "") $pre = trim($pre, "_")."_";  

            $sets = array();
            $sets['icon'] = isset($atts[$pre.'icon']) ? esc_attr($atts[$pre.'icon']) : '';
            $sets['icon_align'] = isset($atts[$pre.'icon_align']) ? esc_attr($atts[$pre.'icon_align']) : '';
            $sets['icon_margin'] = isset($atts[$pre.'icon_margin']) ? esc_attr($atts[$pre.'icon_margin']) : 10;
            $sets['icon_size'] = isset($atts[$pre.'icon_size']) ? esc_attr($atts[$pre.'icon_size']) : 100;
        
            if (!strpos($sets['icon_margin'], "px")) $sets['icon_margin'] = $sets['icon_margin']."px";
            if (!strpos($sets['icon_size'], "%")) $sets['icon_size'] = $sets['icon_size']."%";
            // debug($sets);

            if ($content == "" && $sets['icon'] == "") {
                // $sets['icon'] = "icon_search";
                return "<span>&nbsp;</span>";
            }

            if ($content == "") {
                $sets['icon_margin'] = "0px";
                $content = "<span>".$content."</span>";
            }
            else
                $content = "<span style='flex:1'>".$content."</span>";

            if ($sets['icon'] != '') {
                if ($sets['icon_align'] == "left")
                    $content = "<span style='margin-right:".$sets['icon_margin']."; font-size:".$sets['icon_size']."' aria-hidden='true' class='".$sets['icon']."'></span>".$content;
                else
                    $content = $content."<span style='margin-left:".$sets['icon_margin']."; font-size:".$sets['icon_size']."' aria-hidden='true' class='".$sets['icon']."'></span>";
            }

            return $content;
        }


        /* 
            custom styles 
        */

        /**
         * Helper for visual composer 'vc_map' to define custom styles
         * 
         * @param string $pre     param_name prefix for the custom types
         * @param string $dep_el  param_name of the dependant element
         * @param string $dep_val value(s) of the dependant element
         * @param string $group   value of the group
         * 
         * @return array params for vc_map()
         */
        public static function custom_element_params_vc($pre, $dep_el=false, $dep_val=false, $group='') {
            // if ($pre != "" && !strpos($pre, "_")) $pre .= "_";
            if ($pre != "") $pre = trim($pre, "_")."_";  
            $dependency = array();
            $group      = array('group' => $group);

            if ($dep_el != false) {
                if ($dep_val == "not_empty") {
                    $dependency = array( 'dependency' => array(
                        'element' => $dep_el,
                        'not_empty' => true
                    ) );
                }
                else {
                    $dependency = array( 'dependency' => array(
                        'element' => $dep_el,
                        'value' => $dep_val
                    ) );
                }
            }

            return array(
                array_merge(
                    array(
                        "type"        => 'new_line',
                        "param_name"  => $pre.'new_line_mode',
                    ), $dependency, $group
                ),
                // typo/size
                array_merge(  
                    array(
                        'type'          => 'textfield',
                        'heading'       => __('Schriftgröße', 'core'),
                        'description'   => __('in px oder %', 'core'),
                        'param_name'    => $pre.'font_size',
                        'edit_field_class' => 'vc_col-xs-2 vc_group_t',
                    ), $dependency, $group
                ),
                array_merge(  
                    array(
                        "type"          => "dropdown",
                        "heading"       => __('Schriftschnitt', 'core'),
                        "param_name"    => $pre.'font_weight',
                        'edit_field_class' => 'vc_col-xs-2 vc_group_t',
                        "value"		  	=> array(
                            _x('Standard', 'small', 'core') => '',
                            __('100 - extra thin', 'core') => '100',
                            __('300 - light', 'core') => '300',
                            __('400 - regular', 'core') => '400',
                            __('600 - semi-bold', 'core') => '600',
                            __('700 - bold', 'core') => '700',
                        )
                    ), $dependency, $group
                ),
                array_merge(
                    array(
                        'type'          => 'textfield',
                        'heading'       => __('Zeilenhöhe', 'core'),
                        'description'   => __('in px oder %', 'core'),
                        'param_name'    => $pre.'line_height',
                        'edit_field_class' => 'vc_col-xs-2 vc_group_t',
                    ), $dependency, $group
                ),
                array_merge(
                    array(
                        'type'          => 'textfield',
                        'heading'       => __('Padding', 'core').'&nbsp;<u>'.__('oben/unten', 'core').'</u>',
                        'description'   => __('in px', 'core'),
                        'param_name'    => $pre.'padding_top',
                        'edit_field_class' => 'vc_col-xs-3 vc_group_t',
                    ), $dependency, $group
                ),
                array_merge(
                    array(
                        'type'          => 'textfield',
                        'heading'       => __('Padding', 'core').'&nbsp;<u>'.__('seitlich', 'core').'</u>',
                        'description'   => __('in px', 'core'),
                        'param_name'    => $pre.'padding_right',
                        'edit_field_class' => 'vc_col-xs-3 vc_group_tr',
                    ), $dependency, $group
                ),
                // colors
                array_merge(
                    array(
                        'type'        => 'colorselect',
                        'heading'     => __('Hintergrundfarbe', 'core'),
                        'param_name'  => $pre.'background',
                        'edit_field_class' => 'vc_col-xs-4 vc_group_l vc_clearleft',
                    ), $dependency, $group
                ),
                array_merge(
                    array(
                        'type'        => 'colorselect',
                        'heading'     => __('Schriftfarbe', 'core'),
                        'param_name'  => $pre.'color',
                        'edit_field_class' => 'vc_col-xs-4 vc_group_m',
                    ), $dependency, $group
                ),
                array_merge(
                    array(
                        'type'          => 'colorselect',
                        'heading'       => __('Rahmenfarbe', 'core'),
                        'param_name'    => $pre.'border',
                        'edit_field_class' => 'vc_col-xs-4 vc_group_r',
                    ), $dependency, $group
                ),
                // colors hover
                array_merge(
                    array(
                        'type'        => 'colorselect',
                        'heading'     => __('Hintergrundfarbe', 'core').'&nbsp;<u>'.__('Hover', 'core').'</u>',
                        'param_name'  => $pre.'background_hover',
                        'edit_field_class' => 'vc_col-xs-4 vc_group_l vc_clearleft',
                    ), $dependency, $group
                ),
                array_merge(
                    array(
                        'type'        => 'colorselect',
                        'heading'     => __('Schriftfarbe', 'core').'&nbsp;<u>'.__('Hover', 'core').'</u>',
                        'param_name'  => $pre.'color_hover',
                        'edit_field_class' => 'vc_col-xs-4 vc_group_m',
                    ), $dependency, $group
                ),
                array_merge(
                    array(
                        'type'          => 'colorselect',
                        'heading'       => __('Rahmenfarbe', 'core').'&nbsp;<u>'.__('Hover', 'core').'</u>',
                        'param_name'    => $pre.'border_hover',
                        'edit_field_class' => 'vc_col-xs-4 vc_group_r',
                    ), $dependency, $group
                ),
                // border
                array_merge(
                    array(
                        'type'          => 'textfield',
                        'heading'       => __('Eckenradius', 'core'),
                        'description'   => __('in px', 'core'),
                        'param_name'    => $pre.'border_radius',
                        'edit_field_class' => 'vc_col-xs-2 vc_clearleft',
                    ), $dependency, $group
                ),
                array_merge(
                    array(
                        'type'          => 'textfield',
                        'heading'       => __('Rahmenbreite', 'core'),
                        'description'   => __('in px', 'core'),
                        'param_name'    => $pre.'border_width',
                        'edit_field_class' => 'vc_col-xs-2',
                    ), $dependency, $group
                ),
                array_merge(
                    array(
                        'type'          => 'dropdown',
                        'heading'       => __('Rahmen', 'core').'&nbsp;<u>'.__('links', 'core').'</u>',
                        'param_name'    => $pre.'border_left',
                        'value'         => helper::get_border_styles(true),
                        "std"           => 'none',
                        'edit_field_class' => 'vc_col-xs-2',
                    ), $dependency, $group
                ),
                array_merge(
                    array(
                        'type'          => 'dropdown',
                        'heading'       => __('Rahmen', 'core').'&nbsp;<u>'.__('oben', 'core').'</u>',
                        'param_name'    => $pre.'border_top',
                        'value'         => helper::get_border_styles(true),
                        "std"           => 'none',
                        'edit_field_class' => 'vc_col-xs-2 ',
                    ), $dependency, $group
                ),
                array_merge(
                    array(
                        'type'          => 'dropdown',
                        'heading'       => __('Rahmen', 'core').'&nbsp;<u>'.__('rechts', 'core').'</u>',
                        'param_name'    => $pre.'border_right',
                        'value'         => helper::get_border_styles(true),
                        "std"           => 'none',
                        'edit_field_class' => 'vc_col-xs-2',
                    ), $dependency, $group
                ),
                array_merge(
                    array(
                        'type'          => 'dropdown',
                        'heading'       => __('Rahmen', 'core').'&nbsp;<u>'.__('unten', 'core').'</u>',
                        'param_name'    => $pre.'border_bottom',
                        'value'         => helper::get_border_styles(true),
                        "std"           => 'none',
                        'edit_field_class' => 'vc_col-xs-2',
                    ), $dependency, $group
                ),
                array_merge(
                    array(
                        'type'          => 'shadow',
                        'heading'       => __('Schlagschatten', 'core'),
                        'param_name'    => $pre.'shadow',
                        'value'         => 'none',
                        'edit_field_class' => 'vc_col-xs-12',
                    ), $dependency, $group
                ),
                array_merge(
                    array(
                        'type'          => 'shadow',
                        'heading'       => __('Schlagschatten', 'core').'&nbsp;<u>'.__('Hover', 'core').'</u>',
                        'param_name'    => $pre.'shadow_hover',
                        'value'         => 'none',
                        'edit_field_class' => 'vc_col-xs-12 vc_group_b',
                    ), $dependency, $group
                ),
            );
        }

        public static function get_custom_element_setup($atts, $pre) {
            // if ($pre != "" && !strpos($pre, "_")) $pre .= "_";
            if ($pre != "") $pre = trim($pre, "_")."_";  

            // debug($atts);
            $sets = array();
            isset($atts[$pre.'font_size']) ? $sets[$pre.'font_size'] = esc_attr($atts[$pre.'font_size']) : null;
            isset($atts[$pre.'font_weight']) ? $sets[$pre.'font_weight'] = esc_attr($atts[$pre.'font_weight']) : null;
            isset($atts[$pre.'line_height']) ? $sets[$pre.'line_height'] = esc_attr($atts[$pre.'line_height']) : null;
            isset($atts[$pre.'padding_top']) ? $sets[$pre.'padding_top'] = esc_attr($atts[$pre.'padding_top']) : null;
            isset($atts[$pre.'padding_right']) ? $sets[$pre.'padding_right'] = esc_attr($atts[$pre.'padding_right']) : null;
            isset($atts[$pre.'color']) ? $sets[$pre.'color'] = helper::get_colorselect($atts, $pre.'color', '') : null;
            isset($atts[$pre.'background']) ? $sets[$pre.'background'] = helper::get_colorselect($atts, $pre.'background') : null;
            isset($atts[$pre.'border']) ? $sets[$pre.'border'] = helper::get_colorselect($atts, $pre.'border') : null;        
            isset($atts[$pre.'color_hover']) ? $sets[$pre.'color_hover'] = helper::get_colorselect($atts, $pre.'color_hover') : null;
            isset($atts[$pre.'background_hover']) ? $sets[$pre.'background_hover'] = helper::get_colorselect($atts, $pre.'background_hover') : null;
            isset($atts[$pre.'border_hover']) ? $sets[$pre.'border_hover'] = helper::get_colorselect($atts, $pre.'border_hover') : null;  
            isset($atts[$pre.'border_width']) ? $sets[$pre.'border_width'] = esc_attr($atts[$pre.'border_width']) : null;
            isset($atts[$pre.'border_radius']) ? $sets[$pre.'border_radius'] = esc_attr($atts[$pre.'border_radius']) : null;        
            isset($atts[$pre.'border_left']) ? $sets[$pre.'border_left'] = esc_attr($atts[$pre.'border_left']) : null;
            isset($atts[$pre.'border_top']) ? $sets[$pre.'border_top'] = esc_attr($atts[$pre.'border_top']) : null;
            isset($atts[$pre.'border_right']) ? $sets[$pre.'border_right'] = esc_attr($atts[$pre.'border_right']) : null;
            isset($atts[$pre.'border_bottom']) ? $sets[$pre.'border_bottom'] = esc_attr($atts[$pre.'border_bottom']) : null;
            isset($atts[$pre.'shadow']) ? $sets[$pre.'shadow'] = helper::get_shadow($atts, $pre.'shadow', 'none') : null;
            isset($atts[$pre.'shadow_hover']) ? $sets[$pre.'shadow_hover'] = helper::get_shadow($atts, $pre.'shadow_hover', 'none') : null;
            // debug($sets);

            return $sets;
        }

        /**
         * helper for shortcode rendering of Elements with custom styles
         * 
         * $atts    all shortcode atts
         * $pre     param_name prefix of the custom types
         * $css     original css-styles to append to
         * 
         * @return  string of custom css-styles with inline 'onMouseOver' and 'onMouseOut' js
         */
        public static function make_custom_element($atts, $pre, $css="") {
            // if ($pre != "" && !strpos($pre, "_")) $pre .= "_";  
            if ($pre != "") $pre = trim($pre, "_")."_";  

            // debug($atts);
            $sets = array();
            isset($atts[$pre.'font_size']) ? $sets['font_size'] = esc_attr($atts[$pre.'font_size']) : null;
            isset($atts[$pre.'font_weight']) ? $sets['font_weight'] = esc_attr($atts[$pre.'font_weight']) : null;
            isset($atts[$pre.'line_height']) ? $sets['line_height'] = esc_attr($atts[$pre.'line_height']) : null;
            isset($atts[$pre.'padding_top']) ? $sets['padding_top'] = esc_attr($atts[$pre.'padding_top']) : null;
            isset($atts[$pre.'padding_right']) ? $sets['padding_right'] = esc_attr($atts[$pre.'padding_right']) : null;   
            isset($atts[$pre.'color']) ? $sets['color'] = helper::get_colorselect($atts, $pre.'color', '') : null;
            isset($atts[$pre.'background']) ? $sets['background'] = helper::get_colorselect($atts, $pre.'background') : null;
            isset($atts[$pre.'border']) ? $sets['border'] = helper::get_colorselect($atts, $pre.'border') : null;        
            isset($atts[$pre.'color_hover']) ? $sets['color_hover'] = helper::get_colorselect($atts, $pre.'color_hover') : null;
            isset($atts[$pre.'background_hover']) ? $sets['background_hover'] = helper::get_colorselect($atts, $pre.'background_hover') : null;
            isset($atts[$pre.'border_hover']) ? $sets['border_hover'] = helper::get_colorselect($atts, $pre.'border_hover') : null;     
            isset($atts[$pre.'border_width']) ? $sets['border_width'] = esc_attr($atts[$pre.'border_width']) : null;
            isset($atts[$pre.'border_radius']) ? $sets['border_radius'] = esc_attr($atts[$pre.'border_radius']) : null;        
            isset($atts[$pre.'border_left']) ? $sets['border_left'] = esc_attr($atts[$pre.'border_left']) : null;
            isset($atts[$pre.'border_top']) ? $sets['border_top'] = esc_attr($atts[$pre.'border_top']) : null;
            isset($atts[$pre.'border_right']) ? $sets['border_right'] = esc_attr($atts[$pre.'border_right']) : null;
            isset($atts[$pre.'border_bottom']) ? $sets['border_bottom'] = esc_attr($atts[$pre.'border_bottom']) : null;
            isset($atts[$pre.'shadow']) ? $sets['shadow'] = helper::get_shadow($atts, $pre.'shadow', 'none') : null;
            isset($atts[$pre.'shadow_hover']) ? $sets['shadow_hover'] = helper::get_shadow($atts, $pre.'shadow_hover', 'none') : null;
            // debug($sets);

            $css = $css."text-decoration:none;";
            $style = $css;
            $normal_js = "this.setAttribute( \"style\", \"".$css;
            $hover_js = "this.setAttribute( \"style\", \"".$css; 

            if (isset($sets['font_size'])) {
                if (!strpos($sets['font_size'], '%') && !strpos($sets['font_size'], 'px') ) $sets['font_size'] .= "%";
                $style .= "font-size: ".$sets['font_size']." !important; ";
                $normal_js .= "font-size: ".$sets['font_size']." !important; ";
                $hover_js .= "font-size: ".$sets['font_size']." !important; ";
            }
            if (isset($sets['font_weight'])) {
                $style .= "font-weight: ".$sets['font_weight']." !important; ";
                $normal_js .= "font-weight: ".$sets['font_weight']." !important; ";
                $hover_js .= "font-weight: ".$sets['font_weight']." !important; ";
            }
            if (isset($sets['line_height'])) {
                if (!strpos($sets['line_height'], '%') && !strpos($sets['line_height'], 'px') ) $sets['line_height'] .= "%";
                $style .= "line-height: ".$sets['line_height']." !important; ";
                $normal_js .= "line-height: ".$sets['line_height']." !important; ";
                $hover_js .= "line-height: ".$sets['line_height']." !important; ";
            }
            if (isset($sets['padding_top'])) {
                if (!strpos($sets['padding_top'], 'px') ) $sets['padding_top'] .= "px";
                $style .= "padding-top: ".$sets['padding_top']." !important; padding-bottom: ".$sets['padding_top']." !important; ";
                $normal_js .= "padding-top: ".$sets['padding_top']." !important; padding-bottom: ".$sets['padding_top']." !important; ";
                $hover_js .= "padding-top: ".$sets['padding_top']." !important; padding-bottom: ".$sets['padding_top']." !important; ";
            }
            if (isset($sets['padding_right'])) {
                if (!strpos($sets['padding_right'], 'px') ) $sets['padding_right'] .= "px";
                $style .= "padding-right: ".$sets['padding_right']." !important; padding-left: ".$sets['padding_right']." !important; ";
                $normal_js .= "padding-right: ".$sets['padding_right']." !important; padding-left: ".$sets['padding_right']." !important; ";
                $hover_js .= "padding-right: ".$sets['padding_right']." !important; padding-left: ".$sets['padding_right']." !important; ";
            }

            if (isset($sets['border_width'])) {
                if (!strpos($sets['border_width'], 'px') ) $sets['border_width'] .= "px";
                $style .= "border-width: ".$sets['border_width']." !important; ";
                $normal_js .= "border-width: ".$sets['border_width']." !important; ";
                $hover_js .= "border-width: ".$sets['border_width']." !important; ";
            }
            if (isset($sets['border_radius'])) {
                if (!strpos($sets['border_radius'], 'px') ) $sets['border_radius'] .= "px";
                $style .= "border-radius: ".$sets['border_radius']." !important; ";
                $normal_js .= "border-radius: ".$sets['border_radius']." !important; ";
                $hover_js .= "border-radius: ".$sets['border_radius']." !important; ";
            }
            if (isset($sets['border_left'])) {
                $style .= "border-left-style: ".$sets['border_left']." !important; ";
                $normal_js .= "border-left-style: ".$sets['border_left']." !important; ";
                $hover_js .= "border-left-style: ".$sets['border_left']." !important; ";
            }
            if (isset($sets['border_top'])) {
                $style .= "border-top-style: ".$sets['border_top']." !important; ";
                $normal_js .= "border-top-style: ".$sets['border_top']." !important; ";
                $hover_js .= "border-top-style: ".$sets['border_top']." !important; ";
            }
            if (isset($sets['border_right'])) {
                $style .= "border-right-style: ".$sets['border_right']." !important; ";
                $normal_js .= "border-right-style: ".$sets['border_right']." !important; ";
                $hover_js .= "border-right-style: ".$sets['border_right']." !important; ";
            }
            if (isset($sets['border_bottom'])) {
                $style .= "border-bottom-style: ".$sets['border_bottom']." !important; ";
                $normal_js .= "border-bottom-style: ".$sets['border_bottom']." !important; ";
                $hover_js .= "border-bottom-style: ".$sets['border_bottom']." !important; ";
            }
            
            if (isset($sets['color'])) {
                $style .= "color: ".$sets['color']." !important; ";
                $normal_js .= "color: ".$sets['color']." !important; ";
            }
            if (isset($sets['background'])) {
                $style .= "background: ".$sets['background']." !important; ";
                $normal_js .= "background: ".$sets['background']." !important; ";
            }
            if (isset($sets['border'])) {
                $style .= "border-color: ".$sets['border']." !important; ";
                $normal_js .= "border-color: ".$sets['border']." !important; ";
            }
            if (isset($sets['shadow'])) {
                $style .= "box-shadow: ".$sets['shadow']." !important; ";
                $normal_js .= "box-shadow: ".$sets['shadow']." !important; ";
                if (!isset($sets['shadow_hover']))
                    $hover_js .= "box-shadow: ".$sets['shadow']." !important; ";
            }
            if (isset($sets['shadow_hover'])) $hover_js .= "box-shadow: ".$sets['shadow_hover']." !important; ";

            if (isset($sets['color_hover'])) $hover_js .= "color: ".$sets['color_hover']." !important; ";
            if (isset($sets['background_hover'])) $hover_js .= "background: ".$sets['background_hover']." !important; ";
            if (isset($sets['border_hover'])) $hover_js .= "border-color: ".$sets['border_hover']." !important; ";

            $normal_js .= "\" );";
            $hover_js .= "\" );";

            // debug($style);
            // debug($normal_js);
            // debug($hover_js);
            // debug($style."' onmouseenter='".$hover_js."' onmouseleave='".$normal_js);
            return $style."' onmouseenter='".$hover_js."' onmouseleave='".$normal_js;
        }

        /*
            border params
        */
        public static function border_params_vc($pre, $group, $hover=true, $dep_el=false, $dep_val=false) {
            if ($pre != "") $pre = trim($pre, "_")."_";  
            $dependency = array();
            if ($dep_el != false) {
                if ($dep_val == "not_empty")
                    $dependency = array( 'dependency'  => array(
                                            'element' => $dep_el,
                                            'not_empty' => true
                                        ) );
                else
                    $dependency = array( 'dependency'  => array(
                                            'element' => $dep_el,
                                            'value' => $dep_val
                                        ) );
            }

            $border_params = array(
                // border color
                array_merge(
                    array(
                        "group"         => $group,
                        "type"          => "colorselect",
                        "heading"       => __('Farbe', 'core'),
                        "param_name"    => $pre."border_colorselect",
                        // "value"         => 'color_61',
                        'edit_field_class' => 'vc_col-xs-6',
                    ), $dependency
                ),
                // border settings
                array_merge(
                    array(
                        "group"         => $group,
                        "type"        => 'new_line',
                        "param_name"  => 'new_line_'.$pre.'border',
                    )
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'textfield',
                        'heading'       => __('Stärke', 'core'),
                        'description'   => __('in px', 'core'),
                        'param_name'    => $pre.'border_width',
                        "value"         => '1px',
                        'edit_field_class' => 'vc_col-xs-2',
                    ), $dependency
                ),
                // array_merge(
                //     array(
                //         "group"         => $group,
                //         'type'          => 'textfield',
                //         'heading'       => __('Eckenradius', 'core'),
                //         'description'   => __('in px', 'core'),
                //         'param_name'    => $pre.'border_radius',
                //         "value"         => '0px',
                //         'edit_field_class' => 'vc_col-xs-2',
                //     ), $dependency
                // ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'dropdown',
                        'heading'       => __('Rahmen', 'core').' <u>'.__('links', 'core').'</u>',
                        'param_name'    => $pre.'border_left',
                        'value'         => helper::get_border_styles(),
                        'edit_field_class' => 'vc_col-xs-2',
                    ), $dependency
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'dropdown',
                        'heading'       => __('Rahmen', 'core').' <u>'.__('oben', 'core').'</u>',
                        'param_name'    => $pre.'border_top',
                        'value'         => helper::get_border_styles(),
                        'edit_field_class' => 'vc_col-xs-2',
                    ), $dependency
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'dropdown',
                        'heading'       => __('Rahmen', 'core').' <u>'.__('rechts', 'core').'</u>',
                        'param_name'    => $pre.'border_right',
                        'value'         => helper::get_border_styles(),
                        'edit_field_class' => 'vc_col-xs-2',
                    ), $dependency
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'dropdown',
                        'heading'       => __('Rahmen', 'core').' <u>'.__('unten', 'core').'</u>',
                        'param_name'    => $pre.'border_bottom',
                        'value'         => helper::get_border_styles(),
                        'edit_field_class' => 'vc_col-xs-2',
                    ), $dependency
                ),
            );
            $border_hover_params = array(
                // border hover
                array_merge(
                    array(
                        "group"         => $group,
                        "type"        => 'sub_seperator',
                        "heading"     => __('Hover', 'core'),
                        "param_name"  => 'sub_seperator_'.$pre.'border_hover',
                    ), $dependency
                ),
                // border hover color
                array_merge(
                    array(
                        "group"         => $group,
                        "type"          => "colorselect",
                        "heading"       => __('Farbe', 'core'),
                        "param_name"    => $pre."border_colorselect_hover",
                        // "value"         => 'color_61',
                        'edit_field_class' => 'vc_col-xs-6',
                    ), $dependency
                ),
                // border hover settings
                array_merge(
                    array(
                        "group"         => $group,
                        "type"        => 'new_line',
                        "param_name"  => 'new_line_'.$pre.'border',
                    )
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'textfield',
                        'heading'       => __('Stärke', 'core'),
                        'description'   => __('in px', 'core'),
                        'param_name'    => $pre.'border_width_hover',
                        "value"         => '1px',
                        'edit_field_class' => 'vc_col-xs-2',
                    ), $dependency
                ),
                // array_merge(
                //     array(
                //         "group"         => $group,
                //         'type'          => 'textfield',
                //         'heading'       => __('Eckenradius', 'core'),
                //         'description'   => __('in px', 'core'),
                //         'param_name'    => $pre.'border_radius_hover',
                //         "value"         => '0px',
                //         'edit_field_class' => 'vc_col-xs-2',
                //     ), $dependency
                // ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'dropdown',
                        'heading'       => __('Rahmen', 'core').' <u>'.__('links', 'core').'</u>',
                        'param_name'    => $pre.'border_left_hover',
                        'value'         => helper::get_border_styles(),
                        'edit_field_class' => 'vc_col-xs-2',
                    ), $dependency
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'dropdown',
                        'heading'       => __('Rahmen', 'core').' <u>'.__('oben', 'core').'</u>',
                        'param_name'    => $pre.'border_top_hover',
                        'value'         => helper::get_border_styles(),
                        'edit_field_class' => 'vc_col-xs-2',
                    ), $dependency
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'dropdown',
                        'heading'       => __('Rahmen', 'core').' <u>'.__('rechts', 'core').'</u>',
                        'param_name'    => $pre.'border_right_hover',
                        'value'         => helper::get_border_styles(),
                        'edit_field_class' => 'vc_col-xs-2',
                    ), $dependency
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'dropdown',
                        'heading'       => __('Rahmen', 'core').' <u>'.__('unten', 'core').'</u>',
                        'param_name'    => $pre.'border_bottom_hover',
                        'value'         => helper::get_border_styles(),
                        'edit_field_class' => 'vc_col-xs-2',
                    ), $dependency
                ),
            );

            if ($hover) return array_merge($border_params, $border_hover_params);
            else return $border_params;
        }
        public static function make_border($atts, $pre) {
            if ($pre != "") $pre = trim($pre, "_")."_";  
            
            $border = array(
                'normal' => "",
                'hover' => "",
            );

            // border-color
            $border_color = helper::get_color($atts, $pre.'border_', '', 'color_61');
            $border_color_hover = helper::get_color($atts, $pre.'border_', '_hover', 'color_61');
            $border['normal'] .= "border-color: ".$border_color.";";
            $border['hover'] .= "border-color: ".$border_color_hover.";";

            // border-width
            $border_width = $border_width_hover = "1px";
            if (isset($atts[$pre.'border_width']) && $atts[$pre.'border_width'] != "") $border_width = str_replace("px", "", $atts[$pre.'border_width'])."px";
            if (isset($atts[$pre.'border_width_hover']) && $atts[$pre.'border_width_hover'] != "") $border_width_hover = str_replace("px", "", $atts[$pre.'border_width_hover'])."px";
            $border['normal'] .= "border-width: ".$border_width."; ";
            $border['hover'] .= "border-width: ".$border_width_hover."; ";

            // // border-radius
            // $border_radius = $border_radius_hover = "0px";
            // if (isset($atts[$pre.'border_radius']) && $atts[$pre.'border_radius'] != "") $border_radius = str_replace("px", "", $atts[$pre.'border_radius'])."px";
            // if (isset($atts[$pre.'border_radius_hover']) && $atts[$pre.'border_radius_hover'] != "") $border_radius_hover = str_replace("px", "", $atts[$pre.'border_radius_hover'])."px";
            // $border['normal'] .= "border-radius: ".$border_radius."; ";
            // $border['hover'] .= "border-radius: ".$border_radius_hover."; ";

            // border-style
            $border_left = $border_top = $border_right = $border_bottom = "solid";
            if (isset($atts[$pre.'border_left']) && $atts[$pre.'border_left'] != "") $border_left = $atts[$pre.'border_left'];
            if (isset($atts[$pre.'border_top']) && $atts[$pre.'border_top'] != "") $border_top = $atts[$pre.'border_top'];
            if (isset($atts[$pre.'border_right']) && $atts[$pre.'border_right'] != "") $border_right = $atts[$pre.'border_right'];
            if (isset($atts[$pre.'border_bottom']) && $atts[$pre.'border_bottom'] != "") $border_bottom = $atts[$pre.'border_bottom'];
            $border['normal'] .= "border-left-style: ".$border_left."; border-top-style: ".$border_top."; border-right-style: ".$border_right."; border-bottom-style: ".$border_bottom."; ";
            // border-style-hover
            $border_left_hover = $border_top_hover = $border_right_hover = $border_bottom_hover = "solid";
            if (isset($atts[$pre.'border_left_hover']) && $atts[$pre.'border_left_hover'] != "") $border_left_hover = $atts[$pre.'border_left_hover'];
            if (isset($atts[$pre.'border_top_hover']) && $atts[$pre.'border_top_hover'] != "") $border_top_hover = $atts[$pre.'border_top_hover'];
            if (isset($atts[$pre.'border_right_hover']) && $atts[$pre.'border_right_hover'] != "") $border_right_hover = $atts[$pre.'border_right_hover'];
            if (isset($atts[$pre.'border_bottom_hover']) && $atts[$pre.'border_bottom_hover'] != "") $border_bottom_hover = $atts[$pre.'border_bottom_hover'];
            $border['hover'] .= "border-left-style: ".$border_left_hover."; border-top-style: ".$border_top_hover."; border-right-style: ".$border_right_hover."; border-bottom-style: ".$border_bottom_hover."; ";

            return $border;
        }
        
        /*
            shadow params
        */
        public static function shadow_params_vc($pre, $group, $hover=true, $dep_el=false, $dep_val=false) {
            if ($pre != "") $pre = trim($pre, "_")."_";  
            $dependency = array();
            if ($dep_el != false) {
                if ($dep_val == "not_empty")
                    $dependency = array( 'dependency'  => array(
                                            'element' => $dep_el,
                                            'not_empty' => true
                                        ) );
                else
                    $dependency = array( 'dependency'  => array(
                                            'element' => $dep_el,
                                            'value' => $dep_val
                                        ) );
            }

            $shadow_params = array(
                // dropshadow 2.0
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'shadow',
                        // 'heading'       => __('Schlagschatten', 'core'),
                        'param_name'    => $pre.'shadow',
                        "old"           => array( 
                            "type"   => $pre."sdw_type", 
                            "x"      => $pre."sdw_x", 
                            "y"      => $pre."sdw_y", 
                            "blur"   => $pre."sdw_blur", 
                            "spread" => $pre."sdw_spread", 
                            "color"  => $pre."sdw_colorselect", 
                            "colorold" => $pre."sdw_color", 
                        ),
                        'edit_field_class' => 'vc_col-xs-12',
                    ), $dependency
                ),
                // dropshadow color
                array_merge(
                    array(
                        "group"         => $group,
                        "type"          => "colorselect",
                        "heading"       => __('Farbe', 'core'),
                        "param_name"    => $pre."sdw_colorselect",
                        'edit_field_class' => 'vc_col-xs-6 hidden',
                    ), $dependency
                ),
                // dropshadow settings
                array_merge(
                    array(
                        "group"         => $group,
                        "type"        => 'new_line',
                        "param_name"  => 'new_line_'.$pre.'sdw',
                        'edit_field_class' => 'hidden',
                    )
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'dropdown',
                        'heading'       => __('Position', 'core'),
                        'param_name'    => $pre.'sdw_type',
                        'value'         => array(
                            _x('außen', 'small', 'core') => '', 
                            _x('innen', 'small', 'core') => 'inset'
                        ),
                        'edit_field_class' => 'vc_col-xs-4 hidden',
                    ), $dependency
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'textfield',
                        'heading'       => __('Verschiebung', 'core').' <u>'.__('horizontal', 'core').'</u>',
                        'description'   => __('in px', 'core'),
                        'param_name'    => $pre.'sdw_x',
                        "value"         => '2px',
                        'edit_field_class' => 'vc_col-xs-2 hidden',
                    ), $dependency
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'textfield',
                        'heading'       => __('Verschiebung', 'core').' <u>'.__('vertikal', 'core').'</u>',
                        'description'   => __('in px', 'core'),
                        'param_name'    => $pre.'sdw_y',
                        "value"         => '2px',
                        'edit_field_class' => 'vc_col-xs-2 hidden',
                    ), $dependency
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'textfield',
                        'heading'       => __('Weichzeichnung', 'core'),
                        'description'   => __('in px', 'core'),
                        'param_name'    => $pre.'sdw_blur',
                        "value"         => '4px',
                        'edit_field_class' => 'vc_col-xs-2 hidden',
                    ), $dependency
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'textfield',
                        'heading'       => __('Ausdehnung', 'core'),
                        'description'   => __('in px', 'core'),
                        'param_name'    => $pre.'sdw_spread',
                        "value"         => '0px',
                        'edit_field_class' => 'vc_col-xs-2 hidden',
                    ), $dependency
                ),
            );
            $shadow_hover_params = array(
                // Dropshadow hover
                array_merge(
                    array(
                        "group"         => $group,
                        "type"        => 'sub_seperator',
                        "heading"     => __('Hover', 'core'),
                        "param_name"  => 'sub_seperator_'.$pre.'sdw',
                    ), $dependency
                ),
                // dropshadow 2.0
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'shadow',
                        // 'heading'       => __('Schlagschatten', 'core'),
                        'param_name'    => $pre.'shadow_hover',
                        "old"           => array( 
                            "type"   => $pre."sdw_type_hover", 
                            "x"      => $pre."sdw_x_hover", 
                            "y"      => $pre."sdw_y_hover", 
                            "blur"   => $pre."sdw_blur_hover", 
                            "spread" => $pre."sdw_spread_hover", 
                            "color"  => $pre."sdw_colorselect_hover", 
                            "colorold" => $pre."sdw_color_hover", 
                        ),
                        'edit_field_class' => 'vc_col-xs-12',
                    ), $dependency
                ),
                // Dropshadow hover color
                array_merge(
                    array(
                        "group"         => $group,
                        "type"          => "colorselect",
                        "heading"       => __('Farbe', 'core'),
                        "param_name"    => $pre."sdw_colorselect_hover",
                        'edit_field_class' => 'vc_col-xs-6 hidden',
                    ), $dependency
                ),
                // Dropshadow hover settings
                array_merge(
                    array(
                        "group"         => $group,
                        "type"        => 'new_line',
                        "param_name"  => 'new_line_'.$pre.'sdw_hover',
                        'edit_field_class' => 'hidden',
                    )
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'dropdown',
                        'heading'       => __('Typ', 'core'),
                        'param_name'    => $pre.'sdw_type_hover',
                        'value'         => array(
                            _x('außen', 'small', 'core') => '', 
                            _x('innen', 'small', 'core') => 'inset'
                        ),
                        'edit_field_class' => 'vc_col-xs-4 hidden',
                    ), $dependency
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'textfield',
                        'heading'       => __('Verschiebung', 'core').' <u>'.__('horizontal', 'core').'</u>',
                        'description'   => __('in px', 'core'),
                        'param_name'    => $pre.'sdw_x_hover',
                        "value"         => '2px',
                        'edit_field_class' => 'vc_col-xs-2 hidden',
                    ), $dependency
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'textfield',
                        'heading'       => __('Verschiebung', 'core').' <u>'.__('vertikal', 'core').'</u>',
                        'description'   => __('in px', 'core'),
                        'param_name'    => $pre.'sdw_y_hover',
                        "value"         => '2px',
                        'edit_field_class' => 'vc_col-xs-2 hidden',
                    ), $dependency
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'textfield',
                        'heading'       => __('Weichzeichnung', 'core'),
                        'description'   => __('in px', 'core'),
                        'param_name'    => $pre.'sdw_blur_hover',
                        "value"         => '4px',
                        'edit_field_class' => 'vc_col-xs-2 hidden',
                    ), $dependency
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'textfield',
                        'heading'       => __('Ausdehnung', 'core'),
                        'description'   => __('in px', 'core'),
                        'param_name'    => $pre.'sdw_spread_hover',
                        "value"         => '0px',
                        'edit_field_class' => 'vc_col-xs-2 hidden',
                    ), $dependency
                ),
            );

            if ($hover) return array_merge($shadow_params, $shadow_hover_params);
            else return $shadow_params;
        }
        public static function make_shadow($atts, $pre) {
            if ($pre != "") $pre = trim($pre, "_")."_";  

            // debug($atts);
            if (isset($atts[$pre.'shadow']) && $atts[$pre.'shadow'] != "") {
                $shadow = array(
                    'normal' => 'box-shadow: '.helper::get_shadow($atts, $pre.'shadow', 'none').';',
                    'hover' => 'box-shadow: '.helper::get_shadow($atts, $pre.'shadow_hover', 'none').';'
                );
                return $shadow;
            }
            else {
                // shadow-color
                $sdw_color = helper::get_color($atts, $pre.'sdw_', '', 'color_61');
                $sdw_color_hover = helper::get_color($atts, $pre.'sdw_', '_hover', 'color_61');

                // sdw_x
                $sdw_type = isset($atts[$pre.'sdw_type']) ? $atts[$pre.'sdw_type'] : '';
                $sdw_type_hover = isset($atts[$pre.'sdw_type_hover']) ? $atts[$pre.'sdw_type_hover'] : '';
                // sdw_x
                $sdw_x = $sdw_x_hover = "2px";
                if (isset($atts[$pre.'sdw_x']) && $atts[$pre.'sdw_x'] != "") $sdw_x = str_replace("px", "", $atts[$pre.'sdw_x'])."px";
                if (isset($atts[$pre.'sdw_x_hover']) && $atts[$pre.'sdw_x_hover'] != "") $sdw_x_hover = str_replace("px", "", $atts[$pre.'sdw_x_hover'])."px";
                // sdw_y
                $sdw_y = $sdw_y_hover = "2px";
                if (isset($atts[$pre.'sdw_y']) && $atts[$pre.'sdw_y'] != "") $sdw_y = str_replace("px", "", $atts[$pre.'sdw_y'])."px";
                if (isset($atts[$pre.'sdw_y_hover']) && $atts[$pre.'sdw_y_hover'] != "") $sdw_y_hover = str_replace("px", "", $atts[$pre.'sdw_y_hover'])."px";
                // sdw_blur
                $sdw_blur = $sdw_blur_hover = "4px";
                if (isset($atts[$pre.'sdw_blur']) && $atts[$pre.'sdw_blur'] != "") $sdw_blur = str_replace("px", "", $atts[$pre.'sdw_blur'])."px";
                if (isset($atts[$pre.'sdw_blur_hover']) && $atts[$pre.'sdw_blur_hover'] != "") $sdw_blur_hover = str_replace("px", "", $atts[$pre.'sdw_blur_hover'])."px";
                // sdw_spread
                $sdw_spread = $sdw_spread_hover = "0px";
                if (isset($atts[$pre.'sdw_spread']) && $atts[$pre.'sdw_spread'] != "") $sdw_spread = str_replace("px", "", $atts[$pre.'sdw_spread'])."px";
                if (isset($atts[$pre.'sdw_spread_hover']) && $atts[$pre.'sdw_spread_hover'] != "") $sdw_spread_hover = str_replace("px", "", $atts[$pre.'sdw_spread_hover'])."px";
                
                $shadow = array(
                    'normal' => "box-shadow: ".$sdw_type." ".$sdw_x." ".$sdw_y." ".$sdw_blur." ".$sdw_spread." ".$sdw_color.";",
                    'hover' => "box-shadow: ".$sdw_type_hover." ".$sdw_x_hover." ".$sdw_y_hover." ".$sdw_blur_hover." ".$sdw_spread_hover." ".$sdw_color_hover.";"
                );
                if ($sdw_color == '' || $sdw_color == 'transparent' || ($sdw_x != "0px" && $sdw_y != "0px" && $sdw_blur != "0px" && $sdw_spread != "0px"))
                    $shadow['normal'] = 'box-shadow: none;';
                if ($sdw_color_hover == '' || $sdw_color_hover == 'transparent' || ($sdw_x_hover != "0px" && $sdw_y_hover != "0px" && $sdw_blur_hover != "0px" && $sdw_spread_hover != "0px"))
                    $shadow['hover'] = 'box-shadow: none;';

                return $shadow;
            }
        }

        /*
            background params
        */
        public static function background_params_vc($pre, $group, $types=true, $hover=true) {
            global $config;
            // if ($pre != "" && !strpos($pre, "_")) $pre .= "_";  
            if ($pre != "") $pre = trim($pre, "_")."_";  

            $bgtypes = array(
                _x('kein Hintergrund', 'small', 'core') => "",
                _x('Farbe', 'small', 'core') => $pre.'color',
                _x('Farbverlauf', 'small', 'core') => $pre.'gradient2',
                _x('Bild', 'small', 'core') => $pre.'image',
                _x('Animation', 'small', 'core') => $pre.'animation',
                _x('Video', 'small', 'core') => $pre.'video',
            );
            if (is_array($types)) {
                $bgtypes = array(
                    _x('kein Hintergrund', 'small', 'core') => ""
                );
                if ($types['color'] == true) $bgtypes[_x('Farbe', 'small', 'core')] = $pre.'color';
                if ($types['gradient2'] == true) $bgtypes[_x('Farbverlauf', 'small', 'core')] = $pre.'gradient2';
                if ($types['image'] == true) $bgtypes[_x('Bild', 'small', 'core')] = $pre.'image';
                if ($types['animation'] == true) $bgtypes[_x('Animation', 'small', 'core')] = $pre.'animation';
                if ($types['video'] == true) $bgtypes[_x('Video', 'small', 'core')] = $pre.'video';
            }
            if ($config->settings['site']['lottie']['mode'] == 'disable') {
                unset($bgtypes[_x('Animation', 'small', 'core')]);
            }

            $params = array(
                'type' => array(
                    array(
                        "group"         => $group,
                        "type"          => "dropdown",
                        "heading"       => __('Hintergrundtyp', 'core'),
                        "param_name"    => $pre."type",
                        "value"         => $bgtypes,
                        'edit_field_class' => 'vc_col-xs-6',
                    ),
                    // opacity
                    array(
                        "group"         => $group,
                        'type'          => 'range',
                        'heading'       => __('Deckkraft', 'core'),
                        'param_name'    => $pre.'opacity',
                        'input_attrs'   => array( "min" => 0, "max" => 100, "step" => 1 ),
                        'label'         => array( "lbl" => "", "unit" => "%" ),
                        'value'         => '100',
                        'dependency'  => array(
                            'element' => $pre.'type',
                            'not_empty' => true
                        ),
                        'edit_field_class' => 'vc_col-xs-3',
                    ),
                    array(
                        "group"         => $group,
                        "type"        => 'new_line',
                        "param_name"  => 'new_line_'.$pre.'after_opacity',
                    ),
                ),
                'image' => array(
                    // dynamic image
                    array(
                        "group"         => $group,
                        'type'          => 'dynamic',
                        'param_name'    => 'dynamic_'.$pre.'image',
                        'heading'       => __( 'Typ', 'core' ),
                        'text'          => __('Indem du Inhalte von Modulen in Templates dynamisch machst, kannst du diese beim späteren Einbinden in eine Seite befüllen. Dadurch kannst du das Template an verschiedenen Stellen mit unterschiedlichen Inhalten verwenden.', 'core'),
                        'value'         => 'static',
                        'params'        => array(
                            'type' => 'file_picker_image',
                            'field' => $pre.'image',
                        ),
                        'dependency'  => array(
                            'element' => $pre.'type',
                            'value' => array($pre.'image'),
                        ),
                        'edit_field_class' => 'vc_col-xs-12',
                    ),
                    array(
                        "group"         => $group,
                        'type'          => 'file_picker',
                        'heading'       => __( 'Bild wählen', 'core' ),
                        'param_name'    => $pre.'image',
                        'filetype'      => 'image',
                        'dependency'  => array(
                            'element' => $pre.'type',
                            'value' => array($pre.'image'),
                        ),
                    ),
                    array(
                        "group"         => $group,
                        "type"          => "dropdown",
                        "heading"       => __('Größe', 'core'),
                        "param_name"    => $pre."image_size",
                        "value"         => array(
                            _x('einpassen (contain)', 'small', 'core') => '',
                            _x('vollständig ausfüllen (cover)', 'small', 'core') => 'cover',
                            _x('Originalgröße (initial)', 'small', 'core') => 'initial',
                        ),
                        'dependency'  => array(
                            'element' => $pre.'type',
                            'value' => array($pre.'image'),
                        ),
                        'edit_field_class' => 'vc_col-xs-4',
                    ),
                    array(
                        "group"         => $group,
                        "type"          => "dropdown",
                        "heading"       => __('Wiederholung', 'core'),
                        "description"       => __('Soll das Bild wiederholt werden, wenn es kleiner ist als die Fläche?', 'core'),
                        "param_name"    => $pre."image_repeat",
                        "value"         => array(
                            _x('vertikal & horizontal', 'small', 'core') => '',
                            _x('horizontal', 'small', 'core') => 'repeat-x',
                            _x('vertikal', 'small', 'core') => 'repeat-y',
                            _x('nicht wiederholen', 'small', 'core') => 'no-repeat',
                        ),
                        'dependency'  => array(
                            'element' => $pre.'type',
                            'value' => array($pre.'image'),
                        ),
                        'edit_field_class' => 'vc_col-xs-4',
                    ),
                    array(
                        "group"         => $group,
                        "type"          => "dropdown",
                        "heading"       => __('Position', 'core'),
                        "param_name"    => $pre."image_position",
                        "value"         => array(
                            _x('oben mittig', 'small', 'core') => "",
                            _x('oben links', 'small', 'core') => 'top_left',
                            _x('oben rechts', 'small', 'core') => 'top_right',
                            _x('mittig', 'small', 'core') => "center_center",
                            _x('mittig links', 'small', 'core') => 'center_left',
                            _x('mittig rechts', 'small', 'core') => 'center_right',
                            _x('unten mittig', 'small', 'core') => "bottom_center",
                            _x('unten links', 'small', 'core') => 'bottom_left',
                            _x('unten rechts', 'small', 'core') => 'bottom_right',
                        ),
                        'dependency'  => array(
                            'element' => $pre.'type',
                            'value' => array($pre.'image'),
                        ),
                        'edit_field_class' => 'vc_col-xs-4',
                    ),
                ),
                'animation' => array(
                    // dynamic animation
                    array(
                        "group"         => $group,
                        'type'          => 'dynamic',
                        'param_name'    => 'dynamic_'.$pre.'animation',
                        'heading'       => __( 'Typ', 'core' ),
                        'text'          => __('Indem du Inhalte von Modulen in Templates dynamisch machst, kannst du diese beim späteren Einbinden in eine Seite befüllen. Dadurch kannst du das Template an verschiedenen Stellen mit unterschiedlichen Inhalten verwenden.', 'core'),
                        'value'         => 'static',
                        'params'        => array(
                            'type' => 'file_picker_json',
                            'field' => $pre.'animation_file',
                        ),
                        'dependency'  => array(
                            'element' => $pre.'type',
                            'value' => array($pre.'animation'),
                        ),
                        'edit_field_class' => 'vc_col-xs-12',
                    ),
                    array(
                        "group"         => $group,
                        'type'          => 'file_picker',
                        'heading'       => __( 'Auswahl Animation', 'core' ),
                        'param_name'    => $pre.'animation_file',
                        'filetype'      => 'json',
                        'dependency'  => array(
                            'element' => $pre.'type',
                            'value' => array($pre.'animation'),
                        ),
                        'edit_field_class' => 'vc_col-xs-6',
                    ),
                    // dynamic placeholder
                    array(
                        "group"         => $group,
                        'type'          => 'dynamic',
                        'param_name'    => 'dynamic_'.$pre.'animation_placeholder',
                        'heading'       => __( 'Typ', 'core' ),
                        'text'          => __('Indem du Inhalte von Modulen in Templates dynamisch machst, kannst du diese beim späteren Einbinden in eine Seite befüllen. Dadurch kannst du das Template an verschiedenen Stellen mit unterschiedlichen Inhalten verwenden.', 'core'),
                        'value'         => 'static',
                        'params'        => array(
                            'type' => 'file_picker_image',
                            'field' => $pre.'animation_placeholder',
                        ),
                        'dependency'  => array(
                            'element' => $pre.'type',
                            'value' => array($pre.'animation'),
                        ),
                        'edit_field_class' => 'vc_col-xs-12',
                    ),
                    array(
                        "group"         => $group,
                        'type'          => 'file_picker',
                        'heading'       => __( 'Platzhalter', 'core' ),
                        'param_name'    => $pre.'animation_placeholder',
                        'filetype'      => 'image',
                        'dependency'  => array(
                            'element' => $pre.'type',
                            'value' => array($pre.'animation'),
                        ),
                        'edit_field_class' => 'vc_col-xs-6',
                    ),
                    array(
                        "group"         => $group,
                        "type"        => 'new_line',
                        "param_name"  => 'new_line_'.$pre.'after_placeholder',
                        'dependency'  => array(
                            'element' => $pre.'type',
                            'value' => array($pre.'animation'),
                        ),
                    ),
                    array(
                        "group"         => $group,
                        'type'          => 'dropdown',
                        'heading'       => __('Start der Animation', 'core'),
                        'param_name'    => $pre.'animation',
                        'value' => array(
                            _x('automatisch', 'small', 'core') => '',
                            // _x('Start on Hover', 'small', 'core') => 'hover',
                            _x('sobald sichtbar', 'small', 'core') => 'visible',
                        ),
                        'dependency'  => array(
                            'element' => $pre.'type',
                            'value' => array($pre.'animation'),
                        ),
                        'edit_field_class' => 'vc_col-xs-4',
                    ),
                    array(
                        "group"         => $group,
                        "type"          => "dropdown",
                        "heading"       => __('Größe', 'core'),
                        "param_name"    => $pre."anim_size",
                        "value"         => array(
                            _x('Originalgröße', 'small', 'core') => '',
                            _x('volle Breite', 'small', 'core') => 'full',
                        ),
                        'dependency'  => array(
                            'element' => $pre.'type',
                            'value' => array($pre.'animation'),
                        ),
                        'edit_field_class' => 'vc_col-xs-4',
                    ),
                    array(
                        "group"         => $group,
                        "type"          => "dropdown",
                        "heading"       => __('Position', 'core'),
                        "param_name"    => $pre."anim_position",
                        "value"         => array(
                            _x('oben mittig', 'small', 'core') => "",
                            _x('oben links', 'small', 'core') => 'top_left',
                            _x('oben rechts', 'small', 'core') => 'top_right',
                            _x('mittig', 'small', 'core') => "center_center",
                            _x('mittig links', 'small', 'core') => 'center_left',
                            _x('mittig rechts', 'small', 'core') => 'center_right',
                            _x('unten mittig', 'small', 'core') => "bottom_center",
                            _x('unten links', 'small', 'core') => 'bottom_left',
                            _x('unten rechts', 'small', 'core') => 'bottom_right',
                        ),
                        'dependency'  => array(
                            'element' => $pre.'anim_size',
                            'value' => array(''),
                        ),
                        'edit_field_class' => 'vc_col-xs-4',
                    ),
                    array(
                        "group"         => $group,
                        "type"          => "dropdown",
                        "heading"       => __('Ausrichtung', 'core'),
                        "param_name"    => $pre."anim_full_position",
                        "value"         => array(
                            _x('oben Mitte', 'small', 'core') => "",
                            _x('Mitte', 'small', 'core') => "center",
                            _x('unten Mitte', 'small', 'core') => "bottom",
                        ),
                        'dependency'  => array(
                            'element' => $pre.'anim_size',
                            'value' => array('full'),
                        ),
                        'edit_field_class' => 'vc_col-xs-4',
                    ),
                ),
                'video' => array(
                    // dynamic video link
                    array(
                        "group"         => $group,
                        'type'          => 'dynamic',
                        'param_name'    => 'dynamic_'.$pre.'video',
                        'heading'       => __( 'Typ', 'core' ),
                        'text'          => __('Indem du Inhalte von Modulen in Templates dynamisch machst, kannst du diese beim späteren Einbinden in eine Seite befüllen. Dadurch kannst du das Template an verschiedenen Stellen mit unterschiedlichen Inhalten verwenden.', 'core'),
                        'value'         => 'static',
                        'params'        => array(
                            'type' => 'textfield',
                            'field' => $pre.'video',
                        ),
                        'dependency'  => array(
                            'element' => $pre.'type',
                            'value' => array($pre.'video'),
                        ),
                        'edit_field_class' => 'vc_col-xs-12',
                    ),
                    array(
                        "group"         => $group,
                        'type'          => 'textfield',
                        'heading'       => __('Video Link', 'core'),
                        'description'   => __('YouTube oder Vimeo URL', 'core'),
                        'param_name'    => $pre.'video',
                        'dependency'  => array(
                            'element' => $pre.'type',
                            'value' => array($pre.'video'),
                        ),
                        'edit_field_class' => 'vc_col-xs-6',
                    ),
                    array(
                        "group"         => $group,
                        "type"          => "dropdown",
                        "heading"       => __('Format', 'core'),
                        "param_name"    => $pre."video_aspect",
                        "value"         => array(
                            _x('16/9', 'small', 'core') => "16/9",
                            _x('21/9', 'small', 'core') => "21/9",
                            _x('4/3', 'small', 'core') => "4/3",
                            _x('1/1', 'small', 'core') => "1/1",
                        ),
                        'dependency'  => array(
                            'element' => $pre.'type',
                            'value' => array($pre.'video'),
                        ),
                        'edit_field_class' => 'vc_col-xs-3',
                    ),
                ),
                'color' => array(
                    array(
                        "group"         => $group,
                        "type"          => "colorselect",
                        "heading"       => __('Hintergrundfarbe', 'core'),
                        "param_name"    => $pre."colorselect",
                        'dependency'  => array(
                            'element' => $pre.'type',
                            'value' => array($pre.'color', $pre.'image', $pre.'animation', $pre.'video'),
                        ),
                        'edit_field_class' => 'vc_col-xs-6',
                    ),
                ),
                'gradient2' => array(
                    array(
                        "group"         => $group,
                        "type"        => 'new_line',
                        "param_name"  => 'new_line_'.$pre.'grad2',
                    ),
                    array(
                        "group"         => $group,
                        "type"          => "colorgradient",
                        "heading"       => __('Farbverlauf', 'core'),
                        "param_name"    => $pre."gradient2",
                        "old"           => array( 
                            "color1"    => $pre."color", 
                            "pos1"      => $pre."gradient_pos",
                            "color2"    => $pre."color2", 
                            "pos2"      => $pre."gradient_pos2",
                            "type"      => $pre."gradient_type", 
                            "angle"     => $pre."gradient_angle" , 
                            "scroll"    => $pre."gradient_scroll" 
                        ),
                        'dependency'  => array(
                            'element' => $pre.'type',
                            'value' => array($pre.'gradient2'),
                        ),
                    ),
                ),
            );

            if ($hover) {
                $params['color'] = array_merge(
                    $params['color'],
                    array(
                        array(
                            "group"         => $group,
                            "type"          => "colorselect",
                            "heading"       => __('Hintergrundfarbe', 'core').'&nbsp;<u>'.__('Hover', 'core').'</u>',
                            "param_name"    => $pre."colorselect_hover",
                            'dependency'  => array(
                                'element' => $pre.'type',
                                'value' => array($pre.'color', $pre.'image', $pre.'animation', $pre.'video'),
                            ),
                            'edit_field_class' => 'vc_col-xs-6',
                        ),
                    )
                );
            }

            $final_params = $params['type'];
            if (is_array($types)) {
                if ($types['image'] == true) $final_params = array_merge($final_params, $params['image']);
                if ($types['animation'] == true) $final_params = array_merge($final_params, $params['animation']);
                if ($types['video'] == true) $final_params = array_merge($final_params, $params['video']);
                if ($types['color'] == true) $final_params = array_merge($final_params, $params['color']);
                if ($types['gradient2'] == true) $final_params = array_merge($final_params, $params['gradient2']);
            }
            else {
                $final_params = array_merge(
                    $params['type'], 
                    $params['image'], 
                    $params['animation'], 
                    $params['video'], 
                    $params['color'], 
                    $params['gradient2']
                );
            }

            return $final_params;
        }
        public static function make_background($atts, $pre, $bg) {
            // if ($pre != "" && !strpos($pre, "_")) $pre .= "_";  
            if ($pre != "") $pre = trim($pre, "_")."_";  

            $bg_id = $bg['id'];
            $bg_inline_style = "";
            $bg_basic = "";

            // basic background
            $type = isset($atts[$pre.'type']) ? esc_attr($atts[$pre.'type']) : '';

            // opacity
            $opacity = helper::get_opacity($atts, $pre);
            $bg_op = "opacity: ".$opacity.";";

            // single color
            if ($type == $pre."color" || $type == $pre."image" || $type == $pre."animation" || $type == $pre."video") {
                $color = helper::get_color($atts, $pre);
                if ($color != "transparent" && !empty($color)) {
                    // make basic color layer
                    $bg_inline_style .= "#".$bg_id." .vc_bg_color { ".$bg_op."background-color: ".$color."; } ";
                    $bg_basic .= "<div class='vc_bg_div vc_bg_color'></div>";
                }
            }
            // single color hover
            if ($type == $pre."color" || $type == $pre."image" || $type == $pre."animation" || $type == $pre."video") {
                $color_hover = helper::get_color($atts, $pre, '_hover');
                if ($color_hover != "transparent" && !empty($color_hover) && $color_hover != $color) {
                    // make basic color_hover layer
                    $bg_inline_style .= "#".$bg_id.":hover .vc_bg_color { ".$bg_op."background-color: ".$color_hover."; } ";
                    if ($bg_basic == "") $bg_basic .= "<div class='vc_bg_div vc_bg_color'></div>";
                }
            }
            // gradient 2.0
            if ($type == $pre."gradient2") {
                $gradient = helper::get_gradient2($atts, $pre);
                $gradient_style = "background-image: linear-gradient(".$gradient['angle']."deg".$gradient['gradient']."); background-attachment: ".$gradient['scroll'].";";
                // make basic gradient layer
                $bg_inline_style .= "#".$bg_id." .vc_bg_gradient { ".$bg_op.$gradient_style." } ";
                $bg_basic .= "<div class='vc_bg_div vc_bg_gradient'></div>";
            }
            // image
            if ($type == $pre."image") {
                $image = isset($atts[$pre.'image']) ? esc_attr($atts[$pre.'image']) : -1;
                if (is_numeric($image)) $image_path = wp_get_attachment_url($image);
                else $image_path = $image;
                if (isset($image_path)) {
                    // image src
                    $image_thumb = (\basics::get_setting(array('site', 'lazyload')) == 'true') ? get_image($image, 'medium') : $image_path;
                    $image_style = "background-image: url(".$image_thumb.");";
                    // image size
                    $image_size = isset($atts[$pre.'image_size']) && $atts[$pre.'image_size'] != "" ? esc_attr($atts[$pre.'image_size']) : "contain";
                    $image_style .= "background-size: ".$image_size.";";
                    // image repeat
                    $image_repeat = isset($atts[$pre.'image_repeat']) && $atts[$pre.'image_repeat'] != "" ? esc_attr($atts[$pre.'image_repeat']) : "repeat";
                    $image_style .= "background-repeat: ".$image_repeat.";";
                    // image position
                    $image_position = isset($atts[$pre.'image_position']) && $atts[$pre.'image_position'] != "" ? esc_attr($atts[$pre.'image_position']) : "top_center";
                    $image_position = str_replace("_", " ", $image_position);
                    $image_style .= "background-position: ".$image_position.";";
                    // image scroll
                    $bg_image_class = "";
                    $bg_image_data = "";
                    $image_scroll = isset($atts[$pre.'image_scroll']) && $atts[$pre.'image_scroll'] != "" ? esc_attr($atts[$pre.'image_scroll']) : "scroll";
                    if ($image_scroll == "scroll" || $image_scroll == "fixed") $image_style .= "background-attachment: ".$image_scroll.";";
                    else {
                        $image_parallax = helper::get_parallax($atts, $pre);
                        $bg_image_data = $image_parallax['data'];
                        $bg_image_class = $image_parallax['class'];
                    }
                    // make basic image layer
                    $bg_inline_style .= "#".$bg_id." .vc_bg_image { ".$bg_op.$image_style." } ";
                    $srcset = " data-srcset='".json_encode(get_imageset($image))."'";
                    $bg_basic .= "<div class='vc_bg_div vc_bg_image ".$bg_image_class."' ".$bg_image_data." $srcset></div>";
                }
            }
            // animation
            if ($type == $pre."animation") {
                $animation_file = isset($atts[$pre.'animation_file']) ? esc_attr($atts[$pre.'animation_file']) : -1;
                if ($animation_file == -1 || $animation_file == "")
                    $animation_file = isset($atts[$pre.'image']) ? esc_attr($atts[$pre.'image']) : -1;
                $image_path = wp_get_attachment_url($animation_file);
                
                if (isset($image_path)) {
                    $anim_id = "anim_".uniqid();
                    $anim_class = "";
                    $anim_data = "";
                    // animation behaviour
                    $anim_behaviour = isset($atts[$pre.'animation']) && $atts[$pre.'animation'] != "" ? esc_attr($atts[$pre.'animation']) : 'auto';
                    $anim_data .= " data-anim='".$anim_behaviour."'";
                    // anim size
                    $anim_size = isset($atts[$pre.'anim_size']) ? esc_attr($atts[$pre.'anim_size']) : "";
                    $style = "";
                    if ($anim_size != "full") {
                        if ($anim_size != "") {
                            $style = "width: ".$anim_size."; ";
                        }
                        // anim position
                        $anim_position = isset($atts[$pre.'anim_position']) && $atts[$pre.'anim_position'] != "" ? esc_attr($atts[$pre.'anim_position']) : "top_center";
                        $anim_class = $anim_position;
                    }
                    else if ($anim_size == "full") {
                        // anim full position
                        $anim_full_position = isset($atts[$pre.'anim_full_position']) && $atts[$pre.'anim_full_position'] != "" ? esc_attr($atts[$pre.'anim_full_position']) : "top";
                        $anim_class = $anim_full_position;
                    }
                    // image scroll
                    $image_scroll = isset($atts[$pre.'image_scroll']) ? esc_attr($atts[$pre.'image_scroll']) : "";
                    if ($image_scroll != "") {
                        $image_parallax = helper::get_parallax($atts, $pre);
                        $anim_data .= $image_parallax['data'];
                        $anim_class .= " div_parallax ".$image_parallax['class'];
                    }
                    // make placeholder
                    $placeholder = isset($atts[$pre.'animation_placeholder']) ? esc_attr($atts[$pre.'animation_placeholder']) : "";
                    if ($placeholder != "") {
                        // $placeholder_path = wp_get_attachment_url($placeholder);
                        $placeholder_path = get_image($placeholder, 'medium');
                        $placeholder = "<img class='bm_icon_placeholder ".$anim_class."' src='".$placeholder_path."' style='display:inline-block;'>";
                        $style .= "display:none;";
                    }
                    else $style .= "display:inline-block;";
                    // make basic animation layer
                    $anim = $placeholder."<div class='bm_icon ".$anim_behaviour." ".$anim_class."' style='$style' id='".$anim_id."' data-src='".$image_path."' ".$anim_data."></div>";
                    $bg_basic .= "<div class='vc_bg_div vc_bg_animation' style='".$bg_op."'>".$anim."</div>";
                }
            }
            // video
            if ($type == $pre."video") {
                $video_src = isset($atts[$pre.'video']) && $atts[$pre.'video'] != "" ? esc_attr($atts[$pre.'video']) : '';
                if ($video_src != "") {
                    $video_id = "video_".uniqid();
                    $video_class = "";
                    $video_data = "";
                    // image scroll
                    $image_scroll = isset($atts[$pre.'image_scroll']) ? esc_attr($atts[$pre.'image_scroll']) : "";
                    if ($image_scroll != "") {
                        $image_parallax = helper::get_parallax($atts, $pre);
                        $video_data .= $image_parallax['data'];
                        $video_class .= " div_parallax ".$image_parallax['class'];
                    }
                    // aspect ratio
                    $video_aspect = isset($atts[$pre.'video_aspect']) ? esc_attr($atts[$pre.'video_aspect']) : "16/9";
                    $video_data .= " data-vc_bg_video_ar='".$video_aspect."'";

                    // make basic video layer
                    if (strpos($video_src, "youtu") !== false) {
                        if (strpos($video_src, "youtu.be")) {
                            $tmp = explode(".be/", $video_src);
                            $video_src = trim($tmp[1]);
                        }
                        else if (strpos($video_src, "?v=")) {
                            $tmp = explode("?v=", $video_src);
                            $video_src = trim($tmp[1]);
                        }
                        else {
                            $tmp = explode("embed/", $video_src);
                            $tmp = explode("?", $tmp[1]);
                            $video_src = trim($tmp[0]);
                        }
                        $video_data .= " data-vc_bg_video_src='youtube' data-vc_bg_video_id='".$video_src."'";
                        $video = "<div class='".$video_class."' style='width:100%;height:100%' ".$video_data." ><div id='".$video_id."'></div></div>";
                    }
                    else if (strpos($video_src, "vimeo") !== false) {
                        $tmp = explode("vimeo.com/", $video_src);
                        $video_src = trim($tmp[1]);
                        
                        $video_data .= " data-vc_bg_video_src='vimeo' data-vc_bg_video_id='".$video_src."'";
                        $video = "<div class='".$video_class."' style='width:100%;height:100%' ".$video_data." >
                                    <iframe id='".$video_id."' src='https://player.vimeo.com/video/".$video_src."?autoplay=1&loop=1&muted=1&background=1&controls=0&title=0&byline=0&portrait=0' frameborder='0' allow='autoplay; fullscreen' allowfullscreen></iframe>
                                </div>";
                    }
                    else {
                        $video = helper::make_message("Video not recognized.");
                    }
                    $bg_basic .= "<div class='vc_bg_div vc_bg_video' style='".$bg_op."'>".$video."</div>";
                }
            }
            
            $bg['inline_style'] .= $bg_inline_style;
            $bg['basic'] .= $bg_basic;
            return $bg;
        }

        /*
            overlay params
        */
        public static function overlay_params_vc($pre, $group, $dep_el=false, $dep_val=false) {
            if ($pre != "") $pre = trim($pre, "_")."_";  
            $dependency = array();
            if ($dep_el != false) {
                if ($dep_val == "not_empty")
                    $dependency = array( 'dependency'  => array(
                                            'element' => $dep_el,
                                            'not_empty' => true
                                        ) );
                else
                    $dependency = array( 'dependency'  => array(
                                            'element' => $dep_el,
                                            'value' => $dep_val
                                        ) );
            }
            return array(
                // overlay pattern
                array_merge(
                    array(
                        "group"       => $group,
                        "type"        => 'sub_seperator',
                        "heading"     => __('Musterüberlagerung', 'core'),
                        "param_name"  => 'sub_seperator_overlay',
                    ), $dependency
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        "type"          => "dropdown",
                        "heading"       => __('Muster', 'core'),
                        'description' => __('Mit welchem Muster soll der Zeilenhintergrund überlagert werden?', 'core'),
                        "param_name"    => $pre."overlay_pattern",
                        "value"         => array(
                            _x('kein Muster', 'small', 'core') => "",
                            _x('kleine Punkte', 'small', 'core') => 'pattern_01',
                            _x('große Punkte', 'small', 'core') => 'pattern_02',
                            _x('Gitterlinien', 'small', 'core') => 'pattern_03',
                            _x('Kreuze', 'small', 'core') => 'pattern_04',
                            _x('horizontale Linien', 'small', 'core') => 'pattern_05',
                            _x('vertikale Linien', 'small', 'core') => 'pattern_06',
                            _x('Quadrate und Punkte', 'small', 'core') => 'pattern_07',
                            _x('kleine Quadrate', 'small', 'core') => 'pattern_08',
                            _x('große Quadrate', 'small', 'core') => 'pattern_09',
                            _x('individuelles Muster', 'small', 'core') => 'pattern_custom',
                        ),
                        "class"       => $pre."overlay_pattern",
                    ), $dependency
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'file_picker',
                        'heading'       => __( 'Auswahl Muster', 'core' ),
                        'param_name'    => $pre.'overlay_cpattern',
                        'filetype'      => 'image',
                        'dependency'  => array(
                            'element' => $pre.'overlay_pattern',
                            'value' => array('pattern_custom'),
                        ),
                    )
                ),
                // overlay pattern settings
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'range',
                        'heading'       => __('Deckkraft', 'core').' <u>'.__('des Musters', 'core').'</u>',
                        'param_name'    => $pre.'overlay_opacity',
                        'input_attrs'   => array( "min" => 0, "max" => 100, "step" => 1 ),
                        'label'         => array( "lbl" => "", "unit" => "%" ),
                        'value'         => '100',
                        'dependency'  => array(
                            'element' => $pre.'overlay_pattern',
                            'not_empty' => true
                        ),
                        'edit_field_class' => 'vc_col-xs-4',
                    )
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'textfield',
                        'heading'       => __('Größe', 'core'),
                        'description'   => __('Wie groß sollen die Muster-Elemente sein? (Einheit: in px)', 'core'),
                        'param_name'    => $pre.'overlay_size',
                        'dependency'  => array(
                            'element' => $pre.'overlay_pattern',
                            'not_empty' => true
                        ),
                        'edit_field_class' => 'vc_col-xs-4',
                    )
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        "type"          => "dropdown",
                        "heading"       => __('Scroll-Verhalten', 'core'),
                        "param_name"    => $pre."overlay_scroll",
                        "value"         => array(
                            _x('mit Inhalt bewegen', 'small', 'core') => "",
                            _x('fixieren', 'small', 'core') => 'fixed',
                        ),
                        'dependency'  => array(
                            'element' => $pre.'overlay_pattern',
                            'not_empty' => true
                        ),
                        'edit_field_class' => 'vc_col-xs-4',
                    )
                ),
                // additional overlay
                array_merge(
                    array(
                        "group"       => $group,
                        "type"        => 'sub_seperator',
                        "heading"     => __('Zusätzliche Farbüberlagerung', 'core'),
                        "param_name"  => 'sub_seperator_overlay_color',
                    ), $dependency
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        "type"          => "dropdown",
                        "heading"       => __('Art', 'core').' <u>'.__('der Überlagerung', 'core').'</u>',
                        "param_name"    => $pre."overlay_type",
                        "value"         => array(
                            _x('zusätzliche Farbe', 'small', 'core') => $pre.'color',
                            _x('zusätzlicher Farbverlauf', 'small', 'core') => $pre.'gradient2',
                            _x('keine zusätzliche Überlagerung', 'small', 'core') => "",
                        ),
                        'edit_field_class' => 'vc_col-xs-6',
                    ), $dependency
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'range',
                        'heading'       => __('Deckkraft', 'core').' <u>'.__('der Überlagerung', 'core').'</u>',
                        'param_name'    => $pre.'overlay_color_opacity',
                        'input_attrs'   => array( "min" => 0, "max" => 100, "step" => 1 ),
                        'label'         => array( "lbl" => "", "unit" => "%" ),
                        'value'         => '100',
                        'dependency'  => array(
                            'element' => $pre.'overlay_type',
                            'not_empty' => true
                        ),
                        'edit_field_class' => 'vc_col-xs-3',
                    )
                ),
                // overlay color
                array_merge(
                    array(
                        "group"         => $group,
                        "type"          => "colorselect",
                         "heading"       => __('Farbe wählen', 'core'),
                        "param_name"    => $pre."overlay_colorselect",
                        'dependency'  => array(
                            'element' => $pre.'overlay_type',
                            'value' => array($pre.'color'),
                        ),
                        'edit_field_class' => 'vc_col-xs-6',
                    )
                ),
                // overlay gradient
                array_merge(
                    array(
                        "group"         => $group,
                        "type"          => "colorgradient",
                        // "heading"       => __('Zusätzlicher Farbverlauf', 'core'),
                        "param_name"    => $pre."overlay_gradient2",
                        'dependency'  => array(
                            'element' => $pre.'overlay_type',
                            'value' => array($pre.'gradient2'),
                        ),
                    )
                ),
            );
        }
        public static function make_overlay($atts, $pre, $bg) {
            if ($pre != "") $pre = trim($pre, "_")."_";  

            $bg_id = $bg['id'];
            $bg_inline_style = "";
            $bg_overlay = "";

            $overlay_type = isset($atts[$pre.'overlay_type']) ? esc_attr($atts[$pre.'overlay_type']) : $pre.'color';

            // color overlay
            if ($overlay_type == $pre."color") {
                $overlay_color = helper::get_color($atts, $pre.'overlay_');
                if ($overlay_color != "transparent" && !empty($overlay_color)) {
                    // color opacity
                    $opacity = helper::get_opacity($atts, $pre.'overlay_color_');
                    $overlay_color_style = "background-color: ".$overlay_color."; opacity: ".$opacity.";";
                    // make color overlay layer
                    $bg_inline_style .= "#".$bg_id." .vc_bg_overlay_color { ".$overlay_color_style." } ";
                    $bg_overlay .= "<div class='vc_bg_overlay_color'></div>";
                }
            }
            // gradient 2.0 overlay
            if ($overlay_type == $pre."gradient2") {
                $gradient = helper::get_gradient2($atts, $pre.'overlay_');
                $gradient_style = "background-image: linear-gradient(".$gradient['angle']."deg".$gradient['gradient']."); background-attachment: ".$gradient['scroll'].";";
                // color opacity
                $opacity = helper::get_opacity($atts, $pre.'overlay_color_');
                $gradient_style .= "opacity: ".$opacity.";";
                // make basic gradient layer
                $bg_inline_style .= "#".$bg_id." .vc_bg_overlay_gradient { ".$gradient_style." } ";
                $bg_overlay .= "<div class='vc_bg_overlay_gradient'></div>";
            }
            // pattern overlay
            $overlay_pattern = isset($atts[$pre.'overlay_pattern']) ? esc_attr($atts[$pre.'overlay_pattern']) : '';
            if ($overlay_pattern != "") {
                // pattern img
                if ($overlay_pattern == "pattern_custom") {
                    $overlay_cpattern = isset($atts[$pre.'overlay_cpattern']) ? esc_attr($atts[$pre.'overlay_cpattern']) : -1;
                    $overlay_path = wp_get_attachment_url($overlay_cpattern);
                    if (isset($overlay_path)) $overlay_style = "background-image: url(".$overlay_path.");";
                }
                else {
                    // $overlay_style = "background-image: url(".get_template_directory_uri()."/assets/img/patterns/".$overlay_pattern.".png);";
                    $overlay_style = "background-image: url(".helper::get_pattern_png($overlay_pattern).");";
                }
                // pattern size
                $overlay_size = isset($atts[$pre.'overlay_size']) ? esc_attr($atts[$pre.'overlay_size']) : "";
                if ($overlay_size != "") {
                    if (strpos($overlay_size, "px") === false) $overlay_size = $overlay_size."px";
                    $overlay_style .= "background-size: ".$overlay_size.";";
                }
                // pattern scroll
                $overlay_scroll = isset($atts[$pre.'overlay_scroll']) ? esc_attr($atts[$pre.'overlay_scroll']) : "";
                if ($overlay_scroll == "fixed") $overlay_style .= "background-attachment: fixed;";
                // pattern opacity
                $opacity = helper::get_opacity($atts, $pre.'overlay_');
                $overlay_style .= "opacity: ".$opacity.";";
                // make pattern overlay layer
                $bg_inline_style .= "#".$bg_id." .vc_bg_overlay_pattern { ".$overlay_style." } ";
                $bg_overlay .= "<div class='vc_bg_overlay_pattern'></div>";
            }

            $bg['inline_style'] .= $bg_inline_style;
            $bg['overlay'] .= $bg_overlay;
            return $bg;
        }

        /*
            seperator params
        */
        public static function seperator_params_vc($pre, $group, $dep_el=false, $dep_val=false) {
            if ($pre != "") $pre = trim($pre, "_")."_";  
            $dependency = array();
            if ($dep_el != false) {
                if ($dep_val == "not_empty")
                    $dependency = array( 'dependency'  => array(
                                            'element' => $dep_el,
                                            'not_empty' => true
                                        ) );
                else
                    $dependency = array( 'dependency'  => array(
                                            'element' => $dep_el,
                                            'value' => $dep_val
                                        ) );
            }
            return array(
                // seperator type
                array_merge(
                    array(
                        "group"         => $group,
                        "type"          => "dropdown",
                        "heading"       => __('Trennelement', 'core'),
                        "param_name"    => $pre."seperator_type",
                        "value"         => array(
                            _x("Kein Trennelement", 'small', 'core') => "",
                            _x("Triangle", 'small', 'core') => "triangle_seperator",
                            _x("Big Triangle", 'small', 'core') => "triangle_big_seperator",
                            _x("Big Triangle Left", 'small', 'core') => "triangle_big_left_seperator",
                            _x("Big Triangle Right", 'small', 'core') => "triangle_big_right_seperator",
                            _x("Half Circle", 'small', 'core') => "circle_seperator",
                            _x("Curve Center", 'small', 'core') => "curve_seperator",
                            _x("Curve Left", 'small', 'core') => "curve_left_seperator",
                            _x("Curve Right", 'small', 'core') => "curve_right_seperator",
                            _x("Tilt Left", 'small', 'core') => "tilt_left_seperator",
                            _x("Tilt Right", 'small', 'core') => "tilt_right_seperator",
                            _x("Waves", 'small', 'core') => "waves_seperator",
                            _x("Clouds", 'small', 'core') => "clouds_seperator",
                            _x("Multi Triangle", 'small', 'core') => "multi_triangle_seperator",
                            // _x("Round Split", 'small', 'core') => "round_split_seperator",
                        ),
                        "class"       => $pre."seperator_type",
                    ), $dependency
                ),
                // seperator settings
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'textfield',
                        'heading'       => __('Höhe', 'core'),
                        'description'   => __('in px', 'core'),
                        'param_name'    => $pre.'seperator_height',
                        'value'         => '60px',
                        'dependency'  => array(
                            'element' => $pre.'seperator_type',
                            'not_empty' => true
                        ),
                        'edit_field_class' => 'vc_col-xs-4',
                    )
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        "type"          => "dropdown",
                        "heading"       => __('Position', 'core'),
                        "param_name"    => $pre."seperator_position",
                        "value"         => array(
                            _x("oben", 'small', 'core') => "",
                            _x("unten", 'small', 'core') => "bottom",
                            _x("oben und unten", 'small', 'core') => "top_bottom",
                            _x("oben und unten asymmetrisch", 'small', 'core') => "top_bottom_asym",
                        ),
                        'dependency'  => array(
                            'element' => $pre.'seperator_type',
                            'not_empty' => true
                        ),
                        'edit_field_class' => 'vc_col-xs-4',
                    )
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        "type"          => "dropdown",
                        "heading"       => __('Ebene (z-Index)', 'core'),
                        "param_name"    => $pre."seperator_zposition",
                        "value"         => array(
                            _x("zwischen Hintergrund und Inhalt", 'small', 'core') => "",
                            _x("über Hintergrund und Inhalt", 'small', 'core') => "1",
                        ),
                        'dependency'  => array(
                            'element' => $pre.'seperator_type',
                            'not_empty' => true
                        ),
                        'edit_field_class' => 'vc_col-xs-4',
                    )
                ),
                // seperator color
                array_merge(
                    array(
                        "group"         => $group,
                        "type"          => "colorselect",
                        "heading"       => __('Farbe', 'core'),
                        "param_name"    => $pre."seperator_colorselect",
                        'dependency'  => array(
                            'element' => $pre.'seperator_type',
                            'not_empty' => true
                        ),
                        'edit_field_class' => 'vc_col-xs-6',
                    )
                ),
                array_merge(
                    array(
                        "group"         => $group,
                        'type'          => 'range',
                        'heading'       => __('Deckkraft <u>des Trenners</u>', 'core'),
                        'param_name'    => $pre.'seperator_opacity',
                        'input_attrs'   => array( "min" => 0, "max" => 100, "step" => 1 ),
                        'label'         => array( "lbl" => "", "unit" => "%" ),
                        'value'         => '100',
                        'dependency'  => array(
                            'element' => $pre.'seperator_type',
                            'not_empty' => true
                        ),
                        'edit_field_class' => 'vc_col-xs-3',
                    )
                )
            );
        }
        public static function make_seperator($atts, $pre, $bg) {
            if ($pre != "") $pre = trim($pre, "_")."_";  

            $bg_id = $bg['id'];
            $bg_inline_style = "";
            $bg_seperator = "";

            $seperator_type = isset($atts[$pre.'seperator_type']) ? esc_attr($atts[$pre.'seperator_type']) : "";
            if ($seperator_type != "") {
                $sep_class = $seperator_type;
                $sep_svg = "";
                $sep_content = "";
                // color
                $seperator_color = helper::get_color($atts, $pre.'seperator_');
                $seperator_color = helper::process_color($seperator_color);
                // size
                $seperator_height = isset($atts[$pre.'seperator_height']) && $atts[$pre.'seperator_height'] != "" ? esc_attr($atts[$pre.'seperator_height']) : "60px";
                if (strpos($seperator_height, "px") === false) $seperator_height = $seperator_height."px";
                // make svg
                $sep_svg = helper::get_seperator_svg($seperator_type, $seperator_color, $seperator_height);
                $bg_inline_style .= "@media (max-width: var(grid_md)) and (min-width: var(grid_sm)) { #".$bg_id." .vc_bg_seperator svg { height: ".( intval(str_replace("px", "", $seperator_height)) / 1.5 )."px; } } ";
                $bg_inline_style .= "@media (max-width: var(grid_sm)) { #".$bg_id." .vc_bg_seperator svg { height: ".( intval(str_replace("px", "", $seperator_height)) / 3 )."px; } } ";
                // position
                $seperator_position = isset($atts[$pre.'seperator_position']) && $atts[$pre.'seperator_position'] != "" ? esc_attr($atts[$pre.'seperator_position']) : "top";
                $seperator_zposition = isset($atts[$pre.'seperator_zposition']) && $atts[$pre.'seperator_zposition'] != "" ? esc_attr($atts[$pre.'seperator_zposition']) : "0";
                if (strpos($seperator_position, "top") !== false) 
                    $sep_content .= "<div class='sep_top' style='z-index:".$seperator_zposition."'>".$sep_svg."</div>";
                if (strpos($seperator_position, "bottom") !== false) {
                    $sep_bclass = "sep_bottom";
                    if (strpos($seperator_position, "asym") !== false) $sep_bclass .= "_mirror";
                    $sep_content .= "<div class='".$sep_bclass."' style='z-index:".$seperator_zposition."'>".$sep_svg."</div>";
                }
                // opacity
                $opacity = helper::get_opacity($atts, $pre.'seperator_color_');
                $sep_style = "style='opacity: ".$opacity."';";
                // make seperator layer
                $bg_seperator .= "<div class='vc_bg_seperator' ".$sep_style.">".$sep_content."</div>";
            }

            $bg['inline_style'] .= $bg_inline_style;
            $bg['seperator'] .= $bg_seperator;
            return $bg;
        }

        /**
         * Trigger actions params for composer setup
         * 
         * @since 0.8.6
         * 
         * @param string $pre           String before the name of each param.
         * @param string $group         VC-Tab to add the options to.
         * @param array  $dependency    Dependency for the options.
         * 
         * @return array
         */
        public static function trigger_action_params_vc($pre="", $group="", $dependency=array()) {
            
            $group  = empty($group) ? __('Trigger Aktionen', 'core') : $group;

            return array(
                array(
                    'type'        => 'checkbox',
                    // 'heading'     => __('Custom Trigger', 'core'),
                    'param_name'  => $pre.'trigger_enable',
                    'value' => array(
                        __('Trigger Aktionen für dieses Modul aktivieren', 'core') => 'enable',
                    ),
                    'description' => __("Platziere einen 'Trigger Button' mithilfe des Button-Moduls auf deiner Seite, um dieses Modul mit Klick auf den Button z.B. ein- und auszublenden.", 'core'),
                    'group'       => $group,
                    'dependency'  => $dependency
                ),
                array(
                    "type"        => 'seperator',
                    'param_name'  => $pre.'seperator',
                    'group'       => $group,
                    'dependency'  => array(
                        'element'   => $pre.'trigger_enable',
                        'value'     => 'enable'
                    ),
                ),
                array(
                    'type'        => 'param_group',
                    'heading'     => __('Aktionen einstellen', 'core'),
                    'param_name'  => $pre.'trigger_options',
                    'group'       => $group,
                    'dependency'  => array(
                        'element'   => $pre.'trigger_enable',
                        'value'     => 'enable'
                    ),
                    'params'      => array(
                        array(
                            'type' => 'textfield',
                            'heading' => __('Trigger Name', 'core'),
                            'description' => __("Gebe deinem Trigger einen eindeutigen Namen zur Referenzierung im Button-Modul.", 'core'),
                            'param_name' => 'name',
                            'admin_label' => true,
                            'edit_field_class' => 'vc_col-xs-6',
                        ),
                        array(
                            "type"          => "dropdown",
                            "heading"       => __('Aktion', 'core'),
                            'description' => __("Was soll beim Auslösen des Triggers mit diesem Modul geschehen?", 'core'),
                            "param_name"    => "action",
                            'admin_label' => true,
                            'edit_field_class' => 'vc_col-xs-6',
                            "value" => array(
                                _x('anzeigen', 'small', 'core') => 'show',
                                _x('ausblenden', 'small', 'core') => 'hide',
                                _x('aus- & einblenden', 'small', 'core') => 'toggle',
                                _x('animiert einblenden', 'small', 'core') => 'fadeIn',
                                _x('animiert ausblenden', 'small', 'core') => 'fadeOut',
                                _x('animiert aus- & einblenden', 'small', 'core') => 'fadeToggle',
                                _x('aufklappen', 'small', 'core') => 'slideDown',
                                _x('zuklappen', 'small', 'core') => 'slideUp',
                                _x('auf- & zuklappen', 'small', 'core') => 'slideToggle',
                            ),
                        ),
                    )
                ),
                array(
                    "type"          => "dropdown",
                    "heading"       => __('Zustand beim Seitenaufruf', 'core'),
                    "param_name"    => $pre."trigger_onload",
                    'edit_field_class' => 'vc_col-xs-6',
                    "value" => array(
                        _x('normal', 'small', 'core') => '',
                        _x('ausgeblendet', 'small', 'core') => 'hide',
                    ),
                    'group'       => $group,
                    'dependency'  => array(
                        'element'   => $pre.'trigger_enable',
                        'value'     => 'enable'
                    ),
                ),
                array(
                    'type'        => 'checkbox',
                    'heading'     => __('Andere Trigger-Elemente', 'core'),
                    'description' => __("Wenn ausgewählt, werden alle benachbarten Trigger-Elemente (z.B. in der gleichen Spalte) ausgeblendet, sobald dieses Element eingeblendet wird.", 'core'),
                    'param_name'  => $pre.'trigger_siblings',
                    'edit_field_class' => 'vc_col-xs-6',
                    'value' => array(
                        __('benachbarte Elemente ausblenden', 'core') => 'hide',
                    ),
                    'group'       => $group,
                    'dependency'  => array(
                        'element'   => $pre.'trigger_enable',
                        'value'     => 'enable'
                    ),
                ),
            );
        }

        /**
         * Get trigger arguments
         * 
         * @since 0.8.7
         * 
         * @param array $atts   All shortcode attributes.
         * @param string $pre   Prefix before the trigger attributes.
         * 
         * @return null|array   array( "click"|"hover" => "greyd_trigger.trigger(event, ... );" )
         */
        public static function get_trigger_events($atts, $pre="") {
            
            $trigger = isset($atts[$pre."trigger_name"]) ? esc_attr($atts[$pre."trigger_name"]) : "";
            if ($trigger === "__custom") {
                $trigger = isset($atts[$pre."custom_trigger_name"]) ? esc_attr($atts[$pre."custom_trigger_name"]) : "";
            }
            $trigger = helper::get_clean_slug($trigger);

            if ( empty($trigger) ) {
                return null;
            }

            /**
             * Events: hover & global
             * 
             * For backward compatibility reasons, this is set via the attribute 'trigger_hover'.
             * The event is triggered on hover, if the value includes the string "true".
             * The event is triggered globally, if the value includes the string "global".
             * Possible values: undefined, "true", "global", "true,global"
             */
            $events     = isset($atts[$pre."trigger_hover"]) ? esc_attr($atts[$pre."trigger_hover"]) : "";
            $event      = strpos($events, "true") !== false ? "hover" : "click";
            $global     = strpos($events, "global") !== false ? "true" : "false";

            // return either atts['click'] or atts['hover']
            return array(
                $event => 'greyd_trigger.trigger(event, "'.$trigger.'", '.$global.')'
            );
        }
        
        /**
         * Render trigger event params
         * 
         * @since 0.8.6
         * 
         * @param array  $atts  All shortcode attributes.
         * @param string $pre   Prefix before the trigger attributes.
         * 
         * @return string       HTML attributes to append to a wrapper.
         */
        public static function make_trigger_action($atts, $pre="") {

            if (!is_array($atts) || !isset($atts[$pre.'trigger_enable']) || $atts[$pre.'trigger_enable'] !== 'enable') {
                return "";
            }
            $html = "";

            $options = isset($atts[$pre.'trigger_options']) ? vc_param_group_parse_atts($atts[$pre.'trigger_options']) : array();
            if ($options && count($options)) {
                $triggers = array();
                foreach($options as $option) {
                    $name   = isset($option['name']) ? helper::get_clean_slug($option['name']) : null;
                    $action = isset($option['action']) ? esc_attr($option['action']) : null;
                    if ( !empty($name) && !empty($action) ) {
                        $triggers[] = $name."|".$action;
                    }
                }
                if (count($triggers)) {
                    $html .= "data-ontrigger='".implode("::", $triggers)."'";
                }

                $onload     = isset($atts[$pre.'trigger_onload']) ? esc_attr($atts[$pre.'trigger_onload']) : "show";
                $html      .= !empty($onload) && $onload !== "show" ? " data-onload='$onload'" : "";

                $siblings   = isset($atts[$pre.'trigger_siblings']) ? esc_attr($atts[$pre.'trigger_siblings']) : "";
                $html      .= $siblings === "hide" ? " data-siblings='$siblings'" : "";
            }

            return $html;
        }

        /*
            color helpers
        */
        public static function get_shadow($atts, $key, $default='none') {
            $shadow = isset($atts[$key]) ? esc_attr($atts[$key]) : $default;
            if ($shadow != 'none') {
                $tmp = explode('+', $shadow);
                $color = $tmp[count($tmp)-2];
                $opacity = $tmp[count($tmp)-1];
                if ($color == 'transparent' || $color == '')
                    $color = array( 'r' => 0, 'g' => 0, 'b' => 0, 'a' => 0);
                else {
                    if (strpos($color, "color_") === 0) {
                        if (count(\processor::$mods) == 0) \processor::process_defaults();
                        $color = \processor::$mods['--'.str_replace("_", "", $color)];
                    }
                    $col = helper::hex2RGB($color);
                    if (!$col) {
                        if ($color == 'transparent' || $color == '')
                            $col = array( 'r' => 0, 'g' => 0, 'b' => 0, 'a' => 0);
                        else $col = helper::rgb2RGB($color);
                    }
                    if (!isset($col['a'])) $col['a'] = 1;
                    $col['a'] = $col['a'] * ($opacity / 100.0);
                    $color = $col;
                }
                $shadowcolor = 'rgba('.$color['r'].','.$color['g'].','.$color['b'].','.$color['a'].')';
                array_pop($tmp);
                array_pop($tmp);
                array_push($tmp, $shadowcolor);
                return implode(' ',$tmp);
            }
            return $shadow;
        }
        public static function get_colorselect($atts, $key, $default='') {
            $color = isset($atts[$key]) ? esc_attr($atts[$key]) : $default;
            if (strpos($color, "color_") === 0) {
                if (count(\processor::$mods) == 0) \processor::process_defaults();
                $color = \processor::$mods['--'.str_replace("_", "", $color)];
            }
            return $color;
        }
        public static function get_color($atts, $pre, $post="", $default='') {
            // debug($atts);
            if (isset($atts[$pre.'colorselect'.$post]) && $atts[$pre.'colorselect'.$post] != "") {
                $color = isset($atts[$pre.'colorselect'.$post]) ? esc_attr($atts[$pre.'colorselect'.$post]) : '';
            }
            else {
                $color = isset($atts[$pre.'color'.$post]) ? esc_attr($atts[$pre.'color'.$post]) : $default;
                if ($color == "color_custom") 
                    $color = isset($atts[$pre.'ccolor'.$post]) ? esc_attr($atts[$pre.'ccolor'.$post]) : '';
            }
            if (strpos($color, "color_") === 0) 
                $color = 'var(--'.str_replace("_", "", $color).')';

            return $color;
        }
        public static function process_color($color) {
            if (strpos($color, "var") !== false) {
                $col = str_replace(array( 'var(', ')' ), '', $color);
                if (count(\processor::$mods) == 0) \processor::process_defaults();
                $col = \processor::$mods[$col];
                return $col;
            }
            else return $color;
        }
        public static function get_opacity($atts, $pre, $post="") {
            $opacity = 1;
            if (isset($atts[$pre.'opacity'.$post])) {
                $op = esc_attr($atts[$pre.'opacity'.$post]);
                $op = str_replace("%", "", $op);
                $opacity = $op/100.0;
            }

            return $opacity;
        }
        public static function get_position($atts, $pre, $post="") {
            $pos = "0%";
            if ($post == "2") $pos = "100%";
            if (isset($atts[$pre.'_gradient_pos'.$post]) && $atts[$pre.'_gradient_pos'.$post] != "") {
                $pos = esc_attr($atts[$pre.'_gradient_pos'.$post]);
                if (strpos($pos, "%") === -1) $pos .= "%";
            }

            return $pos;
        }
        public static function get_gradient2($atts, $pre) {
            // read value
            $gradient_raw = isset($atts[$pre.'gradient2']) ? esc_attr($atts[$pre.'gradient2']) : "scroll|angle|45|color_21:0|color_33:100";
            $tmp = explode('|', $gradient_raw);
            $gradient_array = array( 'type' => $tmp[1], 'angle' => $tmp[2], 'scroll' => $tmp[0], 'colors' => array() );
            // colors
            for ($i=3; $i<count($tmp); $i++) {
                $color = explode(':', $tmp[$i]);
                if (strpos($color[0], "color_") === 0) $color[0] = 'var(--'.str_replace("_", "", $color[0]).')';
                else if ($color[0] == "") $color[0] = 'rgba(255,255,255,0)';
                $gradient_array['colors'][] = array( 'color' => $color[0], 'position' => $color[1] );
            }
            // direction
            $angle = $gradient_array['type'];
            if ($angle == "") $angle = 180;
            else if ($angle == "bottom") $angle = 0;
            else if ($angle == "left") $angle = 90;
            else if ($angle == "right") $angle = 270;
            else $angle = $gradient_array['angle'];
            // make gradient
            $gradient = "";
            for ($i=0; $i<count($gradient_array['colors']); $i++) {
                $gradient .= ', '.$gradient_array['colors'][$i]['color'].' '.$gradient_array['colors'][$i]['position'].'%';
            }
            
            return array( 
                'angle' => $angle, 
                'gradient' => $gradient, 
                'scroll' => $gradient_array['scroll'] 
            );
        }
        public static function get_parallax($atts, $pre) {
            // get data
            $scroll = isset($atts[$pre.'image_scroll']) ? esc_attr($atts[$pre.'image_scroll']) : "";
            if ($scroll == "fixed") {
                $data = " data-vc_bg_parallax_speed='100' data-vc_bg_parallax_enable_mobile='true'";
                $class = "vc_bg_vparallax";
            }
            else {
                $parallax = isset($atts[$pre.'image_parallax']) && $atts[$pre.'image_parallax'] != "" ? esc_attr($atts[$pre.'image_parallax']) : "30";
                $parallax_mobile = $atts[$pre.'image_parallax_mobile'] == "true" ? "true" : "false";
                $data = " data-vc_bg_parallax_speed='".$parallax."' data-vc_bg_parallax_enable_mobile='".$parallax_mobile."'";
                $class = $pre."".$scroll;
            }
            
            return array( 
                'data' => $data, 
                'class' => $class
            );
        }

        /**
         * Get the post excerpt.
         * 
         * If no excerpt exists, trim the content to look like it.
         */
        public static function get_the_excerpt($wp_post, $strip_tags=true) {

            // custom excerpt already attached
            if ( isset($wp_post->excerpt) ) return $wp_post->excerpt;



            // get the default excerpt
            $excerpt = isset($wp_post->post_excerpt) ? $wp_post->post_excerpt : null;
            if ( !empty($excerpt) ) {
                $excerpt = trim( $excerpt );
                if ($strip_tags) {
                    $excerpt =  self::strip_all_tags_and_shortcodes($excerpt);
                }
 
            }

            // default excerpt is empty
            if ( empty($excerpt) ) {

                if ( has_blocks( $wp_post->post_content ) ) {
                    $excerpt = trim( $wp_post->post_content );
                    if ($strip_tags) {
                        $excerpt =  self::strip_all_tags_and_shortcodes($excerpt);
                    }
                } else {
                    $excerpt = self::make_clean_vc_string($wp_post->post_content, 600);
                }
            }
            // trim it
            if ($strip_tags) {
                $excerpt_length = apply_filters('excerpt_length', 55);
                $excerpt_more   = apply_filters('excerpt_more', ' &#91;&hellip;&#93;');
                $excerpt        = wp_trim_words( $excerpt, $excerpt_length, $excerpt_more );
            }

            return $excerpt;
        }

        /**
         * Strip all tags and shortcodes from a string.
         */
        public static function strip_all_tags_and_shortcodes($string) {
            // debug( esc_attr($string) );

            // strip raw_(html|js) shortcodes & stylesheets
            $string = preg_replace( array(
                '/\[vc_raw_.*?\[\/vc_raw_[a-z]+?\]/',
                '/<script[^>]*?>.*?<\/script>/s',
                '/<style[^>]*?>.*?<\/style>/s'
            ), '', $string );

            // strip embed videos, otherwise the url will be shown as text
            $string = preg_replace( '/\<\!\-\- wp\:embed.*?\<\!\-\- \/wp\:embed \-\-\>/s', '', $string );

            // strip normal shortcodes
            $string = preg_replace( '#\[[^\]]+\]#', '', $string );

            // replace breaks with whitespaces
            $string = preg_replace( array( '/<\/h\d>/', '/\n/', '/<br\s?\/?>/' ), ' ', $string );

            // strip all html tags
            $string = strip_tags($string);

            // replace double whitespaces
            $string = preg_replace( '/\s+/', ' ', $string );
            
            return $string;
        }
    }

    if (!function_exists('vc_param_group_parse_atts')) {
        function vc_param_group_parse_atts($atts_string) {
            $array = json_decode( urldecode( $atts_string ), true );
            return $array;
        }
    }
}

namespace {
    /*
        extend visual composer classes
    */
    if ( class_exists( 'WPBakeryShortCodesContainer' ) ) {
        class WPBakeryShortCode_vc_content_box extends \WPBakeryShortCodesContainer {
        }
        class WPBakeryShortCode_vc_list extends \WPBakeryShortCodesContainer {
        }
    }
    if (class_exists("VcShortcodeAutoloader") ) {
        \VcShortcodeAutoloader::getInstance()->includeClass( 'WPBakeryShortCode_VC_Tta_Tabs' );
        \VcShortcodeAutoloader::getInstance()->includeClass( 'WPBakeryShortCode_VC_Tta_Section' );
    }
    /* source: js_composer/include/shortcodes/vc-tta-tabs.php */
    if ( class_exists( 'WPBakeryShortCode_VC_Tta_Tabs' ) ) {
        class WPBakeryShortCode_vc_cond_content extends \WPBakeryShortCode_VC_Tta_Tabs {}
    }
    /* source: js_composer/include/shortcodes/vc-tta-section.php */
    if ( class_exists( 'WPBakeryShortCode_VC_Tta_Section' ) ) {
        class WPBakeryShortCode_vc_cond_content_item extends \WPBakeryShortCode_VC_Tta_Section {}
    }
}