この記事は、名前変換スクリプトCharm.jsの拡張機能の解説です。
カスタム変換(カタカナ変換、区切り等)とは別の説明となっておりますので、ご注意ください。
※カスタム変換の説明はこちら(本館サイト)
spanタグ削除について
機能概要
名前変換後にspanタグの囲みを削除し、プレーンテキストに直します。
注意・補足
- 画面に表示された直後はタグがあるので、タグ削除までタイムラグがあります。
- 名前登録フォームのあるページでは動作しないようになっています。(フォームのページでこの拡張が動いてしまうと、名前の上書き登録ができなくなってしまうので)
編集が必要なところ
削除対象のクラス名の共通部分を、’クラス名’という形でコード内のtargetClassに書きます。
コードがわかる方は他にも編集して構いませんが、基本的にはそのまま使えます。
拡張機能コード全体
/**
* 名前変換後にspanタグを削除する拡張機能
*
* 指定されたクラス名を持つspanタグを削除し、その子要素のTextNodeを親要素に移動する
* - 再登録を反映できるようにするため、登録のための入力欄があるページでは動作しません
* - spanタグが無いので、リロードなしでは復元系機能は基本的に動かなくなります
*/
class ElementRemover {
// 削除対象のクラス名共通文字
static targetClass = 'charmname';
/**
* プラグインの実行メソッド
* @returns {ElementRemover} インスタンス
*/
static run = () => {
let instance = new ElementRemover();
instance.start();
return instance;
}
/**
* コンストラクタ
*/
constructor() {
this.nameClass = Charm.nameClass;
}
/**
* 入力タグが存在するかどうかをチェック
* @returns {boolean} 入力タグが存在する場合はtrue、それ以外はfalse
*/
hasSyncTags = () => {
return document.getElementsByClassName(this.nameClass).length > 0;
}
/**
* spanタグを削除し、親要素のテキストノードを一つに結合する処理を開始
*/
start = () => {
// 再登録をできるようにするため、入力タグが存在する場合は処理をしない
if (this.hasSyncTags()) return;
// 削除対象のspanタグを取得
const elms = this.getSpanElms();
const elmsArray = Array.from(elms);
// 親要素をセットにして保持
const allParents = new Set(elmsArray.map(elm => elm.parentElement));
// 各spanタグを処理
elms.forEach(elm => {
this.removeSpan(elm);
});
// 各親要素のテキストノードを結合
allParents.forEach(parent => {
this.combineTextNodes(parent);
});
}
/**
* spanタグを削除し、その子要素を親要素に移動
* @param {HTMLElement} elm - 削除対象のspanタグ
*/
removeSpan = (elm) => {
const parent = elm.parentElement;
// spanタグ内のテキストを取得
const text = elm.textContent;
// 親要素にテキストノードを追加
parent.insertBefore(document.createTextNode(text), elm);
// spanタグを削除
parent.removeChild(elm);
}
/**
* 親要素のすべてのテキストノードを一つに結合
* @param {HTMLElement} parent - 親要素
*/
combineTextNodes = (parent) => {
let combinedText = '';
const nodes = Array.from(parent.childNodes);
const fragment = document.createDocumentFragment();
nodes.forEach(node => {
if (node.nodeType === Node.TEXT_NODE) {
// テキストノードを結合
combinedText += node.nodeValue;
} else {
if (combinedText) {
// 結合されたテキストをフラグメントに追加
fragment.appendChild(document.createTextNode(combinedText));
combinedText = '';
}
// その他のノードをフラグメントに追加
fragment.appendChild(node);
}
});
// 残った結合テキストをフラグメントに追加
if (combinedText) {
fragment.appendChild(document.createTextNode(combinedText));
}
// 親要素の内容を新しいフラグメントで置き換え
while (parent.firstChild) {
parent.removeChild(parent.firstChild);
}
parent.appendChild(fragment);
}
/**
* 対象のspanタグを取得
* @returns {Array} 対象のspanタグの配列
*/
getSpanElms = () => {
return document.querySelectorAll(`span[class*="${ElementRemover.targetClass}"]`);
}
}
// 拡張を追加するコード
Charm.addEExtension("ElementRemover", ElementRemover);
圧縮版はこちらです。
ファイル容量を削減する場合はこちらをご利用ください。
/**
* 名前変換後にspanタグを削除する拡張機能
*
* 指定されたクラス名を持つspanタグを削除し、その子要素のTextNodeを親要素に移動する
* - 再登録を反映できるようにするため、登録のための入力欄があるページでは動作しません
* - spanタグが無いので、リロードなしでは復元系機能は基本的に動かなくなります
*/
class ElementRemover{static targetClass="charmname";static run=()=>{let e=new ElementRemover;return e.start(),e};constructor(){this.nameClass=Charm.nameClass}hasSyncTags=()=>document.getElementsByClassName(this.nameClass).length>0;start=()=>{if(this.hasSyncTags())return;let e=this.getSpanElms(),t=Array.from(e),a=new Set(t.map(e=>e.parentElement));e.forEach(e=>{this.removeSpan(e)}),a.forEach(e=>{this.combineTextNodes(e)})};removeSpan=e=>{let t=e.parentElement,a=e.textContent;t.insertBefore(document.createTextNode(a),e),t.removeChild(e)};combineTextNodes=e=>{let t="",a=Array.from(e.childNodes),n=document.createDocumentFragment();for(a.forEach(e=>{e.nodeType===Node.TEXT_NODE?t+=e.nodeValue:(t&&(n.appendChild(document.createTextNode(t)),t=""),n.appendChild(e))}),t&&n.appendChild(document.createTextNode(t));e.firstChild;)e.removeChild(e.firstChild);e.appendChild(n)};getSpanElms=()=>document.querySelectorAll(`span[class*="${ElementRemover.targetClass}"]`)}Charm.addEExtension("ElementRemover",ElementRemover);