Custom Arka Plan Yöneticisi

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

As of 2025-01-28. See the latest version.

  1. // ==UserScript==
  2. // @name Custom Arka Plan Yöneticisi
  3. // @namespace http://Vebascans.net/
  4. // @version 2.1.1
  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ı (repeat/cover vs.)
  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. const history = getHistoryData();
  79. history.push(obj);
  80. localStorage.setItem(HISTORY_KEY, JSON.stringify(history));
  81. }
  82.  
  83. // -- Ayarlar (Tekrarlı / Tek sefer)
  84. function getSettings() {
  85. try {
  86. const str = localStorage.getItem(SETTINGS_KEY);
  87. return str ? JSON.parse(str) : {};
  88. } catch (e) {
  89. return {};
  90. }
  91. }
  92.  
  93. function setSettings(newSettings) {
  94. localStorage.setItem(SETTINGS_KEY, JSON.stringify(newSettings));
  95. }
  96.  
  97. /**************************************************************************
  98. * 2) BODY Arkaplanını Aktif Veriye (URL/Color) ve Ayarlara Göre Uygulama
  99. **************************************************************************/
  100. function applyActiveDataToBody() {
  101. const activeData = getActiveData();
  102. if (!activeData) {
  103. // Aktif bir şey yoksa istersen varsayılan temize çek
  104. document.body.style.backgroundImage = '';
  105. document.body.style.backgroundColor = '';
  106. return;
  107. }
  108.  
  109. if (activeData.type === 'url') {
  110. // Body için arkaplan resmi
  111. document.body.style.backgroundImage = `url(${activeData.value})`;
  112. document.body.style.backgroundRepeat = 'no-repeat';
  113. document.body.style.backgroundSize = 'cover';
  114. document.body.style.backgroundColor = '';
  115.  
  116. // .body-wrap için deneme
  117.  
  118. try {
  119.  
  120. const bodyWrap = document.querySelector('body.text-ui-light .body-wrap');
  121. bodyWrap.style.backgroundImage = `url(${activeData.value})`;
  122. bodyWrap.style.backgroundRepeat = 'no-repeat';
  123. bodyWrap.style.backgroundSize = 'cover';
  124. bodyWrap.style.backgroundColor = '';
  125. } catch (error) {
  126. // .body-wrap yoksa hata görmezden gel
  127. }
  128. try {
  129. const sitecontent = document.querySelector('.site-content');
  130. sitecontent.style.backgroundImage = `url(${activeData.value})`;
  131. sitecontent.style.backgroundRepeat = 'no-repeat';
  132. sitecontent.style.backgroundSize = 'cover';
  133. sitecontent.style.backgroundColor = '';
  134. } catch (error) {
  135. // .site-content yoksa hata görmezden gel
  136. }
  137. } else if (activeData.type === 'color') {
  138. // Body için arkaplan rengi
  139. document.body.style.backgroundImage = 'none';
  140. document.body.style.backgroundColor = activeData.value;
  141.  
  142. // .body-wrap için deneme
  143. try {
  144. const bodyWrap = document.querySelector('body.text-ui-light .body-wrap');
  145. bodyWrap.style.backgroundImage = 'none';
  146. bodyWrap.style.backgroundColor = activeData.value;
  147. } catch (error) {
  148. // .body-wrap yoksa hata görmezden gel
  149. }
  150.  
  151. // .site-content için deneme
  152. try {
  153. const sitecontent = document.querySelector('.site-content');
  154. sitecontent.style.backgroundImage = 'none';
  155. sitecontent.style.backgroundColor = activeData.value;
  156. } catch (error) {
  157. // .site-content yoksa hata görmezden gel
  158. }
  159. }
  160. }
  161.  
  162. /**************************************************************************
  163. * 3) MODAL Arayüzü Oluşturma
  164. **************************************************************************/
  165. let modalOverlay, modalContent;
  166.  
  167. window.addEventListener('load', () => {
  168. createModal();
  169. createToggleShortcut(); // F7 ile aç/kapa
  170. applyActiveDataToBody(); // Sayfa açıldığında kaydedilmiş aktif veriyi uygula
  171. });
  172.  
  173. // F7 ile modal aç/kapa
  174. function createToggleShortcut() {
  175. window.addEventListener('keydown', (e) => {
  176. if (e.key === 'F7') {
  177. toggleModal();
  178. }
  179. });
  180. }
  181.  
  182. function toggleModal(forceOpen) {
  183. const isHidden = (modalOverlay.style.display === 'none');
  184. if (forceOpen === true) {
  185. showModal();
  186. } else if (forceOpen === false) {
  187. hideModal();
  188. } else {
  189. if (isHidden) showModal(); else hideModal();
  190. }
  191. }
  192.  
  193. function showModal() {
  194. modalOverlay.style.display = 'block';
  195. refreshHistoryList();
  196. refreshActiveLabel();
  197. refreshSettingsUI();
  198. }
  199.  
  200. function hideModal() {
  201. modalOverlay.style.display = 'none';
  202. }
  203.  
  204. function createModal() {
  205. // (1) Overlay
  206. modalOverlay = document.createElement('div');
  207. Object.assign(modalOverlay.style, {
  208. display: 'none',
  209. position: 'fixed',
  210. top: '0',
  211. left: '0',
  212. width: '100%',
  213. height: '100%',
  214. backgroundColor: 'rgba(0,0,0,0.5)',
  215. zIndex: '99999',
  216. color: '#000'
  217. });
  218. document.body.appendChild(modalOverlay);
  219.  
  220. // (2) İçerik
  221. modalContent = document.createElement('div');
  222. Object.assign(modalContent.style, {
  223. position: 'absolute',
  224. top: '50%',
  225. left: '50%',
  226. transform: 'translate(-50%, -50%)',
  227. width: '400px',
  228. backgroundColor: '#fff',
  229. padding: '20px',
  230. borderTopLeftRadius: '15px',
  231. borderBottomRightRadius: '15px',
  232. border: '3px solid black',
  233. minHeight: '400px',
  234. fontFamily: 'Arial, sans-serif',
  235. fontSize: '14px',
  236. fontWeight: 'normal',
  237. color: '#000',
  238. });
  239. modalOverlay.appendChild(modalContent);
  240.  
  241. // (3) Logo
  242. const img = document.createElement('img');
  243. img.src = 'https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhi0QDJZNeXWcaD9lXWMN2yenYt5XGrqfPavkCFpWLe01CpSEsMn7IGpbOLqxEfjx4QUUi4wgTw0Kc7vP7FrKjPKpcaaCu1N6QRJzlZvS_Wwr2r3kA4l0-E5wl7xObsZchd8YNSxySFZATPAr2bnrkANBUrmy8Rpdexe-mxG8N6QDojEj0onaNNXF_6g-s/w800/logo.png';
  244. img.alt = 'Logo';
  245. Object.assign(img.style, {
  246. width: '130px',
  247. position: 'absolute',
  248. top: '0',
  249. right: '50%',
  250. transform: 'translate(50%, -50%)'
  251. });
  252. modalContent.appendChild(img);
  253.  
  254. // (4) Başlık
  255. const header = document.createElement('h3');
  256. header.innerHTML = '<a href=\"https://www.vebascans.net/\" style=\"color: #402870; font-weight: 500; text-decoration: none; font-family: fantasy;\">Vebascans</a> - Custom Background';
  257. header.style.margin = '0 0 10px 0';
  258. header.style.color = 'black';
  259. header.style.marginTop = '45px';
  260. modalContent.appendChild(header);
  261.  
  262. // (5) Kapat butonu
  263. const closeBtn = document.createElement('button');
  264. closeBtn.innerHTML = `
  265. <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\">
  266. <g fill=\"none\" fill-rule=\"evenodd\">
  267. <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\"/>
  268. <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\"/>
  269. </g>
  270. </svg>`;
  271. Object.assign(closeBtn.style, {
  272. position: 'absolute',
  273. top: '10px',
  274. right: '10px',
  275. border: 'none',
  276. background: 'transparent',
  277. cursor: 'pointer',
  278. color: 'black'
  279. });
  280. closeBtn.onclick = () => hideModal();
  281. modalContent.appendChild(closeBtn);
  282.  
  283. // (6) Seçim Menüsü (URL mi Renk mi)
  284. const selectDiv = document.createElement('div');
  285. Object.assign(selectDiv.style, {
  286. display: 'flex',
  287. flexDirection: 'row',
  288. gap: '5px',
  289. marginBottom: '10px'
  290. });
  291. modalContent.appendChild(selectDiv);
  292.  
  293. const selectLabel = document.createElement('label');
  294. selectLabel.textContent = 'Seçim: ';
  295. selectLabel.style.display = 'flex';
  296. selectLabel.style.alignItems = 'center';
  297. selectDiv.appendChild(selectLabel);
  298.  
  299. const selectInput = document.createElement('select');
  300. selectInput.id = 'typeSelect';
  301. selectInput.style.background ='white';
  302. selectInput.style.border ='2px solid black';
  303. selectInput.style.borderRadius ='3px';
  304. selectInput.style.color = 'black';
  305. const optUrl = new Option('URL', 'url');
  306. const optColor = new Option('Renk', 'color');
  307. selectInput.add(optUrl);
  308. selectInput.add(optColor);
  309. selectDiv.appendChild(selectInput);
  310.  
  311. // (7) URL input
  312. const urlInput = document.createElement('input');
  313. urlInput.type = 'text';
  314. urlInput.id = 'urlInput';
  315. urlInput.placeholder = 'Görsel URL giriniz...';
  316. urlInput.style.background ='transparent';
  317. urlInput.style.border ='2px solid black';
  318. urlInput.style.borderRadius ='3px';
  319. selectDiv.appendChild(urlInput);
  320.  
  321. // (8) Color input
  322. const colorInput = document.createElement('input');
  323. colorInput.type = 'color';
  324. colorInput.id = 'colorInput';
  325. colorInput.value = '#000000';
  326. colorInput.style.width = '50px';
  327. colorInput.style.height = '30px';
  328. colorInput.style.display = 'none';
  329. selectDiv.appendChild(colorInput);
  330.  
  331. // Seçim değişince hangi input görünsün?
  332. selectInput.addEventListener('change', () => {
  333. if (selectInput.value === 'url') {
  334. urlInput.style.display = 'inline-block';
  335. colorInput.style.display = 'none';
  336. } else {
  337. urlInput.style.display = 'none';
  338. colorInput.style.display = 'inline-block';
  339. }
  340. });
  341.  
  342. // (9) Aktar butonu
  343. const aktarBtn = document.createElement('button');
  344. aktarBtn.textContent = 'Aktar';
  345. aktarBtn.style.marginLeft = '5px';
  346. aktarBtn.style.padding = '5px 10px';
  347. aktarBtn.style.cursor = 'pointer';
  348. aktarBtn.style.color = 'black';
  349. aktarBtn.style.border ='2px solid black';
  350. aktarBtn.style.borderRadius ='3px';
  351. aktarBtn.style.background = 'transparent';
  352. selectDiv.appendChild(aktarBtn);
  353.  
  354. aktarBtn.onclick = () => {
  355. const currentType = selectInput.value; // 'url' | 'color'
  356. let currentValue = '';
  357. if (currentType === 'url') {
  358. currentValue = urlInput.value.trim();
  359. if (!currentValue) {
  360. Toast.fire({ icon: 'error', title: 'Lütfen bir URL girin.' });
  361. return;
  362. }
  363. } else {
  364. currentValue = colorInput.value; // #rrggbb
  365. if (!currentValue) {
  366. Toast.fire({ icon: 'error', title: 'Lütfen bir renk seçin.' });
  367. return;
  368. }
  369. }
  370.  
  371. // Yeni aktif obje
  372. const newActiveObj = { type: currentType, value: currentValue };
  373. setActiveData(newActiveObj);
  374. addToHistory(newActiveObj);
  375.  
  376. refreshHistoryList();
  377. refreshActiveLabel();
  378.  
  379. // URL tipini kullandıysa inputu temizleyelim
  380. if (currentType === 'url') {
  381. urlInput.value = '';
  382. }
  383. Toast.fire({ icon: 'success', title: 'Yeni aktif değer atandı ve body arkaplanı güncellendi!' });
  384. };
  385.  
  386. // (10) Tekrar / Tek Sefer AYARI
  387. const repeatDiv = document.createElement('div');
  388. repeatDiv.style.margin = '10px 0';
  389. repeatDiv.style.display = 'flex';
  390. repeatDiv.style.flexDirection = 'row';
  391. repeatDiv.style.gap = '10px';
  392. modalContent.appendChild(repeatDiv);
  393.  
  394. const repeatLabel = document.createElement('span');
  395. repeatLabel.textContent = 'Arkaplan Tekrarı:';
  396. repeatLabel.style.alignSelf = 'center';
  397. repeatDiv.appendChild(repeatLabel);
  398.  
  399. const labelRepeat = document.createElement('label');
  400. const radioRepeat = document.createElement('input');
  401. radioRepeat.type = 'radio';
  402. radioRepeat.name = 'bgRepeat';
  403. radioRepeat.value = 'repeat';
  404. radioRepeat.style.marginRight = '5px';
  405. labelRepeat.appendChild(radioRepeat);
  406. labelRepeat.appendChild(document.createTextNode('Tekrarlı'));
  407. repeatDiv.appendChild(labelRepeat);
  408.  
  409. const labelNoRepeat = document.createElement('label');
  410. const radioNoRepeat = document.createElement('input');
  411. radioNoRepeat.type = 'radio';
  412. radioNoRepeat.name = 'bgRepeat';
  413. radioNoRepeat.value = 'no-repeat';
  414. radioNoRepeat.style.marginRight = '5px';
  415. labelNoRepeat.appendChild(radioNoRepeat);
  416. labelNoRepeat.appendChild(document.createTextNode('Tek Sefer'));
  417. repeatDiv.appendChild(labelNoRepeat);
  418.  
  419. [radioRepeat, radioNoRepeat].forEach(radio => {
  420. radio.addEventListener('change', () => {
  421. const newVal = radio.value; // 'repeat' | 'no-repeat'
  422. const s = getSettings();
  423. s.bgRepeat = newVal;
  424. setSettings(s);
  425. applyActiveDataToBody();
  426. });
  427. });
  428.  
  429. // (11) Aktif Veriyi Sil
  430. const removeActiveBtn = document.createElement('button');
  431. removeActiveBtn.textContent = 'Aktif Veriyi Sil';
  432. removeActiveBtn.style.marginBottom = '10px';
  433. removeActiveBtn.style.padding = '5px 10px';
  434. removeActiveBtn.style.cursor = 'pointer';
  435. removeActiveBtn.style.color = 'black';
  436. removeActiveBtn.style.background = 'transparent';
  437. removeActiveBtn.style.border ='2px solid black';
  438. removeActiveBtn.style.borderRadius ='3px';
  439. modalContent.appendChild(removeActiveBtn);
  440.  
  441. removeActiveBtn.onclick = () => {
  442. removeActiveData();
  443. refreshHistoryList();
  444. refreshActiveLabel();
  445. Toast.fire({ icon: 'info', title: 'Aktif veri silindi. Arkaplan temizlendi.' });
  446. };
  447.  
  448. // (12) Şu anda aktif veriyi gösteren label
  449. const activeDiv = document.createElement('div');
  450. activeDiv.id = 'activeDiv';
  451. activeDiv.style.marginTop = '10px';
  452. modalContent.appendChild(activeDiv);
  453.  
  454. // (13) Geçmiş Başlık
  455. const historyTitle = document.createElement('h4');
  456. historyTitle.textContent = 'Geçmiş';
  457. historyTitle.style.margin = '10px 0 5px 0';
  458. modalContent.appendChild(historyTitle);
  459.  
  460. // (14) Geçmiş Container
  461. const historyContainer = document.createElement('div');
  462. historyContainer.id = 'historyContainer';
  463. historyContainer.style.maxHeight = '200px';
  464. historyContainer.style.overflowY = 'auto';
  465. historyContainer.style.border = '1px solid #ccc';
  466. historyContainer.style.padding = '5px';
  467. modalContent.appendChild(historyContainer);
  468. }
  469.  
  470. /**************************************************************************
  471. * 4) Geçmiş & Aktif Listeyi Güncelleme
  472. **************************************************************************/
  473. function refreshHistoryList() {
  474. const historyContainer = document.getElementById('historyContainer');
  475. if (!historyContainer) return;
  476.  
  477. historyContainer.innerHTML = '';
  478.  
  479. const historyData = getHistoryData();
  480. const activeData = getActiveData(); // {type:'...', value:'...'}
  481.  
  482. historyData.forEach((item) => {
  483. const row = document.createElement('div');
  484. row.style.display = 'flex';
  485. row.style.alignItems = 'center';
  486. row.style.marginBottom = '8px';
  487. row.style.cursor = 'pointer';
  488.  
  489. // URL ise küçük görsel
  490. if (item.type === 'url') {
  491. const imgThumb = document.createElement('img');
  492. imgThumb.src = item.value;
  493. imgThumb.alt = 'Görsel';
  494. imgThumb.style.width = '30px';
  495. imgThumb.style.height = '30px';
  496. imgThumb.style.objectFit = 'cover';
  497. imgThumb.style.marginRight = '8px';
  498. row.appendChild(imgThumb);
  499.  
  500. const label = document.createElement('span');
  501. label.textContent = 'URL';
  502. row.appendChild(label);
  503. }
  504. // Renk ise kutu
  505. else if (item.type === 'color') {
  506. const colorBox = document.createElement('span');
  507. colorBox.style.display = 'inline-block';
  508. colorBox.style.width = '30px';
  509. colorBox.style.height = '30px';
  510. colorBox.style.backgroundColor = item.value;
  511. colorBox.style.marginRight = '8px';
  512. colorBox.style.border = '1px solid #000';
  513. row.appendChild(colorBox);
  514.  
  515. const label = document.createElement('span');
  516. label.textContent = 'Renk';
  517. row.appendChild(label);
  518. }
  519.  
  520. // Aktif mi?
  521. if (activeData && activeData.type === item.type && activeData.value === item.value) {
  522. const activeSpan = document.createElement('span');
  523. activeSpan.textContent = ' (Şu anda aktif)';
  524. activeSpan.style.color = 'green';
  525. activeSpan.style.marginLeft = '5px';
  526. row.appendChild(activeSpan);
  527. }
  528.  
  529. // Tıklayınca bu itemi aktif yap
  530. row.addEventListener('click', () => {
  531. setActiveData(item);
  532. refreshHistoryList();
  533. refreshActiveLabel();
  534. Toast.fire({ icon: 'success', title: 'Aktif değer güncellendi!' });
  535. });
  536.  
  537. historyContainer.appendChild(row);
  538. });
  539. }
  540.  
  541. function refreshActiveLabel() {
  542. const activeDiv = document.getElementById('activeDiv');
  543. if (!activeDiv) return;
  544.  
  545. const activeData = getActiveData();
  546. if (!activeData) {
  547. activeDiv.textContent = 'Şu anda aktif bir değer yok.';
  548. } else {
  549. if (activeData.type === 'url') {
  550. activeDiv.innerHTML = `
  551. Aktif: URL
  552. <img src=\"${activeData.value}\"
  553. alt=\"Aktif Görsel\"
  554. style=\"width: 100px; height: auto; object-fit: cover; margin-left:5px;\"/>
  555. `;
  556. } else {
  557. activeDiv.innerHTML = `
  558. Aktif: Renk
  559. <span style=\"display:inline-block; width:20px; height:20px;
  560. background-color:${activeData.value};
  561. border:1px solid #000; vertical-align:middle;\">
  562. </span>
  563. ${activeData.value}
  564. `;
  565. }
  566. }
  567. }
  568.  
  569. /**************************************************************************
  570. * 5) Arkaplan Ayarı (Tekrar / Tek Sefer) Radyo Butonlarını Güncelleme
  571. **************************************************************************/
  572. function refreshSettingsUI() {
  573. const settings = getSettings();
  574. const bgRepeat = settings.bgRepeat || 'no-repeat'; // Varsayılan no-repeat
  575. const radios = document.getElementsByName('bgRepeat');
  576. radios.forEach(radio => {
  577. radio.checked = (radio.value === bgRepeat);
  578. });
  579. }
  580.  
  581. } // main() sonu
  582.  
  583. })(); // IIFE sonu