สวัสดีครับผม กลับมาพบกันใหม่กับบทความตอนใหม่ ก่อนหน้านี้ผมเคยเขียนบทความเกี่ยวกับการทำ Shortcode สำหรับ visual composer แบบง่ายๆมาแล้ว และก็รับปากไว้ว่าจะเล่าถึงการเขียนแบบซับซ้อนมากขึ้น ซึ่งวิธีการทำจริงๆก็ไม่ยุ่งยากเท่าไหร่ครับ
สำหรับวิธีการทำครั้งนี้จะเป็นการทำสำหรับข้อมูลที่มีการวนลูปอยู่ภายในครับ เช่น สมมติว่าผมจะทำ shortcode สำหรับทำ Slider ซึ่งแน่นอนว่า มันก็ต้องมี slider อย่างน้อยหนึ่งอันขึ้นไปอยู่ในก้อนเดียวกัน แล้วถ้าจะทำแบบนี้เราจะทำอย่างไร มามะมาดูกันครับ
เช่นเคยครับ อย่างแรก เราต้องเขียน mockup ในรูปแบบ HTML มาให้ได้เสียก่อน อย่างในตัวอย่างนี้ผมจะยกตัวอย่างการทำ Slide ครับ และนี่คือ Demo Mockup ของผม
โดยในภาพด้านบน หนึ่งสไลด์ของผมประกอบไปด้วย
- รูปภาพพื้นหลัง
- ข้อความที่เป็น Head line (Music Fest#2)
- ข้อความ sub text (the rock in your heart will boom!)
- ข้อความบนปุ่ม (Buy ticket)
- ลิงค์สำหรับปุ่ม
โค้ด HTML ก็เขียนประมาณนี้ครับ
<section class="hero-slider"> <ul class="slides"> <!-- วน Loop Slider ตรงนี้ --> <li class="overlay"> <div class="background-image-holder parallax-background"> <img class="background-image" alt="Background Image" src="images/music.jpg"> </div> <div class="container align-vertical"> <div class="row"> <div class="col-md-6 col-sm-9"> <h1 class="text-white">Music Fest#2</h1> <h2 class="sub-text">the rock in your heart will boom!</h2> <a href="#" class="btn btn-primary btn-filled">BUY TICKET</a> </div> </div> </div> </li> <!-- สิ้นสุด Slider หนึ่งอัน --> </ul> </section>
จากโค้ดด้านบนจะเห็นนะครับว่า เราจะมีการใช้งานตรงที่จะวนลูปคือแท็ก <li>…</li> ครับผม
มาดูโค้ดแบบเต็มกันก่อนนะครับ เขียนลงใน functions.php
/** Slider **/ // Shortcode Slider if(!function_exists('box_slider')){ function box_slider( $atts, $content = null ) { return ' <section class="hero-slider"> <ul class="slides"> '.do_shortcode($content).' </ul> </section>'; } add_shortcode('box_slider', 'box_slider'); } if(!function_exists('single_box_slider')) { function single_box_slider( $atts, $content = null) { extract(shortcode_atts(array( 'img' => '', 'headline' => '', 'subtext' => '', 'buttonText' => '', 'link' => '', ), $atts)); $content = wpb_js_remove_wpautop($content, true); $image = wp_get_attachment_image_src( $img, 'full'); $image_src = $image['0']; $output ='<li class="overlay"> <div class="background-image-holder parallax-background"> <img class="background-image" alt="Background Image" src="'.$image_src.'"> </div> <div class="container align-vertical"> <div class="row"> <div class="col-md-6 col-sm-9"> <h1 class="text-white">'.$wording.'</h1> <h2 class="sub-text">'.$subtext.'</h2> <a href="'.$link.'" class="btn btn-primary btn-filled">'.$buttonText.'</a> </div> </div> </div> </li>'; return $output; } add_shortcode('single_box_slider', 'single_box_slider'); } // Mapping vc_map( array( "name" => __("Box Slider", "Learn"), "base" => "box_slider", "as_parent" => array('only' => 'single_box_slider'), "content_element" => true, "show_settings_on_create" => false, "is_container" => true, "js_view" => 'VcColumnView', "category" =>array('Learn', 'Content') ) ); vc_map( array( "name" => __("Single Slider Content", "Learn"), "base" => "single_box_slider", "content_element" => true, "as_child" => array('only' => 'box_slider'), "show_settings_on_create" => true, "params" => array( array( 'type' => 'attach_image', 'heading' => __( 'Add Image', 'Learn' ), 'param_name' => 'img', ), array( "type" => "textfield", "holder" => "div", "class" => "", "heading" => __( "ข้อความบน Slide", "my-text-domain" ), "param_name" => "headline", "value" => __( "ใส่ข้อความตรงนี้", "my-text-domain" ), "description" => __( "ช่องสำหรับพิมพ์ข้อความที่อยู่บน slider", "my-text-domain" ) ), array( "type" => "textfield", "holder" => "div", "class" => "", "heading" => __( "ข้อความ Subtext บน Slide", "my-text-domain" ), "param_name" => "subtext", "value" => __( "ใส่ข้อความตรงนี้", "my-text-domain" ), "description" => __( "ช่องสำหรับพิมพ์ข้อความที่อยู่บน slider", "my-text-domain" ) ), array( "type" => "textfield", "holder" => "div", "class" => "", "heading" => __( "ข้อความบนปุ่ม", "my-text-domain" ), "param_name" => "buttonText", "value" => __( "ใส่ข้อความตรงนี้", "my-text-domain" ), "description" => __( "ช่องสำหรับพิมพ์ข้อความที่อยู่บนปุ่ม", "my-text-domain" ) ), array( "type" => "textfield", "holder" => "div", "class" => "", "heading" => __( "URL", "my-text-domain" ), "param_name" => "link", "value" => __( "ใส่ลิงค์สำหรับ ปุ่มบน Slider", "my-text-domain" ), "description" => __( "ช่องสำหรับใส่ลิงค์ของ slider", "my-text-domain" ) ), ), ) ); if ( class_exists( 'WPBakeryShortCodesContainer' ) ) { class WPBakeryShortCode_Box_Slider extends WPBakeryShortCodesContainer { } } if ( class_exists( 'WPBakeryShortCode' ) ) { class WPBakeryShortCode_Single_Box_Slider extends WPBakeryShortCode { } }
[thetext]คำอธิบาย[/thetext]
เราจะแยกข้อมูลออกเป็นสองส่วนครับ คือส่วนของ “โครงสร้างหลัก” และ “เนื้อหาข้างในที่รูปแบบซ้ำกัน” โดยตัวโครงสร้างหลักนั้น ก็จะเป็นบรรทัดที่ 8 ถึงบรรทัดที่ 12 ครับ สังเกตดูนะครับว่า เราจะเขียนถึงแค่ <ul> เท่านั้น และข้างในโครงสร้างหลัก ก็ใช้คำสั่ง do_shortcode($content) เพื่อเรียกเนื้อหาที่เป็นรูปแบบซ้ำๆมาแสดงผลตรงบรรทัดที่ 10
extract(shortcode_atts(array( 'img' => '', 'headline' => '', 'subtext' => '', 'buttonText' => '', 'link' => '',
โค้ดด้านบนเป็นการ extract ค่าที่ได้มาเก็บไว้ในตัวแปรเพื่อเตรียมไปใช้งานต่อครับ (บรรทัดที่ 21 ถึงบรรทัดที่ 28 ในโค้ดชุดเต็ม)
$content = wpb_js_remove_wpautop($content, true); $image = wp_get_attachment_image_src( $img, 'full'); $image_src = $image['0']; $output ='<li class="overlay"> <div class="background-image-holder parallax-background"> <img class="background-image" alt="Background Image" src="'.$image_src.'"> </div> <div class="container align-vertical"> <div class="row"> <div class="col-md-6 col-sm-9"> <h1 class="text-white">'.$wording.'</h1> <h2 class="sub-text">'.$subtext.'</h2> <a href="'.$link.'" class="btn btn-primary btn-filled">'.$buttonText.'</a> </div> </div> </div> </li>'; return $output;
โค้ดด้านบนเป็นการเอาตัวแปรที่ได้มาใช้ร่วมกับโค้ด HTML ของเราครับ ก็แปะๆไป ใช้งานง่ายมากครับ เป็นการเชื่อมสตริงแบบปกติ
// Mapping vc_map( array( "name" => __("Box Slider", "Learn"), "base" => "box_slider", "as_parent" => array('only' => 'single_box_slider'), "content_element" => true, "show_settings_on_create" => false, "is_container" => true, "js_view" => 'VcColumnView', "category" =>array('Learn', 'Content') ) ); vc_map( array( "name" => __("Single Slider Content", "Learn"), "base" => "single_box_slider", "content_element" => true, "as_child" => array('only' => 'box_slider'), "show_settings_on_create" => true, "params" => array( array( 'type' => 'attach_image', 'heading' => __( 'Add Image', 'Learn' ), 'param_name' => 'img', ), array( "type" => "textfield", "holder" => "div", "class" => "", "heading" => __( "ข้อความบน Slide", "my-text-domain" ), "param_name" => "headline", "value" => __( "ใส่ข้อความตรงนี้", "my-text-domain" ), "description" => __( "ช่องสำหรับพิมพ์ข้อความที่อยู่บน slider", "my-text-domain" ) ), array( "type" => "textfield", "holder" => "div", "class" => "", "heading" => __( "ข้อความ Subtext บน Slide", "my-text-domain" ), "param_name" => "subtext", "value" => __( "ใส่ข้อความตรงนี้", "my-text-domain" ), "description" => __( "ช่องสำหรับพิมพ์ข้อความที่อยู่บน slider", "my-text-domain" ) ), array( "type" => "textfield", "holder" => "div", "class" => "", "heading" => __( "ข้อความบนปุ่ม", "my-text-domain" ), "param_name" => "buttonText", "value" => __( "ใส่ข้อความตรงนี้", "my-text-domain" ), "description" => __( "ช่องสำหรับพิมพ์ข้อความที่อยู่บนปุ่ม", "my-text-domain" ) ), array( "type" => "textfield", "holder" => "div", "class" => "", "heading" => __( "URL", "my-text-domain" ), "param_name" => "link", "value" => __( "ใส่ลิงค์สำหรับ ปุ่มบน Slider", "my-text-domain" ), "description" => __( "ช่องสำหรับใส่ลิงค์ของ slider", "my-text-domain" ) ),
โค้ดชุดนี้เป็นการสร้างฟิลด์สำหรับรับข้อมูล ของ “โครงสร้างภายในที่มีการใช้งานซ้ำๆกัน” ครับ โดยวิธีการเขียนก็เหมือนกับบทความด้านบนที่ผมแปะให้ครับ พวกคำอธิบายโค้ดชุดนี้สามารถอ่านได้จากบทความก่อนหน้านี้ได้เลย โดยบรรทัดที่สำคัญคือบรรทัดที่เขียนว่า
"base" => "box_slider",
เพราะเป็นการบอกให้รู้ว่าตัวฟิลด์พวกนี้จะใช้งานเป็นโครงสร้างภายในของโครงสร้างหลักตัวไหน อย่างของผมโครงสร้างหลักมีชื่อว่า box_slider นั่นเอง
สำหรับชื่อฟังก์ชั่นต่างๆนั้นก็ให้เราแก้ไขเป็นของเราเองได้เลยนะครับ ลองดูโค้ดตัวอย่างของผมแล้วนำไปปรับแต่งต่อดูครับ ไม่ยากๆ ลองทำแบบง่ายๆดูก่อนแล้วจะเข้าใจมากยิ่งขึ้นครับผม
และนี่แหละครับคือวิธีการเขียน Shortcode สำหรับ visual composer แบบ Nested หากอยากรู้เพิ่มเติมลองอ่านที่บทความของ Visual Composer ได้นะครับ ที่ลิงค์นี้ครับ แล้วเจอกันใหม่บทความหน้าครับ
https://wpbakery.atlassian.net/wiki/pages/viewpage.action?pageId=524362