/**
* 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);