<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Clipboard API &#8211; 小豬日常</title>
	<atom:link href="https://piglife.tw/tag/clipboard-api/feed/" rel="self" type="application/rss+xml" />
	<link>https://piglife.tw</link>
	<description>Hello World，一個紀錄生活與學習的地方</description>
	<lastBuildDate>Wed, 10 Dec 2025 09:56:24 +0000</lastBuildDate>
	<language>zh-TW</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9</generator>

<image>
	<url>https://piglife.tw/wp-content/uploads/2017/10/cropped-logo-1-32x32.png</url>
	<title>Clipboard API &#8211; 小豬日常</title>
	<link>https://piglife.tw</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>WordPress 單篇文章中為程式碼區塊加入右上角複製按鈕</title>
		<link>https://piglife.tw/technical-notes/wordpress-code-copy-button/</link>
					<comments>https://piglife.tw/technical-notes/wordpress-code-copy-button/#respond</comments>
		
		<dc:creator><![CDATA[小豬]]></dc:creator>
		<pubDate>Wed, 10 Dec 2025 09:51:40 +0000</pubDate>
				<category><![CDATA[技術筆記]]></category>
		<category><![CDATA[Clipboard API]]></category>
		<category><![CDATA[Gutenberg]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://piglife.tw/technical-notes/wordpress-code-copy-button/</guid>

					<description><![CDATA[本文介紹如何在 WordPress 單篇文章頁面，為所有程式碼區塊動態加入右上角複製按鈕，提升讀者複...]]></description>
										<content:encoded><![CDATA[<h2 class="wp-block-heading">前言</h2>
<p>在撰寫技術文章時，常會使用程式碼區塊展示範例程式碼。為了提升讀者體驗，讓他們能快速複製程式碼，本文示範如何在 WordPress 單篇文章頁面中，為所有  pre , code 程式碼區塊動態加入一個右上角的「Copy」按鈕。此功能適用於 Gutenberg、Markdown、Prism.js 或 Highlight.js 等常見的程式碼高亮方案。</p>
<p>此做法適合熟悉 WordPress 主題或外掛開發的工程師，想要自訂前端行為並強化內容互動性。</p>
<h2 class="wp-block-heading">為什麼要這樣設計？</h2>
<p>透過 WordPress 的 <code>wp_footer</code> action，我們能在頁面底部注入必要的 CSS 與 JavaScript，確保只在前台且單篇文章頁面執行，避免管理後台或非文章頁面產生不必要的負擔。</p>
<p>此外，使用 JavaScript 動態包裝 pre 元素並加入按鈕，能兼容多種程式碼呈現方式，且避免重複包裝，確保效能與穩定性。</p>
<h2 class="wp-block-heading">核心程式碼解析</h2>
<h3 class="wp-block-heading">1. 僅在單篇文章頁面執行</h3>
<pre><code class="lang-php language-php php">if ( ! is_singular( &#039;post&#039; ) || is_admin() ) {
    return;
}</code></pre>
<p>這段檢查確保腳本只在前台的單篇文章頁面執行，避免影響其他頁面或後台。</p>
<h3 class="wp-block-heading">2. CSS 樣式定義</h3>
<pre><code class="lang-css language-css css">.code-copy-btn {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 10;
    padding: 4px 10px;
    font-size: 12px;
    border-radius: 6px;
    background: rgba(0, 0, 0, 0.65);
    color: #fff;
    cursor: pointer;
    opacity: 0.75;
    transition: background 0.2s ease, opacity 0.2s ease;
}
.code-copy-btn:hover {
    background: rgba(0, 0, 0, 0.85);
    opacity: 1;
}
.code-copy-btn:disabled {
    cursor: default;
    opacity: 0.6;
}</code></pre>
<p>這些樣式將按鈕定位在程式碼區塊右上角，並提供滑鼠懸停與禁用狀態的視覺反饋。</p>
<h3 class="wp-block-heading">3. 動態包裝與按鈕建立</h3>
<pre><code class="lang-js language-js js">document.querySelectorAll(&#039;pre &gt; code&#039;).forEach(function (codeBlock) {
    const pre = codeBlock.parentNode;
    if (pre.parentNode.classList.contains(&#039;code-block-wrapper&#039;)) return;

    const wrapper = document.createElement(&#039;div&#039;);
    wrapper.className = &#039;code-block-wrapper&#039;;
    pre.parentNode.insertBefore(wrapper, pre);
    wrapper.appendChild(pre);

    const btn = document.createElement(&#039;button&#039;);
    btn.type = &#039;button&#039;;
    btn.className = &#039;code-copy-btn&#039;;
    btn.textContent = &#039;Copy&#039;;

    btn.addEventListener(&#039;click&#039;, function () {
        const text = codeBlock.innerText;
        navigator.clipboard.writeText(text).then(function () {
            btn.textContent = &#039;Copied!&#039;;
            btn.disabled = true;
            setTimeout(function () {
                btn.textContent = &#039;Copy&#039;;
                btn.disabled = false;
            }, 1500);
        });
    });

    wrapper.appendChild(btn);
});</code></pre>
<p>這段程式碼會搜尋所有 pre code 結構，為每個程式碼區塊包裹一個容器，並在右上角加入按鈕。按鈕點擊時會將程式碼文字複製到剪貼簿，並短暫顯示 &#8220;Copied!&#8221; 提示。</p>
<h2 class="wp-block-heading">實務應用與優化建議</h2>
<ul>
<li>可依需求調整按鈕文字或樣式，讓 UI 更符合網站風格。</li>
<li>若網站使用 AJAX 載入文章內容，需確保此腳本在新內容載入後重新執行。</li>
<li>為提升相容性，可加入對 <code>navigator.clipboard</code> 支援性的檢查，並提供替代方案。</li>
<li>若程式碼區塊非常長，複製整段可能影響使用者體驗，可考慮限制複製範圍或加入分段複製功能。</li>
</ul>
<h2 class="wp-block-heading">常見問題與注意事項</h2>
<ul>
<li>本方案依賴現代瀏覽器的 Clipboard API，舊版瀏覽器可能無法正常複製。</li>
<li>若網站有其他 JavaScript 操作程式碼區塊，請注意避免衝突。</li>
<li>按鈕的絕對定位需確保父容器有相對定位，否則位置會錯亂。</li>
</ul>
<h2 class="wp-block-heading">完整程式碼</h2>
<pre><code class="lang-php language-php php">&lt;?php
/**
 * 單篇 post 頁面：全站 
&lt;pre&gt;&lt;code&gt; 右上角加入 Copy 按鈕
 * 適用 Gutenberg / Markdown / Prism / Highlight.js
 */

add_action( &#039;wp_footer&#039;, function () {

    // ✅ 只在前台「單篇文章（post）」執行
    if ( ! is_singular( &#039;post&#039; ) || is_admin() ) {
        return;
    }
    ?&gt;

&lt;style&gt;
        .code-block-wrapper {
            position: relative;
        }

        .code-copy-btn {
            position: absolute;
            top: 8px;
            right: 8px;
            z-index: 10;
            padding: 4px 10px;
            font-size: 12px;
            line-height: 1.4;
            border-radius: 6px;
            border: none;
            background: rgba(0, 0, 0, 0.65);
            color: #fff;
            cursor: pointer;
            transition: background 0.2s ease, opacity 0.2s ease;
            opacity: 0.75;
        }

        .code-copy-btn:hover {
            background: rgba(0, 0, 0, 0.85);
            opacity: 1;
        }

        .code-copy-btn:disabled {
            cursor: default;
            opacity: 0.6;
        }

        .code-block-wrapper pre {
            margin: 0;
        }
    &lt;/style&gt;

    &lt;script&gt;
    document.addEventListener(&#039;DOMContentLoaded&#039;, function () {

        document.querySelectorAll(&#039;pre &gt; code&#039;).forEach(function (codeBlock) {

            const pre = codeBlock.parentNode;

            // 已處理過就跳過（避免 AJAX / 重複包）
            if (pre.parentNode.classList.contains(&#039;code-block-wrapper&#039;)) {
                return;
            }

            // 建立包裝容器
            const wrapper = document.createElement(&#039;div&#039;);
            wrapper.className = &#039;code-block-wrapper&#039;;

            pre.parentNode.insertBefore(wrapper, pre);
            wrapper.appendChild(pre);

            // 建立 Copy 按鈕
            const btn = document.createElement(&#039;button&#039;);
            btn.type = &#039;button&#039;;
            btn.className = &#039;code-copy-btn&#039;;
            btn.textContent = &#039;Copy&#039;;

            btn.addEventListener(&#039;click&#039;, function () {
                const text = codeBlock.innerText;

                navigator.clipboard.writeText(text).then(function () {
                    btn.textContent = &#039;Copied!&#039;;
                    btn.disabled = true;

                    setTimeout(function () {
                        btn.textContent = &#039;Copy&#039;;
                        btn.disabled = false;
                    }, 1500);
                });
            });

            wrapper.appendChild(btn);
        });

    });
    &lt;/script&gt;
    &lt;?php
});
</code></pre>]]></content:encoded>
					
					<wfw:commentRss>https://piglife.tw/technical-notes/wordpress-code-copy-button/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
