国境を越えた旅を始めよう
お問い合わせ

ウェブサイト制作 カスタマーサービス

カスタマーサービス

デザイナー(Figmaのプロトタイプを作る)

简码 [faq_item]

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

add_action('add_meta_boxes', function(){
  add_meta_box('qa_faq_box','Product Q&A','qa_faq_box_cb','product','normal','default');
});
function qa_faq_box_cb($post){
  wp_nonce_field('qa_faq_save','qa_faq_nonce');
  $title = get_post_meta($post->ID,'_qa_title',true);
  $desc  = get_post_meta($post->ID,'_qa_desc',true);
  $items = get_post_meta($post->ID,'_qa_items',true);
  if(!is_array($items)) $items=[];
  echo '<div class="qa-admin-wrap">';
  echo '<div class="qa-admin-row"><label>Section Title</label><input type="text" name="qa_title" value="'.esc_attr($title ?: 'Questions & Answers').'" /></div>';
  echo '<div class="qa-admin-row"><label>Section Description</label>';
  wp_editor($desc,'qa_desc',['textarea_name'=>'qa_desc','media_buttons'=>false,'teeny'=>true,'quicktags'=>true,'editor_height'=>140]);
  echo '</div><div class="qa-admin-items" id="qa-admin-items">';
  foreach($items as $i=>$it){
    $q = isset($it['q'])?$it['q']:'';
    $a = isset($it['a'])?$it['a']:'';
    $eid = 'qa_item_a_'.$i.'_'.wp_generate_uuid4();
    echo '<div class="qa-admin-item" data-index="'.$i.'">';
    echo '<div class="qa-admin-item-head"><strong>FAQ #'.($i+1).'</strong><button type="button" class="button-link-delete qa-remove">Remove</button></div>';
    echo '<div class="qa-admin-item-body"><label>Question</label><input type="text" name="qa_items_q[]" value="'.esc_attr($q).'" />';
    echo '<label>Answer (Rich Text)</label>';
    wp_editor($a,$eid,['textarea_name'=>'qa_items_a[]','media_buttons'=>false,'teeny'=>true,'quicktags'=>true,'editor_height'=>120]);
    echo '</div></div>';
  }
  echo '</div><div class="qa-admin-actions"><button type="button" class="button button-primary" id="qa-add-item">Add FAQ</button></div></div>';
}

add_action('admin_enqueue_scripts', function($hook){
  if(!in_array($hook,['post.php','post-new.php'])) return;
  $s = get_current_screen(); if(!$s || $s->post_type!=='product') return;
  wp_enqueue_editor();
  wp_enqueue_script('jquery');
  add_action('admin_head', function(){
    echo '<style>
      .qa-admin-wrap{padding:10px 0}
      .qa-admin-row>label{display:block;font-weight:600;margin-bottom:6px}
      .qa-admin-row input[type=text]{width:100%}
      .qa-admin-items .qa-admin-item{border:1px solid #e5e5e5;border-radius:6px;margin-bottom:12px;background:#fff}
      .qa-admin-item-head{display:flex;justify-content:space-between;align-items:center;padding:10px 12px;border-bottom:1px solid #eee;background:#fafafa}
      .qa-admin-item-body{padding:12px}
      .qa-admin-item-body label{display:block;margin:8px 0 6px;font-weight:600}
      .qa-admin-item-body input[type=text]{width:100%}
      .qa-admin-actions{margin-top:8px}
    </style>';
  });
  wp_add_inline_script('jquery', <<<'JS'
jQuery(function($){
  var $wrap = $("#qa-admin-items"), idx = $wrap.children(".qa-admin-item").length;
  $("#qa-add-item").on("click", function(e){
    e.preventDefault();
    var uid = Math.random().toString(36).slice(2);
    var id  = "qa_item_a_" + idx + "_" + uid;
    var $item = $('<div class="qa-admin-item" data-index="'+idx+'">\
      <div class="qa-admin-item-head"><strong>FAQ #'+(idx+1)+'</strong><button type="button" class="button-link-delete qa-remove">Remove</button></div>\
      <div class="qa-admin-item-body">\
        <label>Question</label><input type="text" name="qa_items_q[]" value="" />\
        <label>Answer (Rich Text)</label><textarea id="'+id+'" name="qa_items_a[]" rows="6"></textarea>\
      </div></div>');
    $wrap.append($item);
    initEditor(id);
    idx++;
  });
  $wrap.on("click", ".qa-remove", function(e){
    e.preventDefault();
    var $row = $(this).closest(".qa-admin-item");
    var ta = $row.find("textarea").attr("id");
    if (typeof tinymce !== "undefined" && tinymce.get(ta)) tinymce.remove(tinymce.get(ta));
    $row.remove();
  });
  function initEditor(id){
    if (window.wp && wp.editor && typeof wp.editor.initialize === 'function'){
      var s = (wp.editor.getDefaultSettings ? wp.editor.getDefaultSettings() : {});
      if (!s.tinymce) s.tinymce = {};
      s.mediaButtons = false;
      s.quicktags = true;
      s.tinymce.wpautop = true;
      s.tinymce.menubar = false;
      s.tinymce.toolbar1 = 'bold italic | link unlink | bullist numlist | undo redo';
      s.tinymce.toolbar2 = '';
      s.tinymce.height = 140;
      try{ wp.editor.initialize(id, s); }catch(e){}
      waitForTinymce(id,function(){ if (window.switchEditors) switchEditors.go(id,'tmce'); });
      return;
    }
    setTimeout(function(){
      try{
        if (typeof quicktags === 'function') quicktags({id:id});
        if (typeof QTags !== 'undefined' && typeof QTags._buttonsInit === 'function') QTags._buttonsInit();
      }catch(e){}
      try{
        if (typeof tinymce !== 'undefined'){
          var baseKey=null, baseCfg=null;
          if (typeof tinyMCEPreInit !== 'undefined' && tinyMCEPreInit.mceInit){
            if (tinyMCEPreInit.mceInit.qa_desc){ baseCfg = jQuery.extend(true, {}, tinyMCEPreInit.mceInit.qa_desc); }
            else { for (var k in tinyMCEPreInit.mceInit){ baseKey=k; break; } if (baseKey) baseCfg=jQuery.extend(true, {}, tinyMCEPreInit.mceInit[baseKey]); }
          }
          if (!baseCfg) baseCfg={};
          baseCfg.selector = '#'+id;
          baseCfg.wpautop = true;
          baseCfg.menubar = false;
          baseCfg.height = 140;
          tinymce.init(baseCfg);
        }
      }catch(e){}
      waitForTinymce(id,function(){ if (window.switchEditors) switchEditors.go(id,'tmce'); });
    },20);
  }
  function waitForTinymce(id, cb){
    var n=0, t=setInterval(function(){
      var ed = (window.tinymce && tinymce.get(id)) || null;
      if (ed || n++>40){ clearInterval(t); if (ed && cb) cb(ed); }
    },50);
  }
});
JS
  );
});

add_action('save_post_product', function($post_id){
  if(!isset($_POST['qa_faq_nonce'])||!wp_verify_nonce($_POST['qa_faq_nonce'],'qa_faq_save')) return;
  if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
  if(!current_user_can('edit_post',$post_id)) return;
  $title = isset($_POST['qa_title']) ? sanitize_text_field($_POST['qa_title']) : '';
  $desc  = isset($_POST['qa_desc'])  ? wp_kses_post($_POST['qa_desc']) : '';
  $qs = isset($_POST['qa_items_q']) && is_array($_POST['qa_items_q']) ? array_values($_POST['qa_items_q']) : [];
  $as = isset($_POST['qa_items_a']) && is_array($_POST['qa_items_a']) ? array_values($_POST['qa_items_a']) : [];
  $items=[]; $n=max(count($qs),count($as));
  for($i=0;$i<$n;$i++){
    $q = isset($qs[$i]) ? sanitize_text_field($qs[$i]) : '';
    $a = isset($as[$i]) ? wp_kses_post($as[$i]) : '';
    if($q!=='' || $a!=='') $items[]=['q'=>$q,'a'=>$a];
  }
  update_post_meta($post_id,'_qa_title',$title ?: 'Questions & Answers');
  update_post_meta($post_id,'_qa_desc',$desc);
  update_post_meta($post_id,'_qa_items',$items);
});

if (!shortcode_exists('qa_faq')) {
  add_shortcode('qa_faq', function($atts,$content=''){
    $a = shortcode_atts(['title'=>'','desc'=>'','use_product'=>'1'],$atts,'qa_faq');
    $id = 'qa_'.wp_generate_uuid4();
    $GLOBALS['__qa_items']=[]; do_shortcode($content); $items_sc=$GLOBALS['__qa_items'];
    $items=[]; $title='Questions & Answers'; $desc='';
    if($a['use_product']==='1' && function_exists('is_product') && is_product()){
      $pid=get_queried_object_id();
      $items = get_post_meta($pid,'_qa_items',true); if(!is_array($items)) $items=[];
      $title = get_post_meta($pid,'_qa_title',true) ?: $title;
      $desc  = get_post_meta($pid,'_qa_desc',true) ?: '';
    }
    if(count($items_sc)) $items=$items_sc;
    if($a['title']!=='') $title=$a['title'];
    if($a['desc']!=='')  $desc =$a['desc'];
    $limit=6;
    $html = '<div class="qa-wrap" id="'.esc_attr($id).'">';
    $html .= '<div class="qa-head"><h2 class="qa-title">'.esc_html($title).'</h2>';
    if($desc!==''){ $html.='<div class="qa-desc">'.wp_kses_post($desc).'</div>'; }
    $html .= '</div><div class="qa-box"><div class="qa-acc">';
    foreach($items as $i=>$it){
      $q = isset($it['q'])?$it['q']:'';
      $a_content = isset($it['a'])?$it['a']:'';
      $html .= '<div class="qa-item'.($i>=$limit?' qa-hidden':'').'">';
      $html .= '<button type="button" class="qa-q" aria-expanded="false"><span class="qa-q-text">'.esc_html($q).'</span><span class="qa-arrow" aria-hidden="true"></span></button>';
      $html .= '<div class="qa-a" hidden><div class="qa-a-inner">'.do_shortcode(wp_kses_post($a_content)).'</div></div></div>';
    }
    $html .= '</div>';
    if(count($items)>$limit){ $html.='<div class="qa-viewall-wrap"><button class="qa-viewall" data-qa-open="'.esc_attr($id).'">View All ></button></div>'; }
    $html .= '</div>';
    if(count($items)>0){
      $html .= '<div class="qa-modal" id="'.esc_attr($id).'__modal" aria-hidden="true"><div class="qa-overlay" data-qa-close></div><aside class="qa-panel"><div class="qa-modal-header"><div class="qa-modal-title">'.esc_html($title).'</div><button class="qa-close" data-qa-close aria-label="Close">×</button></div><div class="qa-modal-body"><div class="qa-acc qa-acc-modal">';
      foreach($items as $it){
        $q = isset($it['q'])?$it['q']:'';
        $a_content = isset($it['a'])?$it['a']:'';
        $html .= '<div class="qa-item"><button type="button" class="qa-q" aria-expanded="false"><span class="qa-q-text">'.esc_html($q).'</span><span class="qa-arrow" aria-hidden="true"></span></button><div class="qa-a" hidden><div class="qa-a-inner">'.do_shortcode(wp_kses_post($a_content)).'</div></div></div>';
      }
      $html .= '</div></div></aside></div>';
    }
    $html .= '</div>';
    qa_faq_assets_once();
    return $html;
  });
  add_shortcode('faq_item', function($atts,$content=''){
    $q = isset($atts['q']) ? $atts['q'] : '';
    if(!isset($GLOBALS['__qa_items'])||!is_array($GLOBALS['__qa_items'])) $GLOBALS['__qa_items']=[];
    $GLOBALS['__qa_items'][]=['q'=>$q,'a'=>$content];
    return '';
  });
}

function qa_faq_assets_once(){
  static $done=false; if($done) return; $done=true;
  add_action('wp_footer', function(){
    $css = '
      .qa-wrap{max-width:1000px;margin:40px auto}
      .qa-title{font-family:Marcellus,serif;font-size:40px;line-height:1.2;margin:0 0 12px;text-align:center}
      .qa-desc{max-width:900px;margin:0 auto 24px;text-align:center;opacity:.9}
      .qa-box{background:#fcf9f2;padding:20px 50px;border-radius:12px}
      .qa-item{border-bottom:1px solid #eaeaea;padding:15px 0}
      .qa-item:last-child{border-bottom:none}
      .qa-wrap button,.qa-wrap .qa-q,.qa-wrap .qa-viewall,.qa-wrap .qa-close,.qa-wrap input[type="button"],.qa-wrap input[type="submit"],.qa-wrap .elementor-button{background-color:transparent!important;color:inherit!important;border:0 none!important;border-radius:0!important;font-family:"Satoshi-Medium","Satoshi",Arial,sans-serif!important;font-weight:600!important;box-shadow:none!important;padding:0!important}
      .qa-q{width:100%;display:flex;align-items:center;justify-content:space-between;gap:16px;background:transparent;border:0;cursor:pointer;border-radius:0!important;color:inherit;padding:0}
      .qa-q:hover,.qa-q:focus{background:transparent!important;color:inherit!important;box-shadow:none!important;outline:none!important}
      .qa-q:focus-visible{outline:none!important;box-shadow:none!important}
      .qa-q-text{font-family:"Satoshi-Medium","Satoshi","Helvetica Neue",Arial,sans-serif;font-size:18px;line-height:1.5;text-align:left}
      .qa-arrow{width:18px;height:18px;position:relative;flex:0 0 18px}
      .qa-arrow:before,.qa-arrow:after{content:"";position:absolute;left:0;right:0;margin:auto;width:10px;height:2px;background:#222;top:6px;transform-origin:center}
      .qa-arrow:after{transform:rotate(90deg)}
      .qa-item.open .qa-arrow:after{opacity:0}
      .qa-a-inner{font-size:16px;line-height:1.8}
      .qa-a-inner p{margin:0 0 10px}
      .qa-a-inner ul,.qa-a-inner ol{margin:0 0 12px 1.25em}
      .qa-viewall-wrap{text-align:center;margin-top:10px}
      .qa-viewall{background:none;border:0;font-size:14px;text-decoration:underline;cursor:pointer}
      .qa-hidden{display:none}
      .qa-modal{position:fixed;inset:0;z-index:999999;display:none}
      .qa-modal[aria-hidden="false"]{display:block}
      .qa-overlay{position:absolute;inset:0;background:rgba(0,0,0,.45)}
      .qa-panel{position:absolute;top:0;right:0;width:40vw;height:100vh;background:#fff;box-shadow:-10px 0 30px rgba(0,0,0,.15);transform:translateX(100%);transition:transform .3s ease}
      .qa-modal[aria-hidden="false"] .qa-panel{transform:translateX(0)}
      .qa-modal-header{display:flex;align-items:center;justify-content:space-between;padding:18px 20px;border-bottom:1px solid #eee}
      .qa-modal-title{font-family:Marcellus,serif;font-size:24px}
      .qa-close{font-size:28px;line-height:1;background:none;border:0;cursor:pointer}
      .qa-modal-body{height:calc(100vh - 61px);overflow:auto;padding:12px 24px}
      @media(max-width:768px){
        .qa-title{font-size:28px}
        .qa-wrap{max-width:100%;margin:24px auto}
        .qa-box{padding:20px 10px;border-radius:8px}
        .qa-item{padding:15px 0}
        .qa-q-text{font-size:16px}
        .qa-a-inner{font-size:14px}
        .qa-panel{left:0;right:0;width:100vw;height:80vh;bottom:0;top:auto;border-radius:12px 12px 0 0;transform:translateY(100%)}
        .qa-modal[aria-hidden="false"] .qa-panel{transform:translateY(0)}
        .qa-modal-body{height:calc(80vh - 61px)}
      }
      body.qa-modal-open{overflow:hidden}
    ';
    $js = '(function(){
      function toggleItem(btn){
        var item=btn.closest(".qa-item"); var ans=item.querySelector(".qa-a");
        var expanded=btn.getAttribute("aria-expanded")==="true";
        btn.setAttribute("aria-expanded",expanded?"false":"true");
        item.classList.toggle("open",!expanded);
        if(ans){ if(expanded){ans.setAttribute("hidden","hidden");} else {ans.removeAttribute("hidden");} }
      }
      document.addEventListener("click",function(e){
        var q=e.target.closest(".qa-q"); if(q){ e.preventDefault(); toggleItem(q); return; }
        var openBtn=e.target.closest("[data-qa-open]"); if(openBtn){ var id=openBtn.getAttribute("data-qa-open"); var m=document.getElementById(id+"__modal"); if(m){ m.setAttribute("aria-hidden","false"); document.body.classList.add("qa-modal-open"); } return; }
        if(e.target.closest("[data-qa-close]")||e.target.classList.contains("qa-overlay")){ var m=e.target.closest(".qa-modal")||document.querySelector(".qa-modal[aria-hidden=\'false\']"); if(m){ m.setAttribute("aria-hidden","true"); document.body.classList.remove("qa-modal-open"); } return; }
      });
      document.addEventListener("keydown",function(e){ if(e.key==="Escape"){ var m=document.querySelector(".qa-modal[aria-hidden=\'false\']"); if(m){ m.setAttribute("aria-hidden","true"); document.body.classList.remove("qa-modal-open"); } }});
    })();';
    echo '<style>'.$css.'</style><script>'.$js.'</script>';
  });
}