EarnTheStar WebBoard : เอิร์น เดอะสตาร์ เว็บบอร์ด

หมวดคอมพิวเตอร์ => ห้องเว็บและโปรแกรม => หัวข้อที่ตั้งโดย: vs เมื่อ 18 ส.ค 26, 12:23:09

ชื่อ: smf
โดย: vs เมื่อ 18 ส.ค 26, 12:23:09
วิธีเพิ่มลดขนาดฟอนต์ ใน index.css ใน Theme>default>css
ต่อท้ายด้วยโค้ดนี้

/* ===== Custom Thai Typography ===== */

html,
body,
button,
input,
select,
textarea {
    font-family:
        "Segoe UI",
        "Noto Sans Thai",
        Tahoma,
        Arial,
        sans-serif;
}

/* ตัวอักษรหลักทั้งเว็บ */
body {
    font-size: 15px;
    line-height: 1.65;
}

/* เนื้อหาในกระทู้ */
.post{
    font-size: 15px;
    line-height: 1.75;
}

/* ชื่อหัวข้อกระทู้ */
#forumposts .keyinfo h5,
.subject_title,
h1,
h2,
h3 {
    line-height: 1.4;
}

/* ข้อมูลประกอบ เช่น เวลา ผู้โพสต์ เมนูย่อย */
.smalltext {
    font-size: 13px;
}
-------
ชื่อ: ต่อ: smf
โดย: vs เมื่อ 18 ส.ค 26, 13:25:48
yt แนวตั้ง
แก้ 3 ที่

1. subs
---
เพิ่ม array
array(
    'tag' => 'youtube',
    'type' => 'unparsed_equals_content',
    'test' => 'vertical\]',
    'content' => '<div class="videocontainer" data-youtube-orientation="vertical"><div><iframe frameborder="0" src="https://www.youtube.com/embed/$1?origin=' . $hosturl . '&wmode=opaque" data-youtube-id="$1" allowfullscreen loading="lazy"></iframe></div></div>',
    'disabled_content' => '<a href="https://www.youtube.com/watch?v=$1" target="_blank" rel="noopener">https://www.youtube.com/watch?v=$1</a>',
    'block_level' => true,
),

2. index.css
---
เพิ่มตอนท้าย
/* Vertical YouTube 9:16 */
.videocontainer[data-youtube-orientation="vertical"] {
    max-width: 360px;
}

.videocontainer[data-youtube-orientation="vertical"] > div {
    padding-bottom: 177.7777778%;
}
/* Vertical YouTube: allow side-by-side */
.videocontainer[data-youtube-orientation="vertical"] {
    display: inline-block;
    vertical-align: top;
    width: 360px;
    max-width: 100%;
    margin: 0 12px 12px 0;
}

3. jquery.sceditor.smf.js แก้ 2 ที่
---
sceditor.command.set(
   'youtube', {
      _dropDown: function (editor, caller, callback) {
         var content = document.createElement('div');

         var label = document.createElement('label');
         label.textContent = editor._('Video URL:');
         label.style.display = 'block';
         label.style.marginBottom = '4px';

         var input = document.createElement('input');
         input.type = 'text';
         input.placeholder = 'https://';
         input.style.width = '100%';
         input.style.boxSizing = 'border-box';

         var verticalWrap = document.createElement('label');
         verticalWrap.style.display = 'block';
         verticalWrap.style.marginTop = '10px';
         verticalWrap.style.marginBottom = '10px';
         verticalWrap.style.cursor = 'pointer';

         var vertical = document.createElement('input');
         vertical.type = 'checkbox';
         vertical.style.marginRight = '6px';

         verticalWrap.appendChild(vertical);
         verticalWrap.appendChild(
            document.createTextNode('วิดีโอแนวตั้ง 9:16')
         );

         var button = document.createElement('button');
         button.type = 'button';
         button.className = 'button';
         button.textContent = editor._('Insert');

         content.appendChild(label);
         content.appendChild(input);
         content.appendChild(verticalWrap);
         content.appendChild(button);

         function insertYoutube(e) {
            var val = input.value.trim();

            var idMatch = val.match(
               /(?:v=|v\/|embed\/|youtu\.be\/|shorts\/)([a-zA-Z0-9_-]{11})/
            );

            // อนุญาตให้ใส่ Video ID 11 ตัวตรง ๆ ได้ด้วย
            if (!idMatch && /^[a-zA-Z0-9_-]{11}$/.test(val))
               idMatch = [val, val];

            var timeMatch = val.match(
               /[&?](?:start|t)=((\d+[hms]?){1,3})/i
            );

            var time = 0;

            if (timeMatch) {
               timeMatch[1].split(/[hms]/).forEach(function (part) {
                  if (part !== '')
                     time = (time * 60) + Number(part);
               });
            }

            if (idMatch) {
               callback(
                  idMatch[1],
                  time,
                  vertical.checked
               );
            }

            editor.closeDropDown(true);

            if (e)
               e.preventDefault();
         }

         button.addEventListener('click', insertYoutube);

         input.addEventListener('keypress', function (e) {
            if (e.key === 'Enter')
               insertYoutube(e);
         });

         editor.createDropDown(caller, 'insertlink', content);

         setTimeout(function () {
            input.focus();
         }, 0);
      },

      exec: function (caller) {
         var editor = this;

         editor.commands.youtube._dropDown(
            editor,
            caller,
            function (id, time, isVertical) {
               var orientation = isVertical
                  ? ' data-youtube-orientation="vertical"'
                  : '';

               editor.wysiwygEditorInsertHtml(
                  '<div class="videocontainer"' + orientation + '>' +
                     '<div>' +
                        '<iframe frameborder="0" allowfullscreen ' +
                        'src="https://www.youtube-nocookie.com/embed/' +
                        id +
                        '?wmode=opaque&start=' +
                        time +
                        '" data-youtube-id="' +
                        id +
                        '" loading="lazy"></iframe>' +
                     '</div>' +
                  '</div>'
               );
            }
         );
      },

      txtExec: function (caller) {
         var editor = this;

         editor.commands.youtube._dropDown(
            editor,
            caller,
            function (id, time, isVertical) {
               editor.insertText(
                  '[youtube' +
                  (isVertical ? '=vertical' : '') +
                  ']' +
                  id +
                  '[/youtube]'
               );
            }
         );
      }
   }
);


และเพิ่มตอนท้าย
sceditor.formats.bbcode.set(
   'youtube', {
      allowsEmpty: true,

      tags: {
         div: {
            class: 'videocontainer'
         }
      },

      isInline: false,
      skipLastLineBreak: true,

      format: function (element, content) {
         var $element = $(element);
         var youtube_id = $element.find('iframe').data('youtube-id');
         var orientation = $element.attr('data-youtube-orientation');

         if (typeof youtube_id !== "undefined") {
            return '[youtube' +
               (orientation === 'vertical' ? '=vertical' : '') +
               ']' +
               youtube_id +
               '[/youtube]';
         }

         return content;
      },

      html: function (token, attrs, content) {
         if (!/^[a-zA-Z0-9_-]{11}$/.test(content))
            return content;

         var orientation =
            typeof attrs.defaultattr !== 'undefined' &&
            attrs.defaultattr === 'vertical'
               ? ' data-youtube-orientation="vertical"'
               : '';

         return '<div class="videocontainer"' + orientation + '>' +
            '<div>' +
               '<iframe frameborder="0" ' +
               'src="https://www.youtube-nocookie.com/embed/' +
               content +
               '?wmode=opaque" ' +
               'data-youtube-id="' +
               content +
               '" loading="lazy" allowfullscreen></iframe>' +
            '</div>' +
         '</div>';
      }
   }
);
ชื่อ: ต่อ: smf
โดย: vs เมื่อ 18 ส.ค 26, 13:32:52
เปลี่ยน Fonts แบบเต็มสูตร
---


ได้ครับ ใช้ letter-spacing ได้เลย แต่กับภาษาไทย ควรปรับน้อยมาก เพราะถ้าห่างเกินไป สระ/วรรณยุกต์จะดูแปลกได้

จาก CSS ชุดนี้ ผมแนะนำเพิ่มเฉพาะเนื้อหากระทู้ก่อน:

/* เนื้อหาในกระทู้ */
.post {
    font-size: 18px;
    line-height: 1.75;
    letter-spacing: 0.015em;
}

ถ้าต้องการให้ทั้งเว็บโปร่งขึ้นเล็กน้อย:

body {
    font-size: 16px;
    line-height: 1.65;
    letter-spacing: 0.01em;
}

ค่าที่เหมาะกับภาษาไทยประมาณนี้:

letter-spacing: 0;        /* ปกติ */
letter-spacing: 0.01em;  /* โปร่งขึ้นนิดเดียว */
letter-spacing: 0.015em;  /* ผมแนะนำให้ลอง */
letter-spacing: 0.02em;  /* เริ่มเห็นชัด */

ผม ไม่แนะนำ 0.05em ขึ้นไป สำหรับข้อความภาษาไทยทั่วไป

ถ้าจุดประสงค์คือให้ข้อความอ่านสบายขึ้น ผมจะใช้ชุดนี้กับ SMF ของคุณ:

/* ===== Custom Thai Typography ===== */


html,
body,
button,
input,
select,
textarea {
    font-family:
        "Segoe UI",
        "supermarket",
        Tahoma,
        Arial,
        sans-serif;
}


/* ตัวอักษรหลักทั้งเว็บ */
body {
    font-size: 16px;
    line-height: 1.65;
}


/* เนื้อหาในกระทู้ */
.post {
    font-size: 18px;
    line-height: 1.75;
    letter-spacing: 0.015em;
}


/* ชื่อหัวข้อกระทู้ */
#forumposts .keyinfo h5,
.subject_title,
h1,
h2,
h3 {
    line-height: 1.4;
    letter-spacing: 0.005em;
}


/* ข้อมูลประกอบ เช่น เวลา ผู้โพสต์ เมนูย่อย */
.smalltext {
    font-size: 13px;
    letter-spacing: 0;
}

ผมเลือกให้ เนื้อหาโปร่งขึ้น แต่หัวข้อแทบไม่ขยาย เพราะหัวข้อภาษาไทยถ้าห่างมากจะเสียทรง ส่วน .smalltext คงไว้ปกติเพราะขนาดเล็กอยู่แล้วครับ.

ถ้าเป็น Google Fonts เราไม่ต้องอัพโหลดฟอนต์ขึ้นไปใช่ไหมครับ
อย่างนี้ ผมใช้ supermarket

แต่ถ้าไม่ใช่ Google Fonts เราต้องอัพโหลดไปไว้ที่ไหนของ smf ครับ

ใช่ครับ ถ้าเป็น Google Fonts เราไม่ต้องอัปโหลดไฟล์ฟอนต์ขึ้นเซิร์ฟเวอร์เอง เพียงเรียก stylesheet ของ Google แล้วใช้ font-family ได้เลย เช่น Kanit ซึ่ง Google Fonts ให้บริการโดยตรง

แต่ Supermarket ไม่ใช่ Google Font ครับ เป็นฟอนต์ไทยของ Superstorefont ที่เผยแพร่ให้ดาวน์โหลดใช้งานได้ตามเงื่อนไขของเจ้าของฟอนต์

สำหรับ SMF ของเรา ผมแนะนำสร้างโฟลเดอร์นี้:

/forum/Themes/default/fonts/

แล้ววางไฟล์ เช่น:

/forum/Themes/default/fonts/supermarket.woff2
/forum/Themes/default/fonts/supermarket.woff

จากนั้นใน index.css ซึ่งอยู่ที่:

/forum/Themes/default/css/index.css

เพิ่มไว้ก่อนชุด Custom Thai Typography:

@font-face {
    font-family: "supermarket";
    src:
        url("../fonts/supermarket.woff2") format("woff2"),
        url("../fonts/supermarket.woff") format("woff");
    font-weight: normal;
    font-style: normal;
    font-display: swap;
}

แล้ว CSS ที่คุณมีอยู่ก็ใช้ต่อได้เลย:

font-family:
    "Segoe UI",
    "supermarket",
    Tahoma,
    Arial,
    sans-serif;

แต่มีจุดหนึ่งครับ: ลำดับนี้หมายความว่าเครื่อง Windows ส่วนใหญ่จะใช้ Segoe UI ก่อน ทำให้ supermarket แทบไม่ได้ถูกเรียกเลย

ถ้าต้องการให้เว็บใช้ Supermarket เป็นฟอนต์หลักจริง ๆ ต้องสลับเป็น:

font-family:
    "supermarket",
    "Segoe UI",
    Tahoma,
    Arial,
    sans-serif;

อันนี้สำคัญครับ เพราะจาก CSS ที่ส่งมา ตอนนี้ Supermarket เป็นแค่ fallback ตัวที่สอง ไม่ใช่ฟอนต์หลักครับ.

ครับ ที่เครื่องผมอ่านออกเป็นรูปแบบของฟอนต์ supermarket ก็คงเป็นเพราะในเครื่องผมมีฟอนต์นี้อยู่ ใช่ไหมครับ

ใช่ครับ มีความเป็นไปได้สูงว่าเป็นแบบนั้น

จาก CSS นี้:

font-family:
    "Segoe UI",
    "supermarket",
    Tahoma,
    Arial,
    sans-serif;

เบราว์เซอร์จะลองตามลำดับ:

Segoe UI
ถ้าใช้ไม่ได้ ค่อย supermarket
แล้วค่อย Tahoma / Arial

แต่สำหรับภาษาไทย มีกรณีที่ฟอนต์ตัวแรกไม่มี glyph หรือเบราว์เซอร์เลือก fallback บางส่วน ทำให้ supermarket ที่ติดตั้งอยู่ในเครื่องคุณถูกใช้แสดงภาษาไทยได้

ดังนั้น บนเครื่องคุณอาจเห็น Supermarket เพราะเครื่องมีฟอนต์นี้ติดตั้งอยู่ แต่คนอื่นที่ไม่มีฟอนต์ Supermarket อาจเห็นคนละแบบครับ

ถ้าต้องการให้ทุกคนเห็นเหมือนกัน ควรเอาไฟล์ฟอนต์ขึ้นเว็บแล้วประกาศ @font-face จากนั้นใช้:

font-family:
    "supermarket",
    "Segoe UI",
    Tahoma,
    Arial,
    sans-serif;

แบบนี้เว็บจะโหลด Supermarket จากเซิร์ฟเวอร์เอง ไม่ต้องพึ่งว่าคอมพิวเตอร์ของผู้ชมติดตั้งฟอนต์ไว้หรือไม่ครับ.
ชื่อ: ต่อ: smf
โดย: vs เมื่อ 18 ส.ค 26, 13:57:05
ง่ายสุดสำหรับปรับขนาด Fonts คือเพิ่มคำสั่งนี้ไว้ใน index.css

/* ===== Slightly Larger SMF Font ===== */
body {
    font-size: 95%;
}
ชื่อ: ต่อ: smf
โดย: vs เมื่อ 08 ต.ค 26, 15:19:53
# SMF 2.1.7 — คู่มือติดตั้ง YouTube แนวตั้ง 9:16

**คู่มือฉบับใช้งานจริง | 8 ตุลาคม 2026**

ต้นฉบับของคู่มือนี้เป็นโค้ดที่ดึงตรงจากแพ็กเกจ `SMF_YouTube_Vertical_2.1.7.zip` ซึ่งผู้ใช้ได้นำ 3 ไฟล์ไปติดตั้งแล้ว **ยืนยันว่าช่อง "วิดีโอแนวตั้ง 9:16" ปรากฏในหน้าต่างแทรก YouTube** อย่างถูกต้อง ณ วันดังกล่าว แต่ยังไม่ใช่การยืนยันการเล่นวิดีโอทุกลักษณะหรือทุกธีม

## จุดประสงค์
- แทรก YouTube แบบปกติผ่าน `[youtube]VIDEO_ID[/youtube]` ตามเดิม
- เพิ่มทางเลือกแนวตั้งผ่าน `[youtube=vertical]VIDEO_ID[/youtube]`
- ในหน้าเขียนกระทู้ มี Checkbox `วิดีโอแนวตั้ง 9:16` ให้เลือกเอง
- สำหรับแนวตั้งกำหนดพื้นที่แสดงอัตราส่วน **9:16** กว้างสูงสุด 360px และรองรับหน้าจอแคบ

## ไฟล์ที่แก้ (3 ไฟล์)
| ไฟล์ | ตำแหน่งภายในโฟลเดอร์ forum |
|---|---|
| `Subs.php` | `Sources/Subs.php` |
| `index.css` | `Themes/default/css/index.css` |
| `jquery.sceditor.smf.js` | `Themes/default/scripts/jquery.sceditor.smf.js` |

**ข้อสำคัญ:** คัดลอกทั้งโค้ดต้นฉบับของ SMF 2.1.7 มาแก้เฉพาะส่วน อย่านำทั้งไฟล์ที่แนบไปทับ SMF เวอร์ชันอื่นหรือเว็บที่มีส่วนขยาย/ธีมปรับแต่งโดยไม่เปรียบเทียบก่อน

## ขั้นตอนก่อนแก้
1. สำรองทั้ง 3 ไฟล์จากเว็บปลายทาง โดยระบุวันที่และชื่อเว็บ เช่น `backup_2026-10-08` และเก็บไฟล์ที่ใช้งานจริงไว้ต่างหาก
2. ตรวจสอบเวอร์ชัน SMF (ชุดนี้ใช้กับ **2.1.7**) และธีมที่ใช้งานจริง ถ้าไม่ใช่ `default` ต้องตรวจว่าโหลด JS/CSS จากตำแหน่งใด
3. ใช้การแทนที่ชุด YouTube เดิมใน JS ไม่เพิ่ม `set('youtube')` ซ้ำ

## 1) `Sources/Subs.php`
ค้นหา array ที่มี `'tag' => 'youtube'` และ `'type' => 'unparsed_content'` ซึ่งรองรับวิดีโอปกติ

**เพิ่ม array นี้ไว้ทันที *ก่อน* array YouTube ปกติ โดยไม่ลบของเดิม:**

```php
// YouTube Shorts / portrait videos, [youtube=vertical]VIDEO_ID[/youtube]
array(
'tag' => 'youtube',
'type' => 'unparsed_equals_content',
'test' => 'vertical\]',
'content' => '<div class="videocontainer" data-youtube-orientation="vertical"><div><iframe frameborder="0" src="https://www.youtube.com/embed/$1?origin=' . $hosturl . '&wmode=opaque" data-youtube-id="$1" allowfullscreen loading="lazy"></iframe></div></div>',
'disabled_content' => '<a href="https://www.youtube.com/watch?v=$1" target="_blank" rel="noopener">https://www.youtube.com/watch?v=$1</a>',
'block_level' => true,
),
```

เหตุผล: YouTube แนวตั้งต้องถูกแยกด้วย `'type' => 'unparsed_equals_content'` และ `test => 'vertical\]'` เพื่อจับ `[youtube=vertical]` ก่อนกรณี YouTube ทั่วไป

## 2) `Themes/default/css/index.css`
เพิ่มบล็อกนี้ **หนึ่งครั้งที่ท้ายไฟล์** (ถ้ามีบล็อกแนวตั้งเก่าอยู่แล้ว ให้แทนที่ ไม่เพิ่มซ้ำ):

```css
/* YouTube portrait video 9:16 */
.videocontainer[data-youtube-orientation="vertical"] {
display: inline-block;
vertical-align: top;
width: 360px;
max-width: 100%;
margin: 0 12px 12px 0;
}
.videocontainer[data-youtube-orientation="vertical"] > div {
padding-bottom: 177.7777778%;
}
```

`padding-bottom: 177.7777778%` คืออัตราส่วนสูงต่อกว้าง 16:9 สำหรับกรอบแนวตั้ง **กว้าง:สูง = 9:16**

## 3) `Themes/default/scripts/jquery.sceditor.smf.js`
ต้องแก้ **สองจุด** ในไฟล์เดียวกัน โดยใช้ **แทนที่** โค้ดเดิม ไม่ใช่แปะท้ายไฟล์เพิ่ม

### 3A — แทนที่ `sceditor.command.set('youtube', ...)` ทั้งชุด
ค้นหา `sceditor.command.set(` ที่มี `'youtube'` (ของ SMF เดิมมี `exec` แต่ยังไม่มีช่องติ๊ก) แล้วแทนที่ทั้งคำสั่งด้วย:

```javascript
sceditor.command.set(
'youtube', {
_dropDown: function (editor, caller, callback) {
var content = document.createElement('div');
var label = document.createElement('label');
label.textContent = editor._('Video URL:');
label.style.display = 'block';
label.style.marginBottom = '4px';

var input = document.createElement('input');
input.type = 'text';
input.placeholder = 'https://';
input.style.width = '100%';
input.style.boxSizing = 'border-box';

var verticalWrap = document.createElement('label');
verticalWrap.style.display = 'block';
verticalWrap.style.marginTop = '10px';
verticalWrap.style.marginBottom = '10px';
verticalWrap.style.cursor = 'pointer';
var vertical = document.createElement('input');
vertical.type = 'checkbox';
vertical.style.marginRight = '6px';
verticalWrap.appendChild(vertical);
verticalWrap.appendChild(document.createTextNode('วิดีโอแนวตั้ง 9:16'));

var button = document.createElement('button');
button.type = 'button';
button.className = 'button';
button.textContent = editor._('Insert');

content.appendChild(label);
content.appendChild(input);
content.appendChild(verticalWrap);
content.appendChild(button);

function insertYoutube(e) {
var val = input.value.trim();
var idMatch = val.match(/(?:v=|v\/|embed\/|youtu\.be\/|shorts\/)([a-zA-Z0-9_-]{11})/);
if (!idMatch && /^[a-zA-Z0-9_-]{11}$/.test(val))
idMatch = [val, val];

var timeMatch = val.match(/[&?](?:start|t)=((\d+[hms]?){1,3})/i);
var time = 0;
if (timeMatch) {
timeMatch[1].split(/[hms]/).forEach(function (part) {
if (part !== '')
time = (time * 60) + Number(part);
});
}

if (idMatch)
callback(idMatch[1], time, vertical.checked);

editor.closeDropDown(true);
if (e)
e.preventDefault();
}

button.addEventListener('click', insertYoutube);
input.addEventListener('keypress', function (e) {
if (e.key === 'Enter') insertYoutube(e);
});
editor.createDropDown(caller, 'insertlink', content);
setTimeout(function () { input.focus(); }, 0);
},
exec: function (caller) {
var editor = this;
editor.commands.youtube._dropDown(editor, caller, function (id, time, isVertical) {
var orientation = isVertical ? ' data-youtube-orientation="vertical"' : '';
editor.wysiwygEditorInsertHtml(
'<div class="videocontainer"' + orientation + '><div>' +
'<iframe frameborder="0" allowfullscreen src="https://www.youtube-nocookie.com/embed/' +
id + '?wmode=opaque&start=' + time + '" data-youtube-id="' + id +
'" loading="lazy"></iframe></div></div>'
);
});
},
txtExec: function (caller) {
var editor = this;
editor.commands.youtube._dropDown(editor, caller, function (id, time, isVertical) {
editor.insertText('[youtube' + (isVertical ? '=vertical' : '') + ']' + id + '[/youtube]');
});
}
}
);
```

### 3B — แทนที่ `sceditor.formats.bbcode.set('youtube', ...)` ทั้งชุด
ค้นหา `sceditor.formats.bbcode.set(` ที่มี `'youtube'` และ **แทนที่ชุดเดิมทั้งหมด** ด้วย:

```javascript
sceditor.formats.bbcode.set(
'youtube', {
allowsEmpty: true,
tags: {
div: { class: 'videocontainer' }
},
isInline: false,
skipLastLineBreak: true,
format: function (element, content) {
var $element = $(element);
var youtube_id = $element.find('iframe').data('youtube-id');
var orientation = $element.attr('data-youtube-orientation');
if (typeof youtube_id !== 'undefined')
return '[youtube' + (orientation === 'vertical' ? '=vertical' : '') + ']' + youtube_id + '[/youtube]';
return content;
},
html: function (token, attrs, content) {
if (!/^[a-zA-Z0-9_-]{11}$/.test(content))
return content;
var orientation = attrs.defaultattr === 'vertical' ? ' data-youtube-orientation="vertical"' : '';
return '<div class="videocontainer"' + orientation + '><div>' +
'<iframe frameborder="0" src="https://www.youtube-nocookie.com/embed/' + content +
'?wmode=opaque" data-youtube-id="' + content +
'" loading="lazy" allowfullscreen></iframe></div></div>';
}
}
);
```

**ก่อนบันทึก ตรวจอีกครั้ง:** ต้องมี `sceditor.command.set('youtube', ...)` เพียงชุดเดียว และ `sceditor.formats.bbcode.set('youtube', ...)` เพียงชุดเดียว (อย่าให้ BBCode YouTube ถูกประกาศซ้ำ)

## สิ่งที่ผิดในบันทึกเดิม และสิ่งที่แก้
1. **PHP:** บันทึกเดิมมี `;` หลัง `'?origin='` ทำให้ต่อ PHP String กับ `$hosturl` ไม่ถูกต้อง โค้ดที่ถูกคือ `'?origin=' . $hosturl . '&wmode=opaque'` (ไม่มี `;` กลาง expression)
2. **JavaScript:** URL `'.../embed/'; +` มี semicolon เกิน **2 ตำแหน่ง** (คำสั่ง Insert และการแปลง BBCode) ต้องเป็น `'.../embed/' +`
3. **JS BBCode:** ข้อความว่า "และเพิ่มตอนท้าย" ทำให้ประกาศ YouTube ซ้ำ ต้อง "**แทนที่ชุดเดิม**"
4. **CSS:** บันทึกเดิมกำหนด `.videocontainer[data-youtube-orientation="vertical"]` สองครั้ง การทำงานไม่จำเป็นต้องเสีย แต่ควรรวมเหลือกฎชุดเดียวอย่างในคู่มือนี้

## ทดสอบหลังอัปโหลด
1. อัปโหลดไฟล์ทั้ง 3 ไปยังตำแหน่งที่กำหนด (ชื่อไฟล์บนเซิร์ฟเวอร์ต้องตรงตามตาราง ไม่ใช่ชื่อ `(2)` ที่ดาวน์โหลด)
2. ไปหน้าเขียนกระทู้ กด `Ctrl + F5` เพื่อโหลด CSS และ JS ใหม่ แล้วกดปุ่ม YouTube
3. ต้องเห็น URL + **Checkbox "วิดีโอแนวตั้ง 9:16"** + ปุ่มแทรก
4. ทดสอบวิดีโอปกติ **ไม่ติ๊ก** → สร้าง `[youtube]VIDEO_ID[/youtube]`
5. ทดสอบวิดีโอแนวตั้ง **ติ๊ก** → สร้าง `[youtube=vertical]VIDEO_ID[/youtube]`
6. บันทึกกระทู้และเปิดดูบนคอมพิวเตอร์/มือถือ จากนั้นแก้ไขกระทู้อีกครั้งเพื่อตรวจว่า tag แนวตั้งยังอยู่

## ถ้า Checkbox ยังไม่ขึ้น
**อย่ารีบแก้สามไฟล์ใหม่** ให้ตรวจเส้นทาง JS ที่ Browser โหลดก่อน: F12 → Network → ค้นหา `jquery.sceditor.smf.js` → ดู `Request URL` ว่ามาจาก Theme/Path ที่อัปโหลดหรือไม่ หากใช้ไฟล์รวม/minified หรือ cache ต้องปรับตามไฟล์ที่เว็บใช้จริง

## การย้อนกลับ (Rollback)
คืน `Subs.php`, `index.css`, และ `jquery.sceditor.smf.js` จาก Backup ของเว็บเดียวกันและช่วงเวลาเดียวกัน แล้ว Hard Refresh อีกครั้ง

## ไฟล์สำเร็จรูป
ในแพ็กเกจ ZIP คู่มือ จะมีไฟล์ที่ใช้งานได้จริงอยู่ในโครงสร้าง `Sources/` และ `Themes/default/` พร้อมแพตช์เทียบกับ Baseline ที่ผู้ใช้ส่งมาเป็น `* (2)` โดยไม่รวมข้อมูลบัญชีหรือค่าติดตั้งเว็บอื่น