大家好,我是 Eric。
我們在昨天透過短代碼 (shortcode) 的機制,客製化投影片輪播。今天,我們要再透過勾點 (hook) 機制,來替自己的聯絡表單外掛 Contact Form 7 加上台灣縣市選單的功能。
上網搜尋「郵遞區號 javascript」後,我們可以看到有熱心網友提供的 JavaScript 函式庫,如 jQuery TWZipcode 或 TW City Selector。我們這邊以 TW City Selector 為例進行。
根據 Contact Form 7 的官方文件,我們需要透過 wpcf7_init
這個勾點。以今天的例子,我們要加入 address
這個元素:
首先,我們先使用 wpcf7_init
這個勾點,註冊我們想要的標籤名稱。舉例來說 [address]
與必填欄位的 [adress*]
。
add_action( 'wpcf7_init', 'wpcf7_add_address_tag' );
function wpcf7_add_address_tag() {
wpcf7_add_form_tag(
array( 'address', 'address*' ),
'wpcf7_add_address_tag_handler',
array( 'name-attr' => true )
);
}
接著,我們透過類似 wp_enqueue_scripts
的勾點 wpcf7_enqueue_scripts
來引用 TW City Selector 的函式庫。
add_action( 'wpcf7_enqueue_scripts', 'wpcf7_address_script' );
function wpcf7_address_script() {
wp_enqueue_script( 'address-picker', 'https://cdn.jsdelivr.net/npm/tw-city-selector@2.1.1/dist/tw-city-selector.min.js', array( 'jquery' ) );
}
我們在第一步註冊標籤的時候,wpcf7_add_form_tag
的第二個參數 'wpcf7_add_address_tag_handler'
指的就是轉譯來顯示前端 HTML 代碼的方法,以下用註解的方式介紹各程式碼的意涵:
function wpcf7_add_address_tag_handler( $tag ) {
/* 如果沒有定義 name 這個屬性,就不會出現內容。 */
if ( empty( $tag->name ) ) {
return '';
}
/* 顯示 Contact Form 7 的錯誤訊息 */
$validation_error = wpcf7_get_validation_error( $tag->name );
/* 如果有定義 CSS 類型的話,顯示 CSS 類型 */
$class = wpcf7_form_controls_class( $tag->type );
/* 加入 wpcf7-validates-as-text 這個 CSS 類型 */
$class .= ' wpcf7-validates-as-text';
/* 如果回傳錯誤,新增 wpcf7-validates-as-text 這個 CSS 類型 */
if ( $validation_error ) {
$class .= ' wpcf7-not-valid';
}
/* 將相關類型以 $atts 這個變數儲存,方便 */
$atts = array();
$atts['class'] = $tag->get_class_option( $class );
$atts['id'] = $tag->get_id_option();
if ( $tag->has_option( 'readonly' ) ) {
$atts['readonly'] = 'readonly';
}
if ( $tag->is_required() ) {
$atts['aria-required'] = 'true';
}
$value = (string) reset( $tag->values );
$atts['aria-invalid'] = $validation_error ? 'true' : 'false';
if ( $tag->has_option( 'placeholder' ) || $tag->has_option( 'watermark' ) ) {
$atts['placeholder'] = $value;
$value = '';
}
$value = $tag -> get_default_option( $value );
$value = wpcf7_get_hangover( $tag->name, $value );
$atts['value'] = $value;
if ( wpcf7_support_html5() ) {
$atts['type'] = $tag->basetype;
} else {
$atts['type'] = 'text';
}
$atts['name'] = $tag->name;
/* 將 $atts 從陣列的型別,轉換為格式化後的字串 */
$atts = wpcf7_format_atts( $atts );
/* 開始拼裝 HTML 元素 */
/* TW City Selector 的基本標籤 */
$html = '<div role="tw-city-selector" data-has-zipcode></div>';
/* 讓使用者填寫詳細地址 */
$html .= '<input id="street" type="text" class="street" placeholder="OO 路 O 段 O 號 O 樓" />';
/* 這才是實際要回傳的欄位,等等用 jQuery 的方式來組合完整地址 */
$html .= sprintf( '<span class="wpcf7-form-control-wrap %1$s"><input id="address-string" %2$s hidden/>%3$s</span>',
sanitize_html_class( $tag->name ),
$atts,
$validation_error
);
return $html;
}
因為我們實際上要傳遞的資料是來自 #address-string
這個隱藏的欄位,因此我們利用 jQuery,當偵測到使用者填寫詳細地址 (#street
) 的時候,自動將郵遞區號 (.zipcode
)、縣市 (.county
)、鄉鎮市區 (.district
) 與詳細地址 (#street
) 連接起來,拼成完整的地址。
add_action( 'wp_footer', 'wpcf7_address_inline_script' );
function wpcf7_address_inline_script() { ?>
<script id="tw-selector">
new TwCitySelector();
(function($){
$("document").ready( function() {
$("#street").change(function() {
$("#address-string").val($( ".zipcode" ).val() + $(".county").val() + $(".district").val() + $(".street").val());
});
})
})(jQuery);
</script>
<?php }
利用 wpcf7_validate_{tag name}
的勾點,來驗證是否為必填欄位,如果必填欄位沒有值,則會顯示錯誤訊息。
add_filter( 'wpcf7_validate_address', 'wpcf7_address_validation_filter', 10, 2 );
add_filter( 'wpcf7_validate_address*', 'wpcf7_address_validation_filter', 10, 2 );
function wpcf7_address_validation_filter( $result, $tag ) {
$name = $tag->name;
$value = isset( $_POST[$name] )
? trim( wp_unslash( strtr( (string) $_POST[$name], "\n", " " ) ) )
: '';
if ( $tag->is_required() and '' === $value ) {
$result->invalidate( $tag, wpcf7_get_message( 'invalid_required' ) );
}
return $result;
}
今天沒有多餘的介紹,是直接透過程式碼說明我們如何利用勾點 (hook) 的方式,直接擴充 Contact Form 7 的功能。是的,WordPress 透過勾點的機制,不僅能夠讓我們在巨人的肩膀上看得更遠,我們也可以在自己開發的外掛中,讓自己也成為另一個小巨人的肩膀。
除了可以透過勾點的方式來進行客製化外,我們也可以藉由 WordPress 內部的作法,自行定義 AJAX 所需使用的端點,來製作無限捲動的功能。明天的主題,我們將透過實作無限捲動的方式,說明自訂 AJAX 端點的方法。
(有關 AJAX 的介紹,可以參考第 18 天的文章。)
Adding a custom form-tag
Using values from a form-tag
Custom validation