Custom Arka Plan Yöneticisi

Web siteleri için arka plan değiştirme [öncelikli manga-manhwa siteleri]

当前为 2025-01-28 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Custom Arka Plan Yöneticisi
  3. // @namespace http://Vebascans.net/
  4. // @version 2.3
  5. // @description Web siteleri için arka plan değiştirme [öncelikli manga-manhwa siteleri]
  6. // @author www.vebascans.net
  7. // @match https://*/*
  8. // @grant none
  9. // @icon https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhi0QDJZNeXWcaD9lXWMN2yenYt5XGrqfPavkCFpWLe01CpSEsMn7IGpbOLqxEfjx4QUUi4wgTw0Kc7vP7FrKjPKpcaaCu1N6QRJzlZvS_Wwr2r3kA4l0-E5wl7xObsZchd8YNSxySFZATPAr2bnrkANBUrmy8Rpdexe-mxG8N6QDojEj0onaNNXF_6g-s/w800/logo.png
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. // 1) SweetAlert2 kütüphanesini otomatik yükle:
  16. const script = document.createElement('script');
  17. script.src = 'https://cdn.jsdelivr.net/npm/sweetalert2@11';
  18. script.onload = main; // Kütüphane yüklendikten sonra main() fonksiyonunu çalıştır
  19. document.head.appendChild(script);
  20.  
  21. // 2) Tüm kodu main() içine alıyoruz:
  22. function main() {
  23.  
  24. /**************************************************************************
  25. * SweetAlert Tanımlaması
  26. **************************************************************************/
  27. const Toast = Swal.mixin({
  28. toast: true,
  29. position: "top",
  30. showConfirmButton: false,
  31. timer: 3000,
  32. timerProgressBar: true,
  33. didOpen: (toast) => {
  34. toast.onmouseenter = Swal.stopTimer;
  35. toast.onmouseleave = Swal.resumeTimer;
  36. }
  37. });
  38.  
  39. /**************************************************************************
  40. * 0) Sabitler
  41. **************************************************************************/
  42. const ACTIVE_KEY = 'VebaScans.net_custom_wp_active'; // Son seçilen veri (URL/Color)
  43. const HISTORY_KEY = 'VebaScans.net_custom_wp_history'; // Tüm geçmiş
  44. const SETTINGS_KEY = 'vebascans.net_custom_wp_settings'; // Arka plan ayarları
  45.  
  46. /**************************************************************************
  47. * 1) Local Storage Yardımcı Fonksiyonları
  48. **************************************************************************/
  49. function getActiveData() {
  50. try {
  51. const str = localStorage.getItem(ACTIVE_KEY);
  52. return str ? JSON.parse(str) : null;
  53. } catch (e) {
  54. return null;
  55. }
  56. }
  57.  
  58. function setActiveData(obj) {
  59. localStorage.setItem(ACTIVE_KEY, JSON.stringify(obj));
  60. applyActiveDataToBody(); // Aktif veri her değiştiğinde body'yi güncelle
  61. }
  62.  
  63. function removeActiveData() {
  64. localStorage.removeItem(ACTIVE_KEY);
  65. applyActiveDataToBody();
  66. }
  67.  
  68. function getHistoryData() {
  69. try {
  70. const str = localStorage.getItem(HISTORY_KEY);
  71. return str ? JSON.parse(str) : [];
  72. } catch (e) {
  73. return [];
  74. }
  75. }
  76.  
  77. function addToHistory(obj) {
  78. let history = getHistoryData();
  79.  
  80. // 1) Eğer geçmişte aynı öğe zaten varsa ekleme yapma
  81. const exists = history.some(item => item.type === obj.type && item.value === obj.value);
  82. if (exists) return; // Aynısı varsa, ekleme yapmadan çık
  83.  
  84. // 2) Yeni öğeyi ekle
  85. history.push(obj);
  86.  
  87. // 3) Aynı öğelerin tekrarını önlemek için filtrele (sadece bir tane kalacak)
  88. history = history.filter((item, index, self) =>
  89. index === self.findIndex(t => t.type === item.type && t.value === item.value)
  90. );
  91.  
  92. // 4) Güncellenmiş geçmişi kaydet
  93. localStorage.setItem(HISTORY_KEY, JSON.stringify(history));
  94. }
  95.  
  96. // Geçmişten silme
  97. function removeFromHistory(obj) {
  98. let history = getHistoryData();
  99. history = history.filter(x => !(x.type === obj.type && x.value === obj.value));
  100. localStorage.setItem(HISTORY_KEY, JSON.stringify(history));
  101. }
  102.  
  103. // Ayarlar
  104. function getSettings() {
  105. try {
  106. const str = localStorage.getItem(SETTINGS_KEY);
  107. return str ? JSON.parse(str) : {};
  108. } catch (e) {
  109. return {};
  110. }
  111. }
  112.  
  113. function setSettings(newSettings) {
  114. localStorage.setItem(SETTINGS_KEY, JSON.stringify(newSettings));
  115. }
  116.  
  117. /**************************************************************************
  118. * 2) BODY Arkaplanını Aktif Veriye (URL/Color) ve Ayarlara Göre Uygulama
  119. **************************************************************************/
  120. function applyActiveDataToBody() {
  121. const activeData = getActiveData();
  122. const settings = getSettings();
  123.  
  124. // Arkaplan tekrar ayarı (varsayılan = 'no-repeat')
  125. const bgRepeat = settings.bgRepeat || 'no-repeat';
  126. // Arkaplan sabit ayarı (varsayılan = 'scroll')
  127. const bgAttachment = settings.bgAttachment || 'scroll';
  128.  
  129. if (!activeData) {
  130. // Aktif bir şey yoksa varsayılan temize çek
  131. document.body.style.backgroundImage = '';
  132. document.body.style.backgroundColor = '';
  133. document.body.style.backgroundRepeat = '';
  134. document.body.style.backgroundAttachment = '';
  135. return;
  136. }
  137.  
  138. if (activeData.type === 'url') {
  139. // Body için arkaplan resmi
  140. document.body.style.backgroundImage = `url(${activeData.value})`;
  141. document.body.style.backgroundRepeat = bgRepeat;
  142. document.body.style.backgroundSize = 'cover';
  143. document.body.style.backgroundAttachment = bgAttachment;
  144. document.body.style.backgroundColor = '';
  145.  
  146. // .body-wrap için
  147. try {
  148. const bodyWrap = document.querySelector('body.text-ui-light .body-wrap');
  149. bodyWrap.style.backgroundImage = `url(${activeData.value})`;
  150. bodyWrap.style.backgroundRepeat = bgRepeat;
  151. bodyWrap.style.backgroundSize = 'cover';
  152. bodyWrap.style.backgroundAttachment = bgAttachment;
  153. bodyWrap.style.backgroundColor = '';
  154. } catch (error) { /* .body-wrap yoksa hata görmezden gel */ }
  155.  
  156. // .site-content için
  157. try {
  158. const sitecontent = document.querySelector('.site-content');
  159. sitecontent.style.backgroundImage = `url(${activeData.value})`;
  160. sitecontent.style.backgroundRepeat = bgRepeat;
  161. sitecontent.style.backgroundSize = 'cover';
  162. sitecontent.style.backgroundAttachment = bgAttachment;
  163. sitecontent.style.backgroundColor = '';
  164. } catch (error) { /* .site-content yoksa hata görmezden gel */ }
  165.  
  166. } else if (activeData.type === 'color') {
  167. // Body için arkaplan rengi
  168. document.body.style.backgroundImage = 'none';
  169. document.body.style.backgroundColor = activeData.value;
  170. document.body.style.backgroundRepeat = bgRepeat;
  171. document.body.style.backgroundAttachment = bgAttachment;
  172.  
  173. // .body-wrap için
  174. try {
  175. const bodyWrap = document.querySelector('body.text-ui-light .body-wrap');
  176. bodyWrap.style.backgroundImage = 'none';
  177. bodyWrap.style.backgroundColor = activeData.value;
  178. bodyWrap.style.backgroundRepeat = bgRepeat;
  179. bodyWrap.style.backgroundAttachment = bgAttachment;
  180. } catch (error) { /* .body-wrap yoksa hata görmezden gel */ }
  181.  
  182. // .site-content için
  183. try {
  184. const sitecontent = document.querySelector('.site-content');
  185. sitecontent.style.backgroundImage = 'none';
  186. sitecontent.style.backgroundColor = activeData.value;
  187. sitecontent.style.backgroundRepeat = bgRepeat;
  188. sitecontent.style.backgroundAttachment = bgAttachment;
  189. } catch (error) { /* .site-content yoksa hata görmezden gel */ }
  190. }
  191. }
  192.  
  193. /**************************************************************************
  194. * 3) MODAL Arayüzü Oluşturma
  195. **************************************************************************/
  196. let modalOverlay, modalContent;
  197.  
  198. window.addEventListener('load', () => {
  199. createModal();
  200. createToggleShortcut(); // F7 ile aç/kapa
  201. applyActiveDataToBody(); // Sayfa açıldığında kaydedilmiş aktif veriyi uygula
  202. });
  203.  
  204. // F7 ile modal aç/kapa
  205. function createToggleShortcut() {
  206. window.addEventListener('keydown', (e) => {
  207. if (e.key === 'F7') {
  208. toggleModal();
  209. }
  210. });
  211. }
  212.  
  213. function toggleModal(forceOpen) {
  214. const isHidden = (modalOverlay.style.display === 'none');
  215. if (forceOpen === true) {
  216. showModal();
  217. } else if (forceOpen === false) {
  218. hideModal();
  219. } else {
  220. if (isHidden) showModal(); else hideModal();
  221. }
  222. }
  223.  
  224. function showModal() {
  225. modalOverlay.style.display = 'block';
  226. refreshHistoryList();
  227. refreshActiveLabel();
  228. refreshSettingsUI();
  229. }
  230.  
  231. function hideModal() {
  232. modalOverlay.style.display = 'none';
  233. }
  234.  
  235. function createModal() {
  236. // (1) Overlay
  237. modalOverlay = document.createElement('div');
  238. Object.assign(modalOverlay.style, {
  239. display: 'none',
  240. position: 'fixed',
  241. top: '0',
  242. left: '0',
  243. width: '100%',
  244. height: '100%',
  245. backgroundColor: 'rgba(0,0,0,0.5)',
  246. zIndex: '99999',
  247. color: '#000'
  248. });
  249. document.body.appendChild(modalOverlay);
  250.  
  251. // (2) İçerik
  252. modalContent = document.createElement('div');
  253. Object.assign(modalContent.style, {
  254. position: 'absolute',
  255. top: '50%',
  256. left: '50%',
  257. transform: 'translate(-50%, -50%)',
  258. width: '400px',
  259. backgroundColor: '#fff',
  260. padding: '20px',
  261. borderTopLeftRadius: '15px',
  262. borderBottomRightRadius: '15px',
  263. border: '3px solid black',
  264. minHeight: '450px',
  265. fontFamily: 'Arial, sans-serif',
  266. fontSize: '14px',
  267. fontWeight: 'normal',
  268. color: '#000',
  269. });
  270. modalOverlay.appendChild(modalContent);
  271.  
  272. // (3) Logo
  273. const img = document.createElement('img');
  274. img.src = 'https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhi0QDJZNeXWcaD9lXWMN2yenYt5XGrqfPavkCFpWLe01CpSEsMn7IGpbOLqxEfjx4QUUi4wgTw0Kc7vP7FrKjPKpcaaCu1N6QRJzlZvS_Wwr2r3kA4l0-E5wl7xObsZchd8YNSxySFZATPAr2bnrkANBUrmy8Rpdexe-mxG8N6QDojEj0onaNNXF_6g-s/w800/logo.png';
  275. img.alt = 'Logo';
  276. Object.assign(img.style, {
  277. width: '130px',
  278. position: 'absolute',
  279. top: '0',
  280. right: '50%',
  281. transform: 'translate(50%, -50%)'
  282. });
  283. modalContent.appendChild(img);
  284.  
  285. // (4) Başlık
  286. const header = document.createElement('h3');
  287. header.innerHTML = '<a href="https://www.vebascans.net/" style="color: #402870; font-weight: 500; text-decoration: none; font-family: fantasy;">Vebascans</a> - Custom Background';
  288. header.style.margin = '0 0 10px 0';
  289. header.style.color = 'black';
  290. header.style.marginTop = '45px';
  291. modalContent.appendChild(header);
  292.  
  293. // (5) Kapat butonu
  294. const closeBtn = document.createElement('button');
  295. closeBtn.innerHTML = `
  296. <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
  297. <g fill="none" fill-rule="evenodd">
  298. <path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z"/>
  299. <path fill="currentColor" d="m12 14.122l5.303 5.303a1.5 1.5 0 0 0 2.122-2.122L14.12 12l5.304-5.303a1.5 1.5 0 1 0-2.122-2.121L12 9.879L6.697 4.576a1.5 1.5 0 1 0-2.122 2.12L9.88 12l-5.304 5.304a1.5 1.5 0 1 0 2.122 2.12z"/>
  300. </g>
  301. </svg>`;
  302. Object.assign(closeBtn.style, {
  303. position: 'absolute',
  304. top: '10px',
  305. right: '10px',
  306. border: 'none',
  307. background: 'transparent',
  308. cursor: 'pointer',
  309. color: 'black'
  310. });
  311. closeBtn.onclick = () => hideModal();
  312. modalContent.appendChild(closeBtn);
  313.  
  314. // (6) Seçim Menüsü (URL mi Renk mi)
  315. const selectDiv = document.createElement('div');
  316. Object.assign(selectDiv.style, {
  317. display: 'flex',
  318. flexDirection: 'row',
  319. gap: '5px',
  320. marginBottom: '10px'
  321. });
  322. modalContent.appendChild(selectDiv);
  323.  
  324. const selectLabel = document.createElement('label');
  325. selectLabel.textContent = 'Seçim: ';
  326. selectLabel.style.display = 'flex';
  327. selectLabel.style.alignItems = 'center';
  328. selectDiv.appendChild(selectLabel);
  329.  
  330. const selectInput = document.createElement('select');
  331. selectInput.id = 'typeSelect';
  332. selectInput.style.background ='white';
  333. selectInput.style.border ='2px solid black';
  334. selectInput.style.borderRadius ='3px';
  335. selectInput.style.color = 'black';
  336. const optUrl = new Option('URL', 'url');
  337. const optColor = new Option('Renk', 'color');
  338. selectInput.add(optUrl);
  339. selectInput.add(optColor);
  340. selectDiv.appendChild(selectInput);
  341.  
  342. // (7) URL input
  343. const urlInput = document.createElement('input');
  344. urlInput.type = 'text';
  345. urlInput.id = 'urlInput';
  346. urlInput.placeholder = 'Görsel URL giriniz...';
  347. urlInput.style.background ='transparent';
  348. urlInput.style.border ='2px solid black';
  349. urlInput.style.borderRadius ='3px';
  350. selectDiv.appendChild(urlInput);
  351.  
  352. // (8) Color input
  353. const colorInput = document.createElement('input');
  354. colorInput.type = 'color';
  355. colorInput.id = 'colorInput';
  356. colorInput.value = '#000000';
  357. colorInput.style.width = '50px';
  358. colorInput.style.height = '30px';
  359. colorInput.style.display = 'none';
  360. selectDiv.appendChild(colorInput);
  361.  
  362. // Seçim değişince hangi input görünsün?
  363. selectInput.addEventListener('change', () => {
  364. if (selectInput.value === 'url') {
  365. urlInput.style.display = 'inline-block';
  366. colorInput.style.display = 'none';
  367. } else {
  368. urlInput.style.display = 'none';
  369. colorInput.style.display = 'inline-block';
  370. }
  371. });
  372.  
  373. // (9) Aktar butonu
  374. const aktarBtn = document.createElement('button');
  375. aktarBtn.textContent = 'Aktar';
  376. aktarBtn.style.marginLeft = '5px';
  377. aktarBtn.style.padding = '5px 10px';
  378. aktarBtn.style.cursor = 'pointer';
  379. aktarBtn.style.color = 'black';
  380. aktarBtn.style.border ='2px solid black';
  381. aktarBtn.style.borderRadius ='3px';
  382. aktarBtn.style.background = 'transparent';
  383. selectDiv.appendChild(aktarBtn);
  384.  
  385. aktarBtn.onclick = () => {
  386. const currentType = selectInput.value; // 'url' | 'color'
  387. let currentValue = '';
  388. if (currentType === 'url') {
  389. currentValue = urlInput.value.trim();
  390. if (!currentValue) {
  391. Toast.fire({ icon: 'error', title: 'Lütfen bir URL girin.' });
  392. return;
  393. }
  394. } else {
  395. currentValue = colorInput.value; // #rrggbb
  396. if (!currentValue) {
  397. Toast.fire({ icon: 'error', title: 'Lütfen bir renk seçin.' });
  398. return;
  399. }
  400. }
  401.  
  402. // Yeni aktif obje
  403. const newActiveObj = { type: currentType, value: currentValue };
  404. setActiveData(newActiveObj);
  405. addToHistory(newActiveObj);
  406.  
  407. refreshHistoryList();
  408. refreshActiveLabel();
  409.  
  410. // URL tipini kullandıysa inputu temizleyelim
  411. if (currentType === 'url') {
  412. urlInput.value = '';
  413. }
  414. Toast.fire({ icon: 'success', title: 'Yeni aktif değer atandı ve body arkaplanı güncellendi!' });
  415. };
  416.  
  417. // (10) Tekrar / Tek Sefer AYARI
  418. const repeatDiv = document.createElement('div');
  419. repeatDiv.style.margin = '10px 0';
  420. repeatDiv.style.display = 'flex';
  421. repeatDiv.style.flexDirection = 'row';
  422. repeatDiv.style.gap = '10px';
  423. modalContent.appendChild(repeatDiv);
  424.  
  425. const repeatLabel = document.createElement('span');
  426. repeatLabel.textContent = 'Arkaplan Tekrarı:';
  427. repeatLabel.style.alignSelf = 'center';
  428. repeatDiv.appendChild(repeatLabel);
  429.  
  430. const labelRepeat = document.createElement('label');
  431. const radioRepeat = document.createElement('input');
  432. radioRepeat.type = 'radio';
  433. radioRepeat.name = 'bgRepeat';
  434. radioRepeat.value = 'repeat';
  435. radioRepeat.style.marginRight = '5px';
  436. labelRepeat.appendChild(radioRepeat);
  437. labelRepeat.appendChild(document.createTextNode('Tekrarlı'));
  438. repeatDiv.appendChild(labelRepeat);
  439.  
  440. const labelNoRepeat = document.createElement('label');
  441. const radioNoRepeat = document.createElement('input');
  442. radioNoRepeat.type = 'radio';
  443. radioNoRepeat.name = 'bgRepeat';
  444. radioNoRepeat.value = 'no-repeat';
  445. radioNoRepeat.style.marginRight = '5px';
  446. labelNoRepeat.appendChild(radioNoRepeat);
  447. labelNoRepeat.appendChild(document.createTextNode('Tek Sefer'));
  448. repeatDiv.appendChild(labelNoRepeat);
  449.  
  450. [radioRepeat, radioNoRepeat].forEach(radio => {
  451. radio.addEventListener('change', () => {
  452. const newVal = radio.value; // 'repeat' | 'no-repeat'
  453. const s = getSettings();
  454. s.bgRepeat = newVal;
  455. setSettings(s);
  456. applyActiveDataToBody();
  457. });
  458. });
  459.  
  460. // (10b) Arkaplan Sabit AYARI
  461. const attachDiv = document.createElement('div');
  462. attachDiv.style.margin = '10px 0';
  463. attachDiv.style.display = 'flex';
  464. attachDiv.style.flexDirection = 'row';
  465. attachDiv.style.gap = '10px';
  466. modalContent.appendChild(attachDiv);
  467.  
  468. const attachLabel = document.createElement('span');
  469. attachLabel.textContent = 'Arkaplan Sabitliği:';
  470. attachLabel.style.alignSelf = 'center';
  471. attachDiv.appendChild(attachLabel);
  472.  
  473. const labelFixed = document.createElement('label');
  474. const radioFixed = document.createElement('input');
  475. radioFixed.type = 'radio';
  476. radioFixed.name = 'bgAttach';
  477. radioFixed.value = 'fixed';
  478. radioFixed.style.marginRight = '5px';
  479. labelFixed.appendChild(radioFixed);
  480. labelFixed.appendChild(document.createTextNode('Sabit (Fixed)'));
  481. attachDiv.appendChild(labelFixed);
  482.  
  483. const labelScroll = document.createElement('label');
  484. const radioScroll = document.createElement('input');
  485. radioScroll.type = 'radio';
  486. radioScroll.name = 'bgAttach';
  487. radioScroll.value = 'scroll';
  488. radioScroll.style.marginRight = '5px';
  489. labelScroll.appendChild(radioScroll);
  490. labelScroll.appendChild(document.createTextNode('Kaydır (Scroll)'));
  491. attachDiv.appendChild(labelScroll);
  492.  
  493. [radioFixed, radioScroll].forEach(radio => {
  494. radio.addEventListener('change', () => {
  495. const newVal = radio.value; // 'fixed' | 'scroll'
  496. const s = getSettings();
  497. s.bgAttachment = newVal;
  498. setSettings(s);
  499. applyActiveDataToBody();
  500. });
  501. });
  502.  
  503. // (11) Aktif Veriyi Sil
  504. const removeActiveBtn = document.createElement('button');
  505. removeActiveBtn.textContent = 'Devre dışı bırak';
  506. removeActiveBtn.style.marginBottom = '10px';
  507. removeActiveBtn.style.padding = '5px 10px';
  508. removeActiveBtn.style.cursor = 'pointer';
  509. removeActiveBtn.style.color = 'black';
  510. removeActiveBtn.style.background = 'transparent';
  511. removeActiveBtn.style.border ='2px solid black';
  512. removeActiveBtn.style.borderRadius ='3px';
  513. modalContent.appendChild(removeActiveBtn);
  514.  
  515. removeActiveBtn.onclick = () => {
  516. removeActiveData();
  517. refreshHistoryList();
  518. refreshActiveLabel();
  519. Toast.fire({ icon: 'info', title: 'Aktif veri silindi. Arkaplan temizlendi.' });
  520. };
  521.  
  522. // (12) Şu anda aktif veriyi gösteren label
  523. const activeDiv = document.createElement('div');
  524. activeDiv.id = 'activeDiv';
  525. activeDiv.style.marginTop = '10px';
  526. modalContent.appendChild(activeDiv);
  527.  
  528. // (13) Geçmiş Başlık
  529. const historyTitle = document.createElement('h4');
  530. historyTitle.textContent = 'Geçmiş';
  531. historyTitle.style.margin = '10px 0 5px 0';
  532. modalContent.appendChild(historyTitle);
  533.  
  534. // (14) Geçmiş Container
  535. const historyContainer = document.createElement('div');
  536. historyContainer.id = 'historyContainer';
  537. historyContainer.style.maxHeight = '200px';
  538. historyContainer.style.overflowY = 'auto';
  539. historyContainer.style.border = '1px solid #ccc';
  540. historyContainer.style.padding = '5px';
  541. modalContent.appendChild(historyContainer);
  542.  
  543. /**************************************************************************
  544. * (Dışa / İçe Aktar)
  545. **************************************************************************/
  546. // Başlık
  547. const importExportTitle = document.createElement('h4');
  548. importExportTitle.textContent = 'Yedekleme';
  549. importExportTitle.style.margin = '10px 0 5px 0';
  550. modalContent.appendChild(importExportTitle);
  551.  
  552. // Dışa Aktar butonu
  553. const exportBtn = document.createElement('button');
  554. exportBtn.textContent = 'Dışa Aktar (JSON)';
  555. exportBtn.style.padding = '5px 10px';
  556. exportBtn.style.cursor = 'pointer';
  557. exportBtn.style.color = 'black';
  558. exportBtn.style.background = 'transparent';
  559. exportBtn.style.border = '2px solid black';
  560. exportBtn.style.borderRadius = '3px';
  561. exportBtn.style.marginRight = '10px';
  562. modalContent.appendChild(exportBtn);
  563.  
  564. exportBtn.onclick = () => {
  565. exportDataAsJson();
  566. };
  567.  
  568. // İçe Aktar butonu + <input type="file">
  569. const importBtn = document.createElement('button');
  570. importBtn.textContent = 'İçe Aktar (JSON)';
  571. importBtn.style.padding = '5px 10px';
  572. importBtn.style.cursor = 'pointer';
  573. importBtn.style.color = 'black';
  574. importBtn.style.background = 'transparent';
  575. importBtn.style.border = '2px solid black';
  576. importBtn.style.borderRadius = '3px';
  577. modalContent.appendChild(importBtn);
  578.  
  579. const importInput = document.createElement('input');
  580. importInput.type = 'file';
  581. importInput.accept = 'application/json';
  582. importInput.style.display = 'none';
  583. modalContent.appendChild(importInput);
  584.  
  585. importBtn.addEventListener('click', () => {
  586. importInput.click(); // Dosya seçme penceresini aç
  587. });
  588.  
  589. importInput.addEventListener('change', () => {
  590. if (importInput.files && importInput.files[0]) {
  591. importDataFromJson(importInput.files[0]);
  592. }
  593. });
  594. /**************************************************************************
  595. * _Eklenen Kısım Sonu_
  596. **************************************************************************/
  597. }
  598.  
  599. /**************************************************************************
  600. * 4) Geçmiş & Aktif Listeyi Güncelleme
  601. **************************************************************************/
  602. function refreshHistoryList() {
  603. const historyContainer = document.getElementById('historyContainer');
  604. if (!historyContainer) return;
  605.  
  606. historyContainer.innerHTML = '';
  607.  
  608. const historyData = getHistoryData();
  609. const activeData = getActiveData(); // {type:'...', value:'...'}
  610.  
  611. historyData.forEach((item) => {
  612. const row = document.createElement('div');
  613. row.style.display = 'flex';
  614. row.style.alignItems = 'center';
  615. row.style.marginBottom = '8px';
  616. row.style.cursor = 'pointer';
  617. row.style.justifyContent = 'space-between';
  618.  
  619. const leftPart = document.createElement('div');
  620. leftPart.style.display = 'flex';
  621. leftPart.style.alignItems = 'center';
  622. leftPart.style.gap = '8px';
  623.  
  624. // URL ise küçük görsel
  625. if (item.type === 'url') {
  626. const imgThumb = document.createElement('img');
  627. imgThumb.src = item.value;
  628. imgThumb.alt = 'Görsel';
  629. imgThumb.style.width = '30px';
  630. imgThumb.style.height = '30px';
  631. imgThumb.style.objectFit = 'cover';
  632. leftPart.appendChild(imgThumb);
  633.  
  634. const label = document.createElement('span');
  635. label.textContent = 'URL';
  636. leftPart.appendChild(label);
  637.  
  638. } else if (item.type === 'color') {
  639. // Renk ise kutu
  640. const colorBox = document.createElement('span');
  641. colorBox.style.display = 'inline-block';
  642. colorBox.style.width = '30px';
  643. colorBox.style.height = '30px';
  644. colorBox.style.backgroundColor = item.value;
  645. colorBox.style.border = '1px solid #000';
  646. leftPart.appendChild(colorBox);
  647.  
  648. const label = document.createElement('span');
  649. label.textContent = item.value;
  650. leftPart.appendChild(label);
  651. }
  652.  
  653. // Aktif mi?
  654. if (activeData && activeData.type === item.type && activeData.value === item.value) {
  655. const activeSpan = document.createElement('span');
  656. activeSpan.textContent = ' (Aktif)';
  657. activeSpan.style.color = 'green';
  658. leftPart.appendChild(activeSpan);
  659. }
  660.  
  661. // Tıklayınca bu itemi aktif yap
  662. leftPart.addEventListener('click', () => {
  663. setActiveData(item);
  664. refreshHistoryList();
  665. refreshActiveLabel();
  666. Toast.fire({ icon: 'success', title: 'Aktif değer güncellendi!' });
  667. });
  668.  
  669. // Sağ kısma "Geçmişten Sil" butonu
  670. const rightPart = document.createElement('button');
  671. rightPart.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m20 9l-1.995 11.346A2 2 0 0 1 16.035 22h-8.07a2 2 0 0 1-1.97-1.654L4 9m17-3h-5.625M3 6h5.625m0 0V4a2 2 0 0 1 2-2h2.75a2 2 0 0 1 2 2v2m-6.75 0h6.75"/></svg>';
  672. rightPart.style.border ='1px solid black';
  673. rightPart.style.borderRadius ='3px';
  674. rightPart.style.background = 'transparent';
  675. rightPart.style.padding = '3px 5px';
  676. rightPart.style.cursor = 'pointer';
  677.  
  678. rightPart.addEventListener('click', (e) => {
  679. e.stopPropagation(); // Aktif yapma tıklamasını engelle
  680.  
  681. // Aktif veriyi al
  682. const activeData = getActiveData();
  683.  
  684. // Eğer silinmek istenen veri aktif veriyle eşleşiyorsa, işlemi durdur
  685. if (activeData && activeData.type === item.type && activeData.value === item.value) {
  686. Toast.fire({ icon: 'warning', title: 'Aktif olan bir veriyi silemezsiniz!' });
  687. return; // İşlemi durdur
  688. }
  689.  
  690. // Eğer aktif veri değilse, geçmişten sil
  691. removeFromHistory(item);
  692. refreshHistoryList();
  693. Toast.fire({ icon: 'info', title: 'Geçmişten silindi.' });
  694. });
  695.  
  696. row.appendChild(leftPart);
  697. row.appendChild(rightPart);
  698. historyContainer.appendChild(row);
  699. });
  700. }
  701.  
  702. function refreshActiveLabel() {
  703. const activeDiv = document.getElementById('activeDiv');
  704. if (!activeDiv) return;
  705.  
  706. const activeData = getActiveData();
  707. if (!activeData) {
  708. activeDiv.textContent = 'Şu anda aktif bir değer yok.';
  709. } else {
  710. if (activeData.type === 'url') {
  711. activeDiv.innerHTML = `
  712. Aktif: URL
  713. <img src="${activeData.value}"
  714. alt="Aktif Görsel"
  715. style="width: 100px; height: auto; object-fit: cover; margin-left:5px;"/>
  716. `;
  717. } else {
  718. activeDiv.innerHTML = `
  719. Aktif: Renk
  720. <span style="display:inline-block; width:20px; height:20px;
  721. background-color:${activeData.value};
  722. border:1px solid #000; vertical-align:middle;">
  723. </span>
  724. ${activeData.value}
  725. `;
  726. }
  727. }
  728. }
  729.  
  730. /**************************************************************************
  731. * 5) Arkaplan Ayarı (Tekrar / Tek Sefer / Sabit) Radyo Butonlarını Güncelleme
  732. **************************************************************************/
  733. function refreshSettingsUI() {
  734. const settings = getSettings();
  735. const bgRepeat = settings.bgRepeat || 'no-repeat'; // Varsayılan no-repeat
  736. const bgAttach = settings.bgAttachment || 'scroll'; // Varsayılan scroll
  737.  
  738. const radiosRepeat = document.getElementsByName('bgRepeat');
  739. radiosRepeat.forEach(radio => {
  740. radio.checked = (radio.value === bgRepeat);
  741. });
  742.  
  743. const radiosAttach = document.getElementsByName('bgAttach');
  744. radiosAttach.forEach(radio => {
  745. radio.checked = (radio.value === bgAttach);
  746. });
  747. }
  748.  
  749. // Dışa Aktar (JSON olarak)
  750. function exportDataAsJson() {
  751. // Tek bir obje içine aktif, geçmiş ve ayarları al
  752. const data = {
  753. active: getActiveData(),
  754. history: getHistoryData(),
  755. settings: getSettings()
  756. };
  757. const jsonStr = JSON.stringify(data, null, 2);
  758.  
  759. // Dosya oluşturup otomatik indirme linki
  760. const blob = new Blob([jsonStr], { type: 'application/json' });
  761. const url = URL.createObjectURL(blob);
  762. const a = document.createElement('a');
  763. a.href = url;
  764. a.download = 'Vebascans_CustomBackground.json';
  765. document.body.appendChild(a);
  766. a.click();
  767. a.remove();
  768. URL.revokeObjectURL(url);
  769.  
  770. Toast.fire({ icon: 'success', title: 'Veriler JSON formatında indirildi!' });
  771. }
  772.  
  773. // İçe Aktar (JSON dosyasından)
  774. function importDataFromJson(file) {
  775. const reader = new FileReader();
  776. reader.onload = (e) => {
  777. try {
  778. const imported = JSON.parse(e.target.result);
  779.  
  780. // Dosyada hangi veriler varsa alıp localStorage'a yazalım
  781. if (imported.active) {
  782. localStorage.setItem(ACTIVE_KEY, JSON.stringify(imported.active));
  783. }
  784. if (imported.history) {
  785. localStorage.setItem(HISTORY_KEY, JSON.stringify(imported.history));
  786. }
  787. if (imported.settings) {
  788. localStorage.setItem(SETTINGS_KEY, JSON.stringify(imported.settings));
  789. }
  790.  
  791. // Yeniden uygula ve arayüzü tazele
  792. applyActiveDataToBody();
  793. refreshHistoryList();
  794. refreshActiveLabel();
  795. refreshSettingsUI();
  796.  
  797. Toast.fire({ icon: 'success', title: 'JSON verileri başarıyla içe aktarıldı!' });
  798. } catch (error) {
  799. Toast.fire({ icon: 'error', title: 'Geçersiz JSON dosyası veya okuma hatası!' });
  800. }
  801. };
  802. reader.readAsText(file);
  803. }
  804.  
  805. } // main() sonu
  806.  
  807. })(); // IIFE sonu