rendero-info

-

Від 20.10.2021. Дивіться остання версія.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(У мене вже є менеджер скриптів, дайте мені встановити його!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name        rendero-info
// @namespace   what.ever
// @match       https://www.renderosity.com/rr/mod/*
// @match       https://www.renderotica.com/store/sku/*
// @grant       GM_xmlhttpRequest
// @version     1.0
// @author      -
// @description -
// ==/UserScript==

const W = 380;
const H = 494;

let info = null;
// get info
try {
  if(location.host.includes('renderosity')){
    info = {
      store: 'Renderosity',
      title: document.querySelector('.title-header').innerHTML.split('<small>')[0].trim(),
      productID: document.querySelector('.mainImage').href.replace(/.+?product_(\d+).+/, '$1'),
      venderName: []
    }
    for(let a of document.querySelectorAll('.title-header > small > a')){
      if(a.innerText.length > 0){
        info.venderName.push(a.innerText);
      }
    }
  }else if(location.host.includes('renderotica')){
    info = {
      store: 'Renderotica',
      title: document.querySelector('.product-info > h1').innerText.trim(),
      productID: document.querySelector('.product-info > p > span').innerText.trim(),
      venderName: []
    }
    for(let a of document.querySelectorAll('.product-info > p > a')){
      info.venderName.push(a.innerText);
    }

    // wrap cover with lightbox
    const pImg = document.querySelector('.primary-image > img');
    const a = document.createElement('a');
    a.href = pImg.src;
    a.dataset.lightbox = 'image';
    pImg.parentNode.append(a);
    a.append(pImg);
  }
} catch (error) {
  console.error(`can't get product info\n`, error);
  return;
}

// add switcher for info panel
addBtn('📃', switchInfoPanel);
addBtn('✂', clipImage);

function switchInfoPanel(){
  const infoPanel = document.querySelector('#ro-info-panel') || createInfoPanel();
  if(infoPanel.style.display === 'block'){
    infoPanel.style.display = 'none';
  }else{
    infoPanel.style.display = 'block';
  }
}

function createInfoPanel(){
  const infoPanel = document.createElement('div');
  infoPanel.id = 'ro-info-panel';
  infoPanel.innerHTML = `
    <div class="ro-title">
      Product Name:
      <input type="text" class="value">
      <button class="ro-copy">copy</button>
    </div>
    <div class="ro-vender">
      Vender Name:
      <input type="text" class="value">
      <button class="ro-copy">copy</button>
    </div>
    <div class="ro-store">
      Store Name:
      <input type="text" class="value">
      <button class="ro-copy">copy</button>
    </div>
    <div class="ro-id">
      Product ID:
      <input type="text" class="value">
      <button class="ro-copy">copy</button>
    </div>
  `;

  // add style
  addStyle(`
    #ro-info-panel{
      position: fixed;
      top: 10rem;
      right: 3rem;
      z-index: 1;
      background-color: #fff6;
      padding: 1rem;
      border-radius: .5rem;
      text-align: right;
    }
    #ro-info-panel > div{
      margin: 5px;
    }
    .ro-copy{
      margin-left: 5px;
      cursor: pointer;
    }
  `);

  
  // fill info panel
  infoPanel.querySelector('.ro-title > .value').value = info.title;
  infoPanel.querySelector('.ro-vender > .value').value = info.venderName.join(',');
  infoPanel.querySelector('.ro-store > .value').value = info.store;
  infoPanel.querySelector('.ro-id > .value').value = info.productID;
  
  // bind listener
  infoPanel.addEventListener('click', ev=>{
    const t = ev.target;
    if(t.classList.contains('ro-copy')){
      t.previousElementSibling.select();
      if(document.execCommand('copy')) console.log('copied.');
    }
  })

  // show node
  document.body.append(infoPanel);

  return infoPanel;
}

function clipImage(){
  const imgBox = document.querySelector('#lightbox');
  const img = imgBox.querySelector('img');
  if(imgBox.style.display !== 'block'){
    alert('please select an image');
    return;
  }

  // get select box
  let selectBox = document.querySelector('#ro-select-box');

  if(!selectBox){
    createSelectBox();
  }else if(selectBox.style.display === 'none'){
    selectBox.style.display = 'block';
  }else{
    clip();
    selectBox.style.display = 'none';
  }

  function createSelectBox(){
    let selectBox = document.createElement('div');
    selectBox.id = 'ro-select-box';
    // add style
    addStyle(`
      #ro-select-box{
        position: absolute;
        z-index: 99;
        cursor: move;
        border: 2px dashed #fff;
      }
    `);
    selectBox.style.width = W + 'px';
    selectBox.style.height = H + 'px';
    selectBox.style.top = '0px';
    selectBox.style.left = '0px';
    imgBox.querySelector('img').after(selectBox);
    selectBox.addEventListener('mousedown', ev=>{
      const t = ev.target;
      if(t.id !== 'ro-select-box') return;
      selectBox.addEventListener('mousemove', handleDragBox);
    });
    document.body.addEventListener('mouseup', ev=>{
      selectBox.removeEventListener('mousemove', handleDragBox);
    });
    selectBox.addEventListener('contextmenu', ev=>{
      ev.preventDefault();
      selectBox.style.display = 'none';
    });
  
    // create resize corner
    const resizeCorner = document.createElement('div');
    resizeCorner.id = 'resize-corner';
    addStyle(`
      #resize-corner{
        width: 20px;
        height: 20px;
        background: red;
        position: absolute;
        bottom: -5px;
        right: -5px;
        cursor: se-resize;
        border-radius: 10px;
      }
    `);
    resizeCorner.addEventListener('mousedown', ev=>{
      document.body.addEventListener('mousemove', handleResize);
    });
    document.body.addEventListener('mouseup', ev=>{
      document.body.removeEventListener('mousemove', handleResize);
    });
    selectBox.append(resizeCorner);
  
    function handleDragBox(ev){
      // console.log('dragging');
      const t = ev.target;
      const x0 = parseFloat(t.style.left.replace('px', ''));
      const y0 = parseFloat(t.style.top.replace('px', ''));
      t.style.left = x0 + ev.movementX + 'px';
      t.style.top = y0 + ev.movementY + 'px';
    }
  
    function handleResize(ev){
      // console.log('resizing');
      const t = ev.target;
      const x = ev.movementX;
      const y = x / W * H;
      const w0 = parseFloat(selectBox.style.width.replace('px', ''));
      const h0 = parseFloat(selectBox.style.height.replace('px', ''));
      console.log(x,y,w0,h0);
      selectBox.style.width = w0 + x + 'px';
      selectBox.style.height = h0 + y + 'px';
    }
  }

  function clip(ev){
    // get img
    // can't use original img, blocked by CORS
    GM_xmlhttpRequest({
      url: img.src,
      method: 'GET',
      responseType: 'blob',
      onerror: console.error,
      onload: result=>{
        createImageBitmap(result.response).then(
          bitmap=>{
            const ratio = bitmap.height / img.parentElement.clientHeight;
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');
            const sx = ratio * parseFloat(selectBox.style.left.replace('px', ''));
            const sy = ratio * parseFloat(selectBox.style.top.replace('px', ''));
            const sw = ratio * parseFloat(selectBox.style.width.replace('px', ''));
            const sh = ratio * parseFloat(selectBox.style.height.replace('px', ''));
            canvas.width = W;
            canvas.height = H;
            ctx.drawImage(bitmap, sx, sy, sw, sh, 0, 0, W, H);
            ctx.imageSmoothingQuality = 'high';
            // ctx.imageSmoothingEnabled = false;
            const a = document.createElement('a');
            a.download = info.title + '.jpg';
            a.href = canvas.toDataURL('image/jpeg', 0.9);
            a.click();
          }
        );
      }
    });
  }
}

function addStyle(css){
  const elm = document.createElement('style');
  elm.textContent = css;
  document.head.append(elm);
  return elm;
}

function addBtn(icon, callback){
  let ctn = document.body.querySelector('#my-btn-container');
  if(!ctn){
    ctn = document.createElement('div');
    ctn.id = 'my-btn-container';
    addStyle(`
      #my-btn-container{
        position: fixed;
        bottom: 80px;
        right: 80px;
        z-index: 20000;
      }
      #my-btn-container > div{
        background: #fff8;
        border-radius: 10px;
        border: 2px solid #0008;
        padding: 5px;
        margin: 5px 0;
        font-size: 20px;
        cursor: pointer;
        user-select: none;
        text-align: center;
      }
    `);
    document.body.append(ctn);
  }

  const btn = document.createElement('div');
  btn.innerText = icon;
  btn.addEventListener('click', callback);
  ctn.append(btn);

  return btn;
}