/** * Template Loader Service - บริการสำหรับโหลดเทมเพลตจากแหล่งต่างๆ */ (function(global) { 'use strict'; /** * คลาส TemplateLoader * บริการสำหรับโหลดเทมเพลตจากแหล่งต่างๆ */ class TemplateLoader { constructor(editor) { this.editor = editor; this.cache = {}; this.loadingPromises = {}; } /** * โหลดเทมเพลตจาก URL * @param {string} url - URL ของเทมเพลต * @param {Object} options - ตัวเลือก (optional) * @returns {Promise} Promise ที่ส่งคืนเนื้อหาเทมเพลต */ loadFromURL(url, options = {}) { // ตรวจสอบแคช if (this.cache[url]) { return Promise.resolve(this.cache[url]); } // ตรวจสอบว่ากำลังโหลดอยู่หรือไม่ if (this.loadingPromises[url]) { return this.loadingPromises[url]; } // สร้าง Promise สำหรับการโหลด const promise = new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.onload = () => { if (xhr.status === 200) { const template = xhr.responseText; // เก็บในแคช this.cache[url] = template; // ลบจากรายการที่กำลังโหลด delete this.loadingPromises[url]; // ส่งเหตุการณ์ this.editor.emit('template:loaded', {url, template}); resolve(template); } else { reject(new Error(`Failed to load template: ${xhr.status} ${xhr.statusText}`)); } }; xhr.onerror = () => { reject(new Error(`Network error while loading template: ${url}`)); }; xhr.send(); }); // เก็บ Promise ที่กำลังโหลด this.loadingPromises[url] = promise; return promise; } /** * โหลดเทมเพลตจากอิลิเมนต์ * @param {string} selector - ตัวเลือก CSS ของอิลิเมนต์เทมเพลต * @param {Object} options - ตัวเลือก (optional) * @returns {Promise} Promise ที่ส่งคืนเนื้อหาเทมเพลต */ loadFromElement(selector, options = {}) { return new Promise((resolve, reject) => { try { const element = document.querySelector(selector); if (!element) { reject(new Error(`Template element not found: ${selector}`)); return; } const template = element.innerHTML; // ส่งเหตุการณ์ this.editor.emit('template:loaded', {selector, template}); resolve(template); } catch (error) { reject(error); } }); } /** * โหลดเทมเพลตจากข้อความ * @param {string} template - ข้อความเทมเพลต * @param {Object} options - ตัวเลือก (optional) * @returns {Promise} Promise ที่ส่งคืนเนื้อหาเทมเพลต */ loadFromString(template, options = {}) { return new Promise((resolve) => { // ส่งเหตุการณ์ this.editor.emit('template:loaded', {template}); resolve(template); }); } /** * โหลดเทมเพลตจาก localStorage * @param {string} key - คีย์ใน localStorage * @param {Object} options - ตัวเลือก (optional) * @returns {Promise} Promise ที่ส่งคืนเนื้อหาเทมเพลต */ loadFromStorage(key, options = {}) { return new Promise((resolve, reject) => { try { const template = localStorage.getItem(key); if (!template) { reject(new Error(`Template not found in storage: ${key}`)); return; } // ส่งเหตุการณ์ this.editor.emit('template:loaded', {key, template}); resolve(template); } catch (error) { reject(error); } }); } /** * โหลดเทมเพลตจาก JSON * @param {string} url - URL ของไฟล์ JSON * @param {Object} options - ตัวเลือก (optional) * @returns {Promise} Promise ที่ส่งคืนเนื้อหาเทมเพลต */ loadFromJSON(url, options = {}) { // ตรวจสอบแคช if (this.cache[url]) { return Promise.resolve(this.cache[url]); } // ตรวจสอบว่ากำลังโหลดอยู่หรือไม่ if (this.loadingPromises[url]) { return this.loadingPromises[url]; } // สร้าง Promise สำหรับการโหลด const promise = new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = 'json'; xhr.onload = () => { if (xhr.status === 200) { const data = xhr.response; // แปลง JSON เป็น HTML let template = ''; if (data.html) { template = data.html; } else if (data.template) { template = data.template; } else { // ถ้าไม่มีฟิลด์ html หรือ template ให้ใช้ทั้งหมด template = JSON.stringify(data); } // เก็บในแคช this.cache[url] = template; // ลบจากรายการที่กำลังโหลด delete this.loadingPromises[url]; // ส่งเหตุการณ์ this.editor.emit('template:loaded', {url, template, data}); resolve(template); } else { reject(new Error(`Failed to load JSON template: ${xhr.status} ${xhr.statusText}`)); } }; xhr.onerror = () => { reject(new Error(`Network error while loading JSON template: ${url}`)); }; xhr.send(); }); // เก็บ Promise ที่กำลังโหลด this.loadingPromises[url] = promise; return promise; } /** * โหลดเทมเพลตหลายรายการพร้อมกัน * @param {Array} sources - รายการแหล่งที่จะโหลด * @param {Object} options - ตัวเลือก (optional) * @returns {Promise} Promise ที่ส่งคืนอาร์เรย์ของเทมเพลต */ loadMultiple(sources, options = {}) { const promises = sources.map(source => { if (typeof source === 'string') { // ถ้าเป็นสตริง ให้โหลดจาก URL return this.loadFromURL(source, options); } else if (source.url) { // ถ้าเป็นออบเจกต์ที่มี url return this.loadFromURL(source.url, options); } else if (source.selector) { // ถ้าเป็นออบเจกต์ที่มี selector return this.loadFromElement(source.selector, options); } else if (source.key) { // ถ้าเป็นออบเจกต์ที่มี key return this.loadFromStorage(source.key, options); } else if (source.template) { // ถ้าเป็นออบเจกต์ที่มี template return this.loadFromString(source.template, options); } else { // ถ้าไม่ตรงกับเงื่อนไขใดๆ ให้ส่ง Promise ที่ reject return Promise.reject(new Error('Invalid source format')); } }); return Promise.all(promises); } /** * ล้างแคช * @param {string} url - URL ที่จะลบจากแคช (optional) */ clearCache(url = null) { if (url) { delete this.cache[url]; } else { this.cache = {}; } } /** * ตรวจสอบว่ามีในแคชหรือไม่ * @param {string} url - URL ที่จะตรวจสอบ * @returns {boolean} มีในแคชหรือไม่ */ isInCache(url) { return !!this.cache[url]; } /** * รับข้อมูลจากแคช * @param {string} url - URL ที่จะรับข้อมูล * @returns {string} ข้อมูลในแคช */ getFromCache(url) { return this.cache[url] || null; } /** * เพิ่มข้อมูลในแคช * @param {string} url - URL * @param {string} template - เนื้อหาเทมเพลต */ addToCache(url, template) { this.cache[url] = template; } } // เปิดเผยคลาส TemplateLoader ทั่วโลก global.TemplateLoader = TemplateLoader; })(typeof window !== 'undefined' ? window : this);