【Charm.js拡張機能】「spanタグ削除」の使い方

Charm.js

この記事は、名前変換スクリプト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);

タイトルとURLをコピーしました