Changeset 3724996
- Timestamp:
- 10/02/2026 02:44:32 PM (3 weeks ago)
- Location:
- hatatate
- Files:
-
- 8 edited
- 1 copied
-
tags/1.1.1 (copied) (copied from hatatate/trunk )
-
tags/1.1.1/admin/js/hatatate-placements.js (modified) (5 diffs)
-
tags/1.1.1/hatatate.php (modified) (2 diffs)
-
tags/1.1.1/includes/class-hatatate-engine.php (modified) (12 diffs)
-
tags/1.1.1/readme.txt (modified) (2 diffs)
-
trunk/admin/js/hatatate-placements.js (modified) (5 diffs)
-
trunk/hatatate.php (modified) (2 diffs)
-
trunk/includes/class-hatatate-engine.php (modified) (12 diffs)
-
trunk/readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
hatatate/tags/1.1.1/admin/js/hatatate-placements.js
r3721496 r3724996 316 316 317 317 // ハイライト要素を作成して iframe 内の適切な位置に挿入する 318 function _insertHighlight(iframeDoc, rule, contentArea) { 318 // tails: 位置ごとに最後に描いた枠。同じ位置の 2 つ目以降はその直後に入れて、並べ替えの順(上から順)に並べる(記事の側と同じ) 319 function _insertHighlight(iframeDoc, rule, contentArea, tails) { 319 320 var hl = _createHighlight(iframeDoc, [{ name: rule.name, id: rule.id }], rule.preset, rule.alignment); 320 321 var preset = rule.preset; … … 323 324 hl.style.textAlign = rule.alignment || 'center'; 324 325 } 326 327 var tail = (tails && preset !== 'modal' && preset !== 'fixed_button') ? tails[preset] : null; 328 if (tail && tail.parentNode) { 329 tail.parentNode.insertBefore(hl, tail.nextSibling); 330 tails[preset] = hl; 331 return; 332 } 333 // モーダル・固定ボタンは重なり順が同じなので、後ろに置いたものが手前に見える。 334 // 記事の側と同じく並びで上のものを手前に見せるため、同じ隅の 2 つ目以降は前の枠より前に置く 335 var corner = null; 336 if (preset === 'modal') { 337 var anim = rule.modal_animation || 'slide_right'; 338 corner = 'modal:' + (anim === 'slide_right' || anim === 'slide_left' ? anim : 'center'); 339 } else if (preset === 'fixed_button') { 340 corner = 'fixed_button'; 341 } 342 var front = (tails && corner) ? tails[corner] : null; 325 343 326 344 if (preset === 'before_content') { … … 344 362 hl.style.cssText += ';position:fixed;bottom:' + modalBottom + ';right:16px;max-width:280px;margin:0;z-index:9999;'; 345 363 } 346 if rameDoc.body.appendChild(hl);364 if (front && front.parentNode) front.parentNode.insertBefore(hl, front); else iframeDoc.body.appendChild(hl); 347 365 } else if (preset === 'fixed_button') { 348 366 hl.style.cssText += ';position:fixed;bottom:0;left:0;right:0;margin:0;border-radius:0;border-left:none;border-right:none;border-bottom:none;z-index:9999;'; 349 if rameDoc.body.appendChild(hl);367 if (front && front.parentNode) front.parentNode.insertBefore(hl, front); else iframeDoc.body.appendChild(hl); 350 368 } else { 351 369 // カスタム配置位置 … … 361 379 } 362 380 } 381 } 382 if (tails && hl.parentNode) { 383 tails[corner || preset] = hl; 363 384 } 364 385 } … … 619 640 ? window.hatatateDeviceMatches 620 641 : function () { return true; }; 642 var tails = {}; 621 643 _buildRules().forEach(function (rule) { 622 644 // 「PC のみ」「スマホのみ」の配置は、いま見ている側に出るものだけ描く 623 645 if (!matches(rule.device, previewDevice)) { return; } 624 _insertHighlight(iframeDoc, rule, contentArea );646 _insertHighlight(iframeDoc, rule, contentArea, tails); 625 647 }); 626 648 } -
hatatate/tags/1.1.1/hatatate.php
r3724488 r3724996 4 4 * Plugin URI: https://border-haze.co.jp/tools/hatatate/ 5 5 * Description: Place a call-to-action (banner or text) on every post, run an A/B test, and read the report. No per-post editing. 6 * Version: 1.1. 06 * Version: 1.1.1 7 7 * Requires at least: 6.0 8 8 * Requires PHP: 7.4 … … 19 19 } 20 20 21 define( 'HATATATE_VERSION', '1.1. 0' );21 define( 'HATATATE_VERSION', '1.1.1' ); 22 22 define( 'HATATATE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 23 23 define( 'HATATATE_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); -
hatatate/tags/1.1.1/includes/class-hatatate-engine.php
r3721496 r3724996 551 551 552 552 /** 553 * 同じ位置に先に入れたバナーがあれば、その直後に入れる(並べ替えの順を記事でも保つ) 554 * 555 * 「本文の前」「要素の後」「要素の中の先頭」は、毎回同じ場所に入れると後から入れたものが上に来てしまう。 556 * 2 つ目以降を前のバナーの末尾の直後に入れれば、どの挿入方法でも上から順に並ぶ。 557 * 558 * @param array $tails 位置ごとに最後に入れたバナーの末尾の要素 559 * @param string $key 位置 560 * @param DOMDocumentFragment $fragment 入れるバナー 561 * @return bool 入れたら true(先に入れたものが無ければ何もしないで false) 562 */ 563 private static function insert_after_tail( $tails, $key, $fragment ) { 564 if ( empty( $tails[ $key ] ) || ! $tails[ $key ]->parentNode ) { 565 return false; 566 } 567 $tail = $tails[ $key ]; 568 if ( $tail->nextSibling ) { 569 $tail->parentNode->insertBefore( $fragment, $tail->nextSibling ); 570 } else { 571 $tail->parentNode->appendChild( $fragment ); 572 } 573 return true; 574 } 575 576 /** 553 577 * HTML の中で目印に一致する要素の数(「他の記事でも見つかるか」の判定に使う) 554 578 * … … 951 975 952 976 // モーダルウィンドウ・固定ボタン挿入 977 // HTML は並べ替えの順のまま出し、同じ隅で重なるものは並びで上のものを手前に見せる(2 つ目以降の重なり順を 1 つずつ下げる) 978 $stack = array(); 953 979 foreach ( $this->overlay_rules_for_preset( 'modal' ) as $rule_item ) { 954 self::print_cta_html( $this->render_modal_html( $rule_item ) ); 955 } 980 $corner = self::modal_corner( $rule_item ); 981 $stack[ $corner ] = isset( $stack[ $corner ] ) ? $stack[ $corner ] + 1 : 0; 982 self::print_cta_html( $this->render_modal_html( $rule_item, $stack[ $corner ] ) ); 983 } 984 $below = 0; 956 985 foreach ( $this->overlay_rules_for_preset( 'fixed_button' ) as $rule_item ) { 957 self::print_cta_html( $this->render_fixed_button_html( $rule_item ) );986 self::print_cta_html( $this->render_fixed_button_html( $rule_item, $below++ ) ); 958 987 } 959 988 } … … 1035 1064 $modified = false; 1036 1065 1066 // 同じ位置に 2 つ以上あるときは、配置パターンの並び(上から順)のとおりに出す。 1067 // $nth: 同じ位置の何番目か(二重防止の目印を 1 つずつ分ける) 1068 // $loc_targets: 位置ごとの目印の要素(2 つ目以降も最初に見つけた要素を使う。先に入れたバナーの中の要素に当たらないように) 1069 // $loc_tails: 位置ごとに最後に入れたバナーの末尾(2 つ目以降はその直後に入れる) 1070 $nth = array(); 1071 $loc_targets = array(); 1072 $loc_tails = array(); 1073 1037 1074 foreach ( $all_rules as $rule_item ) { 1038 1075 // cta_id が空でも、ABテストとしてフラグが立っていればスキップしない … … 1041 1078 } 1042 1079 1043 $p_id = isset( $rule_item['pattern_id'] ) ? $rule_item['pattern_id'] : 'tmp'; 1044 $preset = isset( $rule_item['placement_preset'] ) ? $rule_item['placement_preset'] : 'custom'; 1045 $mark = $p_id . '_' . $preset; 1080 $p_id = isset( $rule_item['pattern_id'] ) ? $rule_item['pattern_id'] : 'tmp'; 1081 $preset = isset( $rule_item['placement_preset'] ) ? $rule_item['placement_preset'] : 'custom'; 1082 $loc_key = ( $preset === 'custom' ) ? self::get_placement_key( $rule_item ) : $preset; 1083 $mark = $p_id . '_' . $loc_key; 1084 $nth[ $mark ] = isset( $nth[ $mark ] ) ? $nth[ $mark ] + 1 : 1; 1085 $mark .= '_' . $nth[ $mark ]; 1046 1086 1047 1087 // サイドバー・フッター・オーバーレイは別フックで処理するためスキップ … … 1051 1091 } 1052 1092 1053 // すでにこのリクエストで挿入済みの パターン(位置)であればスキップ(重複表示対策)1093 // すでにこのリクエストで挿入済みの配置(パターン・位置・同じ位置の何番目か)であればスキップ(重複表示対策) 1054 1094 if ( isset( self::$injected_marks[ $mark ] ) ) { 1055 1095 continue; … … 1061 1101 } 1062 1102 1103 $tail = $fragment->lastChild; 1104 1063 1105 if ( $preset === 'before_content' ) { 1064 // 本文前: 最初の要素の前に挿入 1106 // 本文前: 最初の要素の前に挿入(同じ位置の 2 つ目以降は、前のバナーの直後) 1065 1107 if ( $body ) { 1066 // $body->firstChild が null でも insertBefore(..., null) は appendChild と同様に機能し、結果的に先頭になる 1067 $body->insertBefore( $fragment, $body->firstChild ); 1108 if ( ! self::insert_after_tail( $loc_tails, $loc_key, $fragment ) ) { 1109 // $body->firstChild が null でも insertBefore(..., null) は appendChild と同様に機能し、結果的に先頭になる 1110 $body->insertBefore( $fragment, $body->firstChild ); 1111 } 1112 $loc_tails[ $loc_key ] = $tail; 1068 1113 $modified = true; 1069 1114 self::$injected_marks[ $mark ] = true; … … 1104 1149 } 1105 1150 1106 $target_node = self::find_location_target( $xpath, $loc_def ); 1151 if ( ! isset( $loc_targets[ $loc_key ] ) ) { 1152 $loc_targets[ $loc_key ] = self::find_location_target( $xpath, $loc_def ); 1153 } 1154 $target_node = $loc_targets[ $loc_key ]; 1107 1155 if ( $target_node ) { 1108 1156 $position = ( ! empty( $loc_def['position'] ) ) ? $loc_def['position'] : 'before'; 1109 self::insert_fragment( $target_node, $fragment, $position ); 1157 if ( ! self::insert_after_tail( $loc_tails, $loc_key, $fragment ) ) { 1158 self::insert_fragment( $target_node, $fragment, $position ); 1159 } 1160 $loc_tails[ $loc_key ] = $tail; 1110 1161 $modified = true; 1111 1162 self::$injected_marks[ $mark ] = true; … … 1546 1597 } 1547 1598 1599 /** モーダルの重なり順の基準(1.1.0 から同じ値。同じ隅の 1 つ目はこの値のまま) */ 1600 const MODAL_Z_INDEX = 99999; 1601 1602 /** 固定ボタンの重なり順の基準(public/css/hatatate-front.css の .hatatate-fixed-bar と同じ値) */ 1603 const FIXED_Z_INDEX = 9990; 1604 1605 /** 1606 * モーダルが出る隅(重なり順を数える単位): 'right'(右下)/ 'left'(左下)/ 'center'(画面の中央) 1607 * 1608 * render_modal_html() と同じ分け方。知らない値は中央のフェードインで描くので 'center'。 1609 */ 1610 public static function modal_corner( $rule_item ) { 1611 $animation = isset( $rule_item['modal_animation'] ) ? $rule_item['modal_animation'] : 'slide_right'; 1612 if ( $animation === 'slide_right' ) { 1613 return 'right'; 1614 } 1615 return ( $animation === 'slide_left' ) ? 'left' : 'center'; 1616 } 1617 1548 1618 /** 1549 1619 * モーダルウィンドウ用の HTML を生成する(動きは public/js/hatatate-front.js。ここは data 属性だけ) 1550 */ 1551 private function render_modal_html( $rule_item ) { 1620 * 1621 * @param array $rule_item 配置 1 件 1622 * @param int $below 同じ隅で、並びでこれより上にあるモーダルの数(その数だけ重なり順を下げ、上のものを手前に見せる) 1623 */ 1624 private function render_modal_html( $rule_item, $below = 0 ) { 1552 1625 $cta_html = $this->render_cta_html( $rule_item ); 1553 1626 if ( empty( $cta_html ) ) { … … 1591 1664 // 角丸や地は CTA 側が持つ。上に空けた帯は閉じるボタンの置き場所で、見た目には出ない。 1592 1665 $width_css = self::modal_width_css( $rule_item ); 1666 $z_index = self::MODAL_Z_INDEX - max( 0, (int) $below ); 1593 1667 // box-sizing は CSS ファイル(.hatatate-modal-box)に置く。 1594 1668 // WordPress の wp_kses は style 属性に書ける CSS を許可リストで絞っていて、box-sizing は入っていない 1595 1669 $box_base = 'position:relative;padding-top:' . self::MODAL_CLOSE_LANE . 'px;' . $width_css; 1596 1670 if ( $animation === 'slide_right' ) { 1597 $overlay_style = 'display:none;position:fixed;bottom:' . $modal_bottom . 'px;right:20px;z-index: 99999;';1671 $overlay_style = 'display:none;position:fixed;bottom:' . $modal_bottom . 'px;right:20px;z-index:' . $z_index . ';'; 1598 1672 $box_style = $box_base; 1599 1673 $display_val = 'block'; 1600 1674 $click_overlay = false; 1601 1675 } elseif ( $animation === 'slide_left' ) { 1602 $overlay_style = 'display:none;position:fixed;bottom:' . $modal_bottom . 'px;left:20px;z-index: 99999;';1676 $overlay_style = 'display:none;position:fixed;bottom:' . $modal_bottom . 'px;left:20px;z-index:' . $z_index . ';'; 1603 1677 $box_style = $box_base; 1604 1678 $display_val = 'block'; … … 1607 1681 // fade_in: 全画面中央(後ろのページを伏せる暗い層は残す。これは CTA の外枠ではない) 1608 1682 // inset も許可リストに入っていないので、上下左右を 1 つずつ書く 1609 $overlay_style = 'display:none;position:fixed;top:0;right:0;bottom:0;left:0;background:rgba(0,0,0,.55);z-index: 99999;align-items:center;justify-content:center;';1683 $overlay_style = 'display:none;position:fixed;top:0;right:0;bottom:0;left:0;background:rgba(0,0,0,.55);z-index:' . $z_index . ';align-items:center;justify-content:center;'; 1610 1684 $box_style = $box_base; 1611 1685 $display_val = 'flex'; … … 1631 1705 /** 1632 1706 * 固定ボタン(画面下部バー)用の HTML を生成する(動きは public/js/hatatate-front.js) 1633 */ 1634 private function render_fixed_button_html( $rule_item ) { 1707 * 1708 * @param array $rule_item 配置 1 件 1709 * @param int $below 並びでこれより上にある固定ボタンの数。1 以上なら重なり順を CSS の値からその数だけ下げる 1710 * (固定ボタンはどれも画面の下端に出るので、同じ高さなら並びで上のものだけが見える) 1711 */ 1712 private function render_fixed_button_html( $rule_item, $below = 0 ) { 1635 1713 $cta_html = $this->render_cta_html( $rule_item ); 1636 1714 if ( empty( $cta_html ) ) { … … 1658 1736 $close_btn = '<button type="button" class="hatatate-fixed-close-btn" aria-label="閉じる">✕</button>'; 1659 1737 1660 $html = '<div id="' . $uid . '" class="' . esc_attr( 'hatatate-fixed-bar' . self::device_class_suffix( $rule_item ) ) . '" style="background:' . $bg_rgba . '; display:block; "' . $hide_attr . '>'1738 $html = '<div id="' . $uid . '" class="' . esc_attr( 'hatatate-fixed-bar' . self::device_class_suffix( $rule_item ) ) . '" style="background:' . $bg_rgba . '; display:block;' . ( $below > 0 ? ' z-index:' . (int) ( self::FIXED_Z_INDEX - $below ) . ';' : '' ) . '"' . $hide_attr . '>' 1661 1739 . '<div class="hatatate-fixed-bar-inner">' 1662 1740 . $close_btn -
hatatate/tags/1.1.1/readme.txt
r3724488 r3724996 4 4 Requires at least: 6.0 5 5 Tested up to: 7.1 6 Stable tag: 1.1. 06 Stable tag: 1.1.1 7 7 Requires PHP: 7.4 8 8 License: GPLv2 or later … … 117 117 == Changelog == 118 118 119 = 1.1.1 = 120 * Fix: when two or more CTAs were placed at the same position inside the post (before the content, after the content, or a custom position), only the first one was shown. All of them are now shown, in the order you arrange them in the placement pattern. The preview on the placement screen shows the same order. 121 * When two or more modals appear in the same corner, or two or more fixed buttons appear at the bottom of the screen, the one placed higher in the placement pattern is now shown in front. 122 119 123 = 1.1.0 = 120 124 * The Home tab has a short news box at the bottom with tips and news. Its text ships with the plugin; nothing is loaded from outside. -
hatatate/trunk/admin/js/hatatate-placements.js
r3721496 r3724996 316 316 317 317 // ハイライト要素を作成して iframe 内の適切な位置に挿入する 318 function _insertHighlight(iframeDoc, rule, contentArea) { 318 // tails: 位置ごとに最後に描いた枠。同じ位置の 2 つ目以降はその直後に入れて、並べ替えの順(上から順)に並べる(記事の側と同じ) 319 function _insertHighlight(iframeDoc, rule, contentArea, tails) { 319 320 var hl = _createHighlight(iframeDoc, [{ name: rule.name, id: rule.id }], rule.preset, rule.alignment); 320 321 var preset = rule.preset; … … 323 324 hl.style.textAlign = rule.alignment || 'center'; 324 325 } 326 327 var tail = (tails && preset !== 'modal' && preset !== 'fixed_button') ? tails[preset] : null; 328 if (tail && tail.parentNode) { 329 tail.parentNode.insertBefore(hl, tail.nextSibling); 330 tails[preset] = hl; 331 return; 332 } 333 // モーダル・固定ボタンは重なり順が同じなので、後ろに置いたものが手前に見える。 334 // 記事の側と同じく並びで上のものを手前に見せるため、同じ隅の 2 つ目以降は前の枠より前に置く 335 var corner = null; 336 if (preset === 'modal') { 337 var anim = rule.modal_animation || 'slide_right'; 338 corner = 'modal:' + (anim === 'slide_right' || anim === 'slide_left' ? anim : 'center'); 339 } else if (preset === 'fixed_button') { 340 corner = 'fixed_button'; 341 } 342 var front = (tails && corner) ? tails[corner] : null; 325 343 326 344 if (preset === 'before_content') { … … 344 362 hl.style.cssText += ';position:fixed;bottom:' + modalBottom + ';right:16px;max-width:280px;margin:0;z-index:9999;'; 345 363 } 346 if rameDoc.body.appendChild(hl);364 if (front && front.parentNode) front.parentNode.insertBefore(hl, front); else iframeDoc.body.appendChild(hl); 347 365 } else if (preset === 'fixed_button') { 348 366 hl.style.cssText += ';position:fixed;bottom:0;left:0;right:0;margin:0;border-radius:0;border-left:none;border-right:none;border-bottom:none;z-index:9999;'; 349 if rameDoc.body.appendChild(hl);367 if (front && front.parentNode) front.parentNode.insertBefore(hl, front); else iframeDoc.body.appendChild(hl); 350 368 } else { 351 369 // カスタム配置位置 … … 361 379 } 362 380 } 381 } 382 if (tails && hl.parentNode) { 383 tails[corner || preset] = hl; 363 384 } 364 385 } … … 619 640 ? window.hatatateDeviceMatches 620 641 : function () { return true; }; 642 var tails = {}; 621 643 _buildRules().forEach(function (rule) { 622 644 // 「PC のみ」「スマホのみ」の配置は、いま見ている側に出るものだけ描く 623 645 if (!matches(rule.device, previewDevice)) { return; } 624 _insertHighlight(iframeDoc, rule, contentArea );646 _insertHighlight(iframeDoc, rule, contentArea, tails); 625 647 }); 626 648 } -
hatatate/trunk/hatatate.php
r3724488 r3724996 4 4 * Plugin URI: https://border-haze.co.jp/tools/hatatate/ 5 5 * Description: Place a call-to-action (banner or text) on every post, run an A/B test, and read the report. No per-post editing. 6 * Version: 1.1. 06 * Version: 1.1.1 7 7 * Requires at least: 6.0 8 8 * Requires PHP: 7.4 … … 19 19 } 20 20 21 define( 'HATATATE_VERSION', '1.1. 0' );21 define( 'HATATATE_VERSION', '1.1.1' ); 22 22 define( 'HATATATE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 23 23 define( 'HATATATE_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); -
hatatate/trunk/includes/class-hatatate-engine.php
r3721496 r3724996 551 551 552 552 /** 553 * 同じ位置に先に入れたバナーがあれば、その直後に入れる(並べ替えの順を記事でも保つ) 554 * 555 * 「本文の前」「要素の後」「要素の中の先頭」は、毎回同じ場所に入れると後から入れたものが上に来てしまう。 556 * 2 つ目以降を前のバナーの末尾の直後に入れれば、どの挿入方法でも上から順に並ぶ。 557 * 558 * @param array $tails 位置ごとに最後に入れたバナーの末尾の要素 559 * @param string $key 位置 560 * @param DOMDocumentFragment $fragment 入れるバナー 561 * @return bool 入れたら true(先に入れたものが無ければ何もしないで false) 562 */ 563 private static function insert_after_tail( $tails, $key, $fragment ) { 564 if ( empty( $tails[ $key ] ) || ! $tails[ $key ]->parentNode ) { 565 return false; 566 } 567 $tail = $tails[ $key ]; 568 if ( $tail->nextSibling ) { 569 $tail->parentNode->insertBefore( $fragment, $tail->nextSibling ); 570 } else { 571 $tail->parentNode->appendChild( $fragment ); 572 } 573 return true; 574 } 575 576 /** 553 577 * HTML の中で目印に一致する要素の数(「他の記事でも見つかるか」の判定に使う) 554 578 * … … 951 975 952 976 // モーダルウィンドウ・固定ボタン挿入 977 // HTML は並べ替えの順のまま出し、同じ隅で重なるものは並びで上のものを手前に見せる(2 つ目以降の重なり順を 1 つずつ下げる) 978 $stack = array(); 953 979 foreach ( $this->overlay_rules_for_preset( 'modal' ) as $rule_item ) { 954 self::print_cta_html( $this->render_modal_html( $rule_item ) ); 955 } 980 $corner = self::modal_corner( $rule_item ); 981 $stack[ $corner ] = isset( $stack[ $corner ] ) ? $stack[ $corner ] + 1 : 0; 982 self::print_cta_html( $this->render_modal_html( $rule_item, $stack[ $corner ] ) ); 983 } 984 $below = 0; 956 985 foreach ( $this->overlay_rules_for_preset( 'fixed_button' ) as $rule_item ) { 957 self::print_cta_html( $this->render_fixed_button_html( $rule_item ) );986 self::print_cta_html( $this->render_fixed_button_html( $rule_item, $below++ ) ); 958 987 } 959 988 } … … 1035 1064 $modified = false; 1036 1065 1066 // 同じ位置に 2 つ以上あるときは、配置パターンの並び(上から順)のとおりに出す。 1067 // $nth: 同じ位置の何番目か(二重防止の目印を 1 つずつ分ける) 1068 // $loc_targets: 位置ごとの目印の要素(2 つ目以降も最初に見つけた要素を使う。先に入れたバナーの中の要素に当たらないように) 1069 // $loc_tails: 位置ごとに最後に入れたバナーの末尾(2 つ目以降はその直後に入れる) 1070 $nth = array(); 1071 $loc_targets = array(); 1072 $loc_tails = array(); 1073 1037 1074 foreach ( $all_rules as $rule_item ) { 1038 1075 // cta_id が空でも、ABテストとしてフラグが立っていればスキップしない … … 1041 1078 } 1042 1079 1043 $p_id = isset( $rule_item['pattern_id'] ) ? $rule_item['pattern_id'] : 'tmp'; 1044 $preset = isset( $rule_item['placement_preset'] ) ? $rule_item['placement_preset'] : 'custom'; 1045 $mark = $p_id . '_' . $preset; 1080 $p_id = isset( $rule_item['pattern_id'] ) ? $rule_item['pattern_id'] : 'tmp'; 1081 $preset = isset( $rule_item['placement_preset'] ) ? $rule_item['placement_preset'] : 'custom'; 1082 $loc_key = ( $preset === 'custom' ) ? self::get_placement_key( $rule_item ) : $preset; 1083 $mark = $p_id . '_' . $loc_key; 1084 $nth[ $mark ] = isset( $nth[ $mark ] ) ? $nth[ $mark ] + 1 : 1; 1085 $mark .= '_' . $nth[ $mark ]; 1046 1086 1047 1087 // サイドバー・フッター・オーバーレイは別フックで処理するためスキップ … … 1051 1091 } 1052 1092 1053 // すでにこのリクエストで挿入済みの パターン(位置)であればスキップ(重複表示対策)1093 // すでにこのリクエストで挿入済みの配置(パターン・位置・同じ位置の何番目か)であればスキップ(重複表示対策) 1054 1094 if ( isset( self::$injected_marks[ $mark ] ) ) { 1055 1095 continue; … … 1061 1101 } 1062 1102 1103 $tail = $fragment->lastChild; 1104 1063 1105 if ( $preset === 'before_content' ) { 1064 // 本文前: 最初の要素の前に挿入 1106 // 本文前: 最初の要素の前に挿入(同じ位置の 2 つ目以降は、前のバナーの直後) 1065 1107 if ( $body ) { 1066 // $body->firstChild が null でも insertBefore(..., null) は appendChild と同様に機能し、結果的に先頭になる 1067 $body->insertBefore( $fragment, $body->firstChild ); 1108 if ( ! self::insert_after_tail( $loc_tails, $loc_key, $fragment ) ) { 1109 // $body->firstChild が null でも insertBefore(..., null) は appendChild と同様に機能し、結果的に先頭になる 1110 $body->insertBefore( $fragment, $body->firstChild ); 1111 } 1112 $loc_tails[ $loc_key ] = $tail; 1068 1113 $modified = true; 1069 1114 self::$injected_marks[ $mark ] = true; … … 1104 1149 } 1105 1150 1106 $target_node = self::find_location_target( $xpath, $loc_def ); 1151 if ( ! isset( $loc_targets[ $loc_key ] ) ) { 1152 $loc_targets[ $loc_key ] = self::find_location_target( $xpath, $loc_def ); 1153 } 1154 $target_node = $loc_targets[ $loc_key ]; 1107 1155 if ( $target_node ) { 1108 1156 $position = ( ! empty( $loc_def['position'] ) ) ? $loc_def['position'] : 'before'; 1109 self::insert_fragment( $target_node, $fragment, $position ); 1157 if ( ! self::insert_after_tail( $loc_tails, $loc_key, $fragment ) ) { 1158 self::insert_fragment( $target_node, $fragment, $position ); 1159 } 1160 $loc_tails[ $loc_key ] = $tail; 1110 1161 $modified = true; 1111 1162 self::$injected_marks[ $mark ] = true; … … 1546 1597 } 1547 1598 1599 /** モーダルの重なり順の基準(1.1.0 から同じ値。同じ隅の 1 つ目はこの値のまま) */ 1600 const MODAL_Z_INDEX = 99999; 1601 1602 /** 固定ボタンの重なり順の基準(public/css/hatatate-front.css の .hatatate-fixed-bar と同じ値) */ 1603 const FIXED_Z_INDEX = 9990; 1604 1605 /** 1606 * モーダルが出る隅(重なり順を数える単位): 'right'(右下)/ 'left'(左下)/ 'center'(画面の中央) 1607 * 1608 * render_modal_html() と同じ分け方。知らない値は中央のフェードインで描くので 'center'。 1609 */ 1610 public static function modal_corner( $rule_item ) { 1611 $animation = isset( $rule_item['modal_animation'] ) ? $rule_item['modal_animation'] : 'slide_right'; 1612 if ( $animation === 'slide_right' ) { 1613 return 'right'; 1614 } 1615 return ( $animation === 'slide_left' ) ? 'left' : 'center'; 1616 } 1617 1548 1618 /** 1549 1619 * モーダルウィンドウ用の HTML を生成する(動きは public/js/hatatate-front.js。ここは data 属性だけ) 1550 */ 1551 private function render_modal_html( $rule_item ) { 1620 * 1621 * @param array $rule_item 配置 1 件 1622 * @param int $below 同じ隅で、並びでこれより上にあるモーダルの数(その数だけ重なり順を下げ、上のものを手前に見せる) 1623 */ 1624 private function render_modal_html( $rule_item, $below = 0 ) { 1552 1625 $cta_html = $this->render_cta_html( $rule_item ); 1553 1626 if ( empty( $cta_html ) ) { … … 1591 1664 // 角丸や地は CTA 側が持つ。上に空けた帯は閉じるボタンの置き場所で、見た目には出ない。 1592 1665 $width_css = self::modal_width_css( $rule_item ); 1666 $z_index = self::MODAL_Z_INDEX - max( 0, (int) $below ); 1593 1667 // box-sizing は CSS ファイル(.hatatate-modal-box)に置く。 1594 1668 // WordPress の wp_kses は style 属性に書ける CSS を許可リストで絞っていて、box-sizing は入っていない 1595 1669 $box_base = 'position:relative;padding-top:' . self::MODAL_CLOSE_LANE . 'px;' . $width_css; 1596 1670 if ( $animation === 'slide_right' ) { 1597 $overlay_style = 'display:none;position:fixed;bottom:' . $modal_bottom . 'px;right:20px;z-index: 99999;';1671 $overlay_style = 'display:none;position:fixed;bottom:' . $modal_bottom . 'px;right:20px;z-index:' . $z_index . ';'; 1598 1672 $box_style = $box_base; 1599 1673 $display_val = 'block'; 1600 1674 $click_overlay = false; 1601 1675 } elseif ( $animation === 'slide_left' ) { 1602 $overlay_style = 'display:none;position:fixed;bottom:' . $modal_bottom . 'px;left:20px;z-index: 99999;';1676 $overlay_style = 'display:none;position:fixed;bottom:' . $modal_bottom . 'px;left:20px;z-index:' . $z_index . ';'; 1603 1677 $box_style = $box_base; 1604 1678 $display_val = 'block'; … … 1607 1681 // fade_in: 全画面中央(後ろのページを伏せる暗い層は残す。これは CTA の外枠ではない) 1608 1682 // inset も許可リストに入っていないので、上下左右を 1 つずつ書く 1609 $overlay_style = 'display:none;position:fixed;top:0;right:0;bottom:0;left:0;background:rgba(0,0,0,.55);z-index: 99999;align-items:center;justify-content:center;';1683 $overlay_style = 'display:none;position:fixed;top:0;right:0;bottom:0;left:0;background:rgba(0,0,0,.55);z-index:' . $z_index . ';align-items:center;justify-content:center;'; 1610 1684 $box_style = $box_base; 1611 1685 $display_val = 'flex'; … … 1631 1705 /** 1632 1706 * 固定ボタン(画面下部バー)用の HTML を生成する(動きは public/js/hatatate-front.js) 1633 */ 1634 private function render_fixed_button_html( $rule_item ) { 1707 * 1708 * @param array $rule_item 配置 1 件 1709 * @param int $below 並びでこれより上にある固定ボタンの数。1 以上なら重なり順を CSS の値からその数だけ下げる 1710 * (固定ボタンはどれも画面の下端に出るので、同じ高さなら並びで上のものだけが見える) 1711 */ 1712 private function render_fixed_button_html( $rule_item, $below = 0 ) { 1635 1713 $cta_html = $this->render_cta_html( $rule_item ); 1636 1714 if ( empty( $cta_html ) ) { … … 1658 1736 $close_btn = '<button type="button" class="hatatate-fixed-close-btn" aria-label="閉じる">✕</button>'; 1659 1737 1660 $html = '<div id="' . $uid . '" class="' . esc_attr( 'hatatate-fixed-bar' . self::device_class_suffix( $rule_item ) ) . '" style="background:' . $bg_rgba . '; display:block; "' . $hide_attr . '>'1738 $html = '<div id="' . $uid . '" class="' . esc_attr( 'hatatate-fixed-bar' . self::device_class_suffix( $rule_item ) ) . '" style="background:' . $bg_rgba . '; display:block;' . ( $below > 0 ? ' z-index:' . (int) ( self::FIXED_Z_INDEX - $below ) . ';' : '' ) . '"' . $hide_attr . '>' 1661 1739 . '<div class="hatatate-fixed-bar-inner">' 1662 1740 . $close_btn -
hatatate/trunk/readme.txt
r3724488 r3724996 4 4 Requires at least: 6.0 5 5 Tested up to: 7.1 6 Stable tag: 1.1. 06 Stable tag: 1.1.1 7 7 Requires PHP: 7.4 8 8 License: GPLv2 or later … … 117 117 == Changelog == 118 118 119 = 1.1.1 = 120 * Fix: when two or more CTAs were placed at the same position inside the post (before the content, after the content, or a custom position), only the first one was shown. All of them are now shown, in the order you arrange them in the placement pattern. The preview on the placement screen shows the same order. 121 * When two or more modals appear in the same corner, or two or more fixed buttons appear at the bottom of the screen, the one placed higher in the placement pattern is now shown in front. 122 119 123 = 1.1.0 = 120 124 * The Home tab has a short news box at the bottom with tips and news. Its text ships with the plugin; nothing is loaded from outside.
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)