Code viewer for World: Text Extraction in Service...


// SLIDESHOW modified from: https://www.w3schools.com/howto/howto_js_slideshow.asp
// Postman for formatting requests and guaranteeing keys work before translating request into JS: https://www.postman.com/
// OpenAI API docs for formatting chatgpt requests: https://platform.openai.com/docs/guides/
// Google Cloud docs for formatting Google requests: https://cloud.google.com/docs
// Microsoft computer vision API docs consulted: https://learn.microsoft.com/en-us/azure/ai-services/computer-vision/
// Microsoft Azure AI api docs consulted: https://learn.microsoft.com/en-us/azure/ai-services/translator/
// CSS based on the way CSS is organised in Darius Beril's language quizzer: https://ancientbrain.com/world.php?world=2000799532
// "Set API Key" buttons based on design in Darisu Beril's language quizzer: https://ancientbrain.com/world.php?world=2000799532
// DeepL API docs consulted: https://developers.deepl.com/docs

// Cloned by Shahin de Faoite Houshidari on 25 Oct 2024 from World "Language Translator and Reader" by Darius Beril 
// Please leave this clone trail here.
 

// Cloned by Darius Beril on 7 Dec 2023 from World "Language Quizzer" by Darius Beril 
// Please leave this clone trail here.

// Cloned by Darius Beril on 6 Dec 2023 from World "Chat with GPT model" by Starter user 
// Please leave this clone trail here.
 
// talk to OpenAI GPT model (ChatGPT)
// adapted from:
//  https://platform.openai.com/docs/api-reference/making-requests

// the OpenAI model we are going to talk to 



// MH edit

var microsoft_translate_key = ""
var microsoft_vision_key    = ""
var google_key              = ""
var chatgpt_key             = ""
var chatgpt_pid             = ""

var d_path      = null
var proxy_key   = ""
var apikey      = ""    // not used! 



 
const W = 1024
const H = 768
const N_OF_SLIDES = 53;
const google_path = "https://vision.googleapis.com/v1/images:annotate" // ?key={key}
const google_t_path = "https://translation.googleapis.com/language/translate/v2" // ?key={key}
const m_path = "https://ancientbrain.cognitiveservices.azure.com/computervision/imageanalysis:analyze?api-version=2023-04-01-preview"
const m_t_path = "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&from=ja&to=en";
const chatgpt_path = 'https://api.openai.com/v1/chat/completions';


var abs_index = 0;
var slide_number = 0;
var slide_strings = generateSlides(N_OF_SLIDES);

// default body is margin 0 and padding 0 
// give it more whitespace:

  $('body').css( "margin", "20px" );
  $('body').css( "padding", "20px" );




 
document.write ( `
<div class="body">
<div class="container">
<h1> Using Multiple AI API’s to Extract and Translate Text </h1>
<p><em>AI’s Applicability in Bolstering Confidence Abroad
Using Japanese Signs as Case-Studies 
</em></p>

<br>
Enter your API key below
<br>



<div class="keys">

<br>
 <!-- Buttons from Darius Beril's Language Quizzer: https://ancientbrain.com/world.php?world=2000799532  -->
Enter Google API key: 
	<input    style='width:25vw;'    maxlength='2000'   NAME="apikey"    id="gk"       VALUE='' >  
	<button onclick="setGoogle()" class=ab-normbutton >Set API key</button>
<br>

Enter Microsoft COMPUTER VISION API key: 
	<input    style='width:25vw;'    maxlength='2000'   NAME="apikey"    id="mvk"       VALUE='' >  
	<button onclick="setMicrosoftVision()" class=ab-normbutton >Set API key</button>
<br>
Enter Microsoft TRANSLATE API key: 
	<input    style='width:25vw;'    maxlength='2000'   NAME="apikey"    id="mtk"       VALUE='' >  
	<button onclick="setMicrosoftTranslate()" class=ab-normbutton >Set API key</button>
<br>
<br>
Enter OpenAI ChatGPT API key: 
	<input    style='width:25vw;'    maxlength='2000'   NAME="apikey"    id="cgptk"       VALUE='' >  
	<button onclick="setChatGPTKey()" class=ab-normbutton >Set API key</button>
<br>

<br>
Enter OpenAI ChatGPT Project ID: 
	<input    style='width:25vw;'    maxlength='2000'   NAME="apikey"    id="cgptpid"       VALUE='' >  
	<button onclick="setChatGPTProjectId()" class=ab-normbutton >Set API key</button>
<br>

To test the App on a Custom Image (i.e. not from the slideshow), enter a URL pointing toward an image (for example, an Ancient Brain Upload): 
	<input    style='width:25vw;'    maxlength='2000'   NAME="custom_img_url"    id="ciu"       VALUE='' >  
	<button onclick='setCustomUrl()' class=ab-normbutton >Set URL</button>
<br>
</div>

<br><br>




<h1> How to use: </h1>
<strong>

<ol>
<li> Select an image from the slideshow/enter a <em>custom url pointing to an image</em></li>
<li> Hit "Transpose" to extract text. <em> (Skip this step if entering a custom url, when hitting "set", the translation occurs automatically.)</em> </li>
<li> Hit "Translate" to translate the extracted text. <em>Note: if DeepL is activated, DeepL shall also translate the text. See the DeepL section below.</em></li>
<li> Hit ChatGPT Assess to translate Google and Microsoft's <em> two text extractions </em> and <em> each of their translations of both their transposition, AND the others </em>.</li>
</ol>
</strong>

<p><em>Once an image has been transposed, hit translate to translate the transposed text.</em></p>

<div class="slideshow-container">
${slide_strings}
 <!-- Slideshow modified from: https://www.w3schools.com/howto/howto_js_slideshow.asp -->

  <!-- Next and previous buttons -->
  <a class="prev" onclick="plusSlides(-1)">&#10094;</a>
  <a class="next" onclick="plusSlides(1)">&#10095;</a>
</div>
<br>


<div style="text-align:center">
  <span class="dot" onclick="currentSlide(1)"></span>
  <span class="dot" onclick="currentSlide(2)"></span>
  <span class="dot" onclick="currentSlide(3)"></span>
</div> 


<br>
<br>
<br>
<button onclick='classify();'  class=ab-normbutton >Transpose Slide</button>
<button onclick='translateText();'  class=ab-normbutton >Translate Current Extracted Text</button>
<button onclick='chatgptButton();'  class=ab-normbutton >ChatGPT Assess</button>
<div class="main-container">
<div class="transpositions">
<div class="wordbox">
<p id="g_ocr">Waiting on Google's transposition</p>
<em><hp id="g_confidence"></p></em>
<br>
</div>
<br>
<div class="wordbox">
<p id="m_ocr">Waiting on Microsoft's transposition</p>
<em><p id="m_confidence"></p></em>
</div>
<br>
<div class="wordbox">
<p id="c_ocr">Waiting on ChatGPT's transposition & assessment</p>
<em><p id="c_confidence"></p></em>
</div>
<br>
</div>
<br>
<br>
<div class="translations">
<div class="wordbox">
<h2>Translating Google's Transposition:</h2>
<h4>Google's Translation:</h4>
<br>
<p id="g_translation1">Waiting on Google's translation</p>
<br>
<br>
<h4>Microsoft's Translation:</h4>
<p id="m_translation1">Waiting on Microsoft's translation</p>
</div>
<br>

<div class="wordbox">
<h2>Translating Microsoft's Transposition:</h2>
<h4>Google's Translation:</h4>
<p id="g_translation2">Waiting on Google's translation</p>
<br>
<br>
<h4>Microsoft's Translation:</h4>
<p id="m_translation2">Waiting on Microsoft's translation</p>
</div>
<br>
<br>
<br>
<div class="wordbox">
<h1>DeepL:</h1>
<h4>DeepL Translation:</h4>
<p id="d_translation">DeepL will translate Google's reading and place it here.</p>
<br>
<hr>
<br>
<p>DeepL translation happens via <em>Proxy API</em>. The link to the GitHub repo containing the Django code to set up and run a local instance of this proxy API is: <br><br><strong>https://github.com/Shahinhou/public_deepL_proxy</strong></p><br>
<p><em>If you are viewing this page between 15/11/2024 and 1/2/2025, a proxy API is being hosted at:</em><br><br> <strong>https://privatedeeplproxy-production.up.railway.app/proxy/</strong></p><br>
<br>
<p>Enter the URL for your proxy API to make a verifying request to DeepL:</p>

	<input    style='width:25vw;'    maxlength='2000'   NAME="deeplproxy"    id="dlp"       VALUE='http://127.0.0.1:8000/proxy/' >  
	<button onclick='setDeepLProxy()' class=ab-normbutton >Set URL</button>
	<p><strong>Please note that if you are hosting your own Proxy API, you must have your own API Key. Instructions to set up the local proxy are at the link above.</strong></p>
	<p><em>Example: "http:127.0.0.1:8000/proxy/"</em</p>
	<p>DeepL Proxy Key: </p>
		<input    style='width:25vw;'    maxlength='2000'   NAME="deeplproxykey"    id="dlpk"       VALUE='' >  
	<button onclick='setDeepLProxyKey()' class=ab-normbutton >Set Proxy Key</button>
	<p><em>This is different from the DeepL key. This is specifically for the proxy. If it is later than 1/2/2025, instructions for setting up your proxy with your own DeepL key and custom Secret Key are at the Git link above.</em></p>

<br>

</div>
</div>
</div>

<br>
<div class="gptbox">
<h4>ChatGPT assessing Google's Transposition:</h4>
<p id="google_assessment">Waiting on ChatGPT's assessment and comparison of both translations of Google's transposition</p>
</div>
<br>
<br>
<br>
<div class="gptbox">
<h4>ChatGPT assessing Microsoft's Transposition:</h4>
<p id="microsoft_assessment">Waiting on ChatGPT's assessment and comparison of both translations of Microsoft's transposition</p>
</div>

<pre>

</pre>

</div>

<pre>

</pre>
</div>

</div>

` );


// 


function getCurrent(){
    console.log(slideIndex);
}

/* Setters for keys etc - logic modified from Darius Beril's Language Quizzer: https://ancientbrain.com/world.php?world=2000799532 */

function setCustomUrl(){
	var  url =  jQuery("input#ciu").val();
	url = url.trim();
	console.log(url)
	classify(url);
}
function setDeepLProxy(){
    
	var  url =  jQuery("input#dlp").val();
	url = url.trim();
	console.log(url)
	d_path = (url);
}

function setDeepLProxyKey(){
    
	proxy_key =  jQuery("input#dlpk").val().trim();
}

function setMicrosoftTranslate(){
	microsoft_translate_key =  jQuery("input#mtk").val().trim();
}

function setMicrosoftVision(){
	microsoft_vision_key =  jQuery("input#mvk").val().trim();
}

function setGoogle(){
	google_key =  jQuery("input#gk").val().trim();
}

function setChatGPTKey(){
	chatgpt_key =  jQuery("input#cgptk").val().trim();
}

function setChatGPTProjectId(){
	chatgpt_pid =  jQuery("input#cgptpid").val().trim();
}


/* ChatGPT button */

function chatgptButton(custom){
    
    if (custom == null){
        imgUrl = document.getElementById(slideIndex-1).src; 
    }
    else {
        
        imgUrl = custom;
    }
    
    var  url =  jQuery("input#ciu").val();
	url = url.trim();
	console.log(url)
	
    
    let ckey = chatgpt_key 
    let pid = chatgpt_pid

   
    let ot1 = document.getElementById("g_ocr").textContent
    let tt1_1 = document.getElementById("g_translation1").textContent
    let tt1_2 = document.getElementById("m_translation1").textContent
    
    let ot2 = document.getElementById("m_ocr").textContent
    let tt2_1 = document.getElementById("g_translation2").textContent
    let tt2_2 = document.getElementById("m_translation2").textContent

    
    chatgptTranspose(ckey, imgUrl, document.getElementById('g_ocr').textContent, document.getElementById('m_ocr').textContent, pid);
    
    chatgptAssessTranslation(ckey, ot1, tt1_1, tt1_2, "google", pid);
    chatgptAssessTranslation(ckey, ot2, tt2_1, tt2_2, "microsoft", pid);

    
}


async function chatgptAssessTranslation(ckey, originalText, translatedText1, translatedText2, target, project_id) {
    console.log('click');
    const payload = {
        model: "gpt-4o-mini", 
        messages: [
            { 
                role: "system", 
                content: "You are an expert in Japanese and English. Please assess the accuracy and quality of two translations of a Japanese text to English." 
            },
            { 
                role: "user", 
                content: `Here is the original Japanese text:\n\n${originalText}\n\nHere is Google's English translation:\n\n${translatedText1}\n\nHere is the Microsoft's English translation:\n\n${translatedText2}\n\nPlease evaluate the translations for accuracy, fluency, and faithfulness to the original meaning, and compare the two. Please give an indication as to which is superior.`  
            }
        ],
        temperature: 0.7, 
    };

    try {
        const response = await fetch(chatgpt_path, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "Authorization": `Bearer ${ckey}`,
                "OpenAI-Organization": "org-9GqX5v167YXP8VuHb4fPUi3a",
                "OpenAI-Project": `${project_id}`
            },
            body: JSON.stringify(payload)
        });

        if (!response.ok) {
            throw new Error(`HTTP error, status: ${response.status}`);
        }

        const data = await response.json();
        console.log("Translation Assessment:", data.choices[0].message.content);
        console.log(data);
        document.getElementById(`${target}_assessment`).innerHTML = `${data.choices[0].message.content}`;
        
    } catch (error) {
        console.error("Error making API request:", error);
    }
}




/* Text Extraction */

function classify(custom=null) {
	
    let gkey = google_key 
    let mkey = microsoft_vision_key 


    let imgUrl = "";
    
    if (custom == null){
        imgUrl = document.getElementById(slideIndex-1).src; 
    }
    else {
        
        imgUrl = custom;
    }
    
    googleTranspose(gkey, imgUrl);
    microsoftTranspose(mkey, imgUrl);
    

}

async function chatgptTranspose(ckey, imgUrl, t1, t2, project_id){
    
    // Built using OpenAI API docs: https://platform.openai.com/docs/guides/vision#quickstart
    console.log('click');
    const payload = {
        model: "gpt-4o-mini", 
        messages: [
            { 
                role: "user", 
                content: [ 
                
                {
                    type:"text",
                    text: "You are an expert in Japanese and English. Please read the text from an image given a URL, and compare two other readings to assess which reading is superior." 
                },
                
                {
                    type: "image_url",
                    image_url: {
                        "url":`${imgUrl}`
                    }
                },
                
                {
                    type:"text",
                    text: `Here is the Google reading:${t1}`
                },
                
                {
                    type:"text",
                    text: `Here is the Microsoft reading:${t2}`
                }
                ]
        }
        ],
        temperature: 0.7, 
    };

    try {
        const response = await fetch(chatgpt_path, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "Authorization": `Bearer ${ckey}`,
                "OpenAI-Organization": "org-9GqX5v167YXP8VuHb4fPUi3a",
                "OpenAI-Project": `${project_id}`
            },
            body: JSON.stringify(payload)
        });
        

        if (!response.ok) {
            throw new Error(`HTTP error, status: ${response.status}`);
        }

        const data = await response.json();
        console.log("Translation Assessment:", data.choices[0].message.content);
        console.log(data);
        document.getElementById(`c_ocr`).innerHTML = `${data.choices[0].message.content}`;
        
    } catch (error) {
        console.error("Error making API request:", error);
    }
}




function googleTranspose(gkey, imgUrl){
        
        // Used google cloud docs: https://cloud.google.com/docs
        fetch(`${google_path}?key=${gkey}`, {
        
        method:"POST",
        header: {
            "Content-type":"application/json"
        },
        body: JSON.stringify(
            {
             "requests":[
              {
                  "image":{
                      
                      
                      "source": {
                         "imageUri": `${imgUrl}`
                      }
                      
                      
                  },
                  "features":[
                   {
                   "type":"DOCUMENT_TEXT_DETECTION",
                   }
                   ],
                   "imageContext": {
                        //"languageHints": ["en-t-i0-handwrit"]
                        "languageHints": ["ja"]
                    }
               }
            ]
            }
        )}
        
    )
    .then(response => response.json())
    .then(response => {
        if (response.responses.length > 0){
            document.getElementById("g_ocr").innerHTML = response.responses[0].fullTextAnnotation.text
            document.getElementById("g_confidence").innerHTML = `Google's confidence: ${response.responses[0].fullTextAnnotation.pages[0].confidence}`
            console.log(response.responses[0].fullTextAnnotation.text);
            console.log(response)
            return response;
        }
    })
}


function microsoftTranspose(mkey, imgUrl){
    
    // Used Postman - modified postman request until it worked, then generated "fetch javascript" code from postman request. Then heavily modified to work in this program.
        
    const myHeaders = new Headers();
	myHeaders.append("Ocp-Apim-Subscription-Key", `${mkey}`);
	myHeaders.append("Content-Type", "application/json");

	const raw = JSON.stringify({
	  "url": `${imgUrl}` 
	});

	const requestOptions = {
	  method: "POST",
	  headers: myHeaders,
	  body: raw,
	  redirect: "follow"
	};

	fetch("https://ancientbrain.cognitiveservices.azure.com/computervision/imageanalysis:analyze?api-version=2023-04-01-preview&features=read", requestOptions)
	  .then((response) => response.json())
	  .then((result) => { 
	      document.getElementById("m_ocr").innerHTML = result.readResult.content;
	      let conf = 0.0;
	      let i = 0;
	      for (d in result.readResult.pages[0].words){
	          console.log(d)
	          conf += result.readResult.pages[0].words[d].confidence;
	          i+=1;
	      }
	      conf = conf / i
	      console.log(conf);
	      console.log(result);
	      document.getElementById("m_confidence").innerHTML = `Microsoft's confidence: ${conf}`;
	      
	  })
	  .catch((error) => console.error(error));
}

function translateText() {
    let gkey = google_key 
    let mkey = microsoft_translate_key 
    
    let imgUrl = document.getElementById(abs_index).src;
    let ot1 = document.getElementById("g_ocr").textContent;
    let ot2 = document.getElementById("m_ocr").textContent;
    
    googleTranslate(gkey,1, ot1);
    microsoftTranslate(mkey,1, ot1);
    
    googleTranslate(gkey,2, ot2);
    microsoftTranslate(mkey,2, ot2);
    
    if (d_path != null){
        deepLTranslate();
    }
}


function googleTranslate(gkey,target,ot){
        
        // Used google cloud docs: https://cloud.google.com/docs
        
        fetch(`${google_t_path}?key=${gkey}`, {
        
        method:"POST",
        header: {
            "Content-type":"application/json"
        },
        body: JSON.stringify(
            {
                q: ot, 
                source: "ja",
                target: "en",
                format: "text"
            }
        )}
        
    )
    .then(response => response.json())
    .then(response => {
        if (response.data.translations.length > 0){
            document.getElementById(`g_translation${target}`).innerHTML = response.data.translations[0].translatedText;
            console.log("google:")
            console.log(response)
            return response;
        }
    })

}

function microsoftTranslate(m_key, target, ot, m_key_region="eastus"){
    
    // Used Postman - modified postman request until it worked, then generated "fetch javascript" code from postman request. Then heavily modified to work in this program.
        
    const myHeaders = new Headers();
    myHeaders.append("Content-Type", "application/json");
    myHeaders.append("Ocp-Apim-Subscription-Key", `${m_key}`);
    myHeaders.append("Ocp-Apim-Subscription-Region", `${m_key_region}`);

    const raw = JSON.stringify([
       {
        "text": ot //`${document.getElementById("m_ocr").textContent}`
      }
    ]);

    const requestOptions = {
      method: "POST",
      headers: myHeaders,
      body: raw,
      redirect: "follow"
    };

    fetch(`${m_t_path}`, requestOptions)
      .then((response) => response.json())
      .then((response) => {
        if (response[0].translations.length > 0){
            document.getElementById(`m_translation${target}`).innerHTML = response[0].translations[0].text;
            console.log("microsoft:")
            console.log(response)
            return response;
            
        }
      })
      .catch((error) => console.error(error));
}

function deepLTranslate(){
    
    // Used Postman - modified postman request until it worked, then generated "fetch javascript" code from postman request. Then heavily modified to work in this program.
        
    const dlHeaders = new Headers();
    dlHeaders.append("Content-Type", "application/json");

    console.log(proxy_key)
    const dlraw = JSON.stringify(
        {
        
        text: `${document.getElementById("g_ocr").textContent}`,
        target_lang: "EN",
        source_lang: "JA",
        key: `${proxy_key}`
        
        }
    )

    const dlrequestOptions = {
    method: "POST",
    headers: dlHeaders,
    body: dlraw,
    redirect: "follow"
    
    };

    fetch(`${d_path}`, dlrequestOptions)
      .then((response) => response.json())
      .then((result) => {
            console.log(result);
            document.getElementById("d_translation").innerHTML = result.translations[0].text;
            
            return result;
        })
      .catch((error) => console.error(error));
}


/* W3 Schools Slides modified from: https://www.w3schools.com/howto/howto_js_slideshow.asp */

let slideIndex = 1;
abs_index = 1;
showSlides(slideIndex);

// Next/previous controls
function plusSlides(n) {
  let length = document.getElementsByClassName("mySlides").length
  
  slide_number = (slide_number + n) % length; 
  abs_index = Math.abs(slide_number);
  console.log(abs_index);
  showSlides(slideIndex+n);
  
}

// Thumbnail image controls
function currentSlide(n) {
  showSlides(slideIndex = n);
  abs_index = n;
  slide_number = n;
}

function showSlides(n) {
  let i;
  let slides = document.getElementsByClassName("mySlides");
  let dots = document.getElementsByClassName("dot");
  slideIndex = n;
  if (n > slides.length) {slideIndex = 1}
  if (n < 1) {slideIndex = slides.length}
  
  for (i = 0; i < slides.length; i++) {
    slides[i].style.display = "none";
  }
  //for (i = 0; i < dots.length; i++) {
    //dots[i].className = dots[i].className.replace(" active", "");
  //}
  slides[slideIndex-1].style.display = "block";
  //dots[slideIndex-1].className += " active";
} 

/* End of w3schools modified content */

function generateSlides(length) {
    
    let index = 0;
    let slide_strings = "";
    
    while (index < length){
    
    slide_strings = slide_strings.concat(`<div class="mySlides fade">
        <div class="numbertext">${index} / ${length}</div>
        <img id="${index}" src="https://ancientbrain.com/uploads/shahindfh/${index}.jpg"  style="width:100%">
        <div class="text">Demo image ${index}</div>
     </div>`);
     //console.log(slide_strings);
     
     index+=1;
     
    }
    return slide_strings;
}

/* CSS styling method based on Darius Beril's Language Quizzer's CSS setup: https://ancientbrain.com/world.php?world=2000799532 */

$('button').css("padding", "10px");
$('*').css("font-family", "Georgia");
$('*').css("font-weight", "light");
$('img').css("padding", "10px");
$('.body').css("background-color", "#a6daff");
$('.body').css("padding", "20px");
$('.container').css("background-color", "#FAF9F6");
$('.container').css("padding", "20px");
$('.container').css("margin", "auto");
$('.container').css("max-width", "85%");

$('.slideshow-container').css("max-width", "500px");
$('.slideshow-container').css("position", "absolute");
$('.slideshow-container').css("left", "200px");
$('.slideshow-container').css("top", "1000px");

$('.transpositions').css("background-color", "#fbfcb8");
$('.transpositions').css("max-width", "900px");
$('.transpositions').css("padding", "20px");


$('.translations').css("background-color", "#fbfcb8");

$('.translations').css("max-width", "2000px");
$('.translations').css("padding", "20px");

$('.main-container').css("background-color", "#feffdb");
$('.main-container').css("margin-left", "45%");
$('.main-container').css("padding", "5px");
$('.main-container').css("max-width", "2000px");

$('.gptbox').css("background-color", "#ffffed");

$('.gptbox').css("max-width", "600px");
$('.gptbox').css("padding", "20px");


$('.wordbox').css("background-color", "#ffffed");
$('.wordbox').css("margin", "auto");
$('.wordbox').css("max-width", "800px");
$('.wordbox').css("padding", "20px");


$('.prev').css("cursor", "pointer");
$('.prev').css("position", "absolute");
$('.prev').css("top", "50%");
$('.prev').css("width", "auto");
$('.prev').css("margin-top", "-22px");
$('.prev').css("padding", "16px");
$('.prev').css("color", "white");
$('.prev').css("font-weight", "bold");
$('.prev').css("font-size", "18px");
$('.prev').css("transition", "0.6s ease");
$('.prev').css("border-radius", "0 3px 3px 0");
$('.prev').css("user-select", "none");

$('.next').css("cursor", "pointer");
$('.next').css("position", "absolute");
$('.next').css("top", "50%");
$('.next').css("width", "auto");
$('.next').css("margin-top", "-22px");
$('.next').css("padding", "16px");
$('.next').css("color", "white");
$('.next').css("font-weight", "bold");
$('.next').css("font-size", "18px");
$('.next').css("transition", "0.6s ease");
$('.next').css("border-radius", "0 3px 3px 0");
$('.next').css("user-select", "none");
$('.next').css("right", "0");
$('.next').css("border-radius", "3px 0 0 3px");

$('.text').css("color", "#f2f2f2");
$('.text').css("font-size", "15px");
$('.text').css("padding", "8px 12px");
$('.text').css("position", "absolute");
$('.text').css("bottom", "8px");
$('.text').css("width", "100%");
$('.text').css("text-align", "center");

$('.numbertext').css("color", "#f2f2f2");
$('.numbertext').css("font-size", "12px");
$('.numbertext').css("padding", "8px 12px");
$('.numbertext').css("position", "absolute");
$('.numbertext').css("top", "0");



/* IMAGES */
/*

https://tabimaniajapan.com/japan-trip/japanese-road-signs-be-mindful-of-the-unique-shape-of-the-%E6%AD%A2%E3%81%BE%E3%82%8C-sign

https://japantravel.navitime.com/en/area/jp/guide/NTJnews0429-en/

https://japan-top-10.com/the-top-10-strangest-road-signs-you-will-find-in-japan/

https://www.tripadvisor.com/LocationPhotoDirectLink-g1120812-d11904798-i233781584-Mama_Cafe-Kin_cho_Kunigami_gun_Okinawa_Prefecture_Kyushu.html

https://dynamic-media-cdn.tripadvisor.com/media/photo-o/2d/e1/70/42/caption.jpg?w=900&h=500&s=1

https://dynamic-media-cdn.tripadvisor.com/media/photo-o/1c/20/c2/90/dsc-0698-largejpg.jpg?w=800&h=400&s=1

https://dynamic-media-cdn.tripadvisor.com/media/photo-o/11/9a/b6/03/menu-2.jpg?w=900&h=500&s=1

https://dynamic-media-cdn.tripadvisor.com/media/photo-o/11/0b/3d/fe/photo0jpg.jpg?w=900&h=-1&s=1

https://dynamic-media-cdn.tripadvisor.com/media/photo-o/21/87/55/db/caption.jpg?w=900&h=500&s=1

https://dynamic-media-cdn.tripadvisor.com/media/photo-o/21/3a/9a/cc/caption.jpg?w=900&h=500&s=1

https://www.japantimes.co.jp/life/2017/11/06/language/cants-donts-japanese-society-writ-large-signage/

https://i0.wp.com/100travelstories.com/wp-content/uploads/2014/11/japan-funny-sign-1.jpg?resize=563%2C750

https://bbqboy.net/wp-content/uploads/2017/03/hat-sign-japan.jpg

https://ankiweb.net/shared/mpreview/135266511/1.jpg?1414627200

https://100travelstories.com/blog/funny-signs-japan/

https://landingaway.blogspot.com/2010/11/signs.html

https://ktotokyo.wordpress.com/wp-content/uploads/2012/03/dscn11831.jpg

https://discoverdiscomfort.com/learning-language-to-order-food/

https://unseen-japan.com/tackling-food-kanji-in-japanese-menus/

https://www.reddit.com/r/trains/comments/16cvu8e/one_for_the_only_in_japan_category_instructions/#lightbox

https://www.alamy.com/an-information-sign-on-a-dedicated-shinkansen-bullet-train-platform-showing-where-specific-carriages-will-be-positioned-for-boarding-image354111590.html?imageid=E36828D8-42AE-4B63-A3C7-38EAE4127CF6&p=810080&pn=2&searchId=1a78009a577d33431859f87aab9aceef&searchtype=0

https://www.flickr.com/photos/22749160@N06/7165000339/

https://asia.nikkei.com/Life-Arts/Life/Lost-in-translation-Signs-puzzle-overseas-tourists-in-Japan

https://www.turbosquid.com/FullPreview/1139856

https://wanderthemap.com/2015/04/lost-in-translation-engrish-in-japan/

https://www.japanese-vintage.org/vintage-shop-sign-1950s

https://www.flickr.com/photos/188326905@N04/50821851578

https://aucview.aucfan.com/yahoo/b1026628638/

https://saitoshika-west.com/wp/wp-content/uploads/2022/06/005.jpg

https://japantoday.com/category/features/opinions/The-noise-problem-in-conflict-averse-Japan

https://pt.3dexport.com/3dmodel-japanese-store-signs-142940.htm

https://www.asahi.com/ajw/articles/14829277

https://www.freepik.com/free-photo/close-up-japanese-street-food-shop_22898150.htm

https://figureculture.wordpress.com/wp-content/uploads/2012/05/japaneseracoon.jpg

https://www.alamy.com/yellow-monkey-crossing-road-sign-in-rural-japan-image341086625.html
https://weathernews.jp/s/topics/202010/300115/

https://www.alamy.com/beware-of-wild-bears-sign-akita-japan-image358285942.html?imageid=0A3F5F9A-3ED5-4A9E-A9A9-3D2B9BF651F7&p=14768&pn=1&searchId=2dff3243da58ded39db6ca2148b1c04d&searchtype=0

https://www.upguides.com/nor/trips/japan-road-trip-hokkaido

https://yamap.com/activities/13370370/article

https://en.photo-ac.com/photo/357092/shrine-signs

https://www.istockphoto.com/photos/omikuji?page=3

https://www.dreamstime.com/editorial-image-sign-japanese-park-trelling-people-must-have-their-dog-dog-leash-forbidden-to-leave-dog-poo-image52233760

https://www.photo-ac.com/main/detail/24152724?title=%E9%9D%92%E7%A9%BA%E3%81%A8%E9%A7%90%E7%A6%81

https://textureofjapan.com/products/6-sign-no-bike-parking



*/