xref: /plugin/copy2clipboard/script.js (revision 2f4d862e5abea60afe39e08fe64d1d9813adf6eb)
1add26278SSchplurtz le Déboulonné/*
2add26278SSchplurtz le Déboulonné * Copy2clipboard - copy <pre> text to clipboard.
3add26278SSchplurtz le Déboulonné * Copyright (C) 2020, 2021 Schplurtz le Déboulonné <Schplurtz@laposte.net>
4add26278SSchplurtz le Déboulonné *
5add26278SSchplurtz le Déboulonné * This program is free software; you can redistribute it and/or modify
6add26278SSchplurtz le Déboulonné * it under the terms of the CECILL 2.1 free license. See files
7add26278SSchplurtz le Déboulonné * LICENSE and LICENSE-fr for the details in the distribution directory or
8add26278SSchplurtz le Déboulonné * http://cecill.info/licences/Licence_CeCILL_V2.1-en.html
9add26278SSchplurtz le Déboulonné */
104a476730SSchplurtz le DéboulonnéjQuery(function() {
114a476730SSchplurtz le Déboulonné  if(!navigator.clipboard)
124a476730SSchplurtz le Déboulonné    return;
131c306beaSSchplurtz le Déboulonné  // messageBox( 'id', 'text' ); flash a message at top of screen
144a476730SSchplurtz le Déboulonné  var messageBox=function( id, txt ) {
154a476730SSchplurtz le Déboulonné    const body=document.getElementsByTagName('body')[0];
164a476730SSchplurtz le Déboulonné    const msg=document.createElement('div');
174a476730SSchplurtz le Déboulonné    msg.setAttribute('id', id );
184a476730SSchplurtz le Déboulonné    msg.classList.add('cp2clipmsg');
194a476730SSchplurtz le Déboulonné    const content = document.createTextNode(txt);
204a476730SSchplurtz le Déboulonné    msg.appendChild(content);
214a476730SSchplurtz le Déboulonné    body.appendChild(msg);
224a476730SSchplurtz le Déboulonné    window.setTimeout(function() {
234a476730SSchplurtz le Déboulonné        jQuery("#"+id).fadeTo(500, 0).slideUp(500, function(){
244a476730SSchplurtz le Déboulonné            jQuery(this).remove();
254a476730SSchplurtz le Déboulonné        });
264a476730SSchplurtz le Déboulonné    }, 1500);
2795208031SSchplurtz le Déboulonné  };
281c306beaSSchplurtz le Déboulonné  // true on MS windows. used to set EOL
2986783ee6SSchplurtz le Déboulonné  var iswin = (navigator.appVersion.indexOf("Win") != -1);
301c306beaSSchplurtz le Déboulonné  // The async function that respond to click event
31eeae6715SSchplurtz le Déboulonné  var response=async function(event) {
32eeae6715SSchplurtz le Déboulonné    try {
33b16ffdaeSSchplurtz le Déboulonné      let text='';
3486783ee6SSchplurtz le Déboulonné      // when line numbers are on, geshi uses <li> tag for each line
351c306beaSSchplurtz le Déboulonné      let lis=event.target.previousSibling.getElementsByTagName('li');
36eeae6715SSchplurtz le Déboulonné      if( lis.length ) {
37eeae6715SSchplurtz le Déboulonné        for( let li of lis ) {
38eeae6715SSchplurtz le Déboulonné          text += li.textContent + '\n';
39eeae6715SSchplurtz le Déboulonné        }
40eeae6715SSchplurtz le Déboulonné      }
4186783ee6SSchplurtz le Déboulonné      // no line numbers, whole text is directely in <pre> tag
42eeae6715SSchplurtz le Déboulonné      else {
431c306beaSSchplurtz le Déboulonné        text = event.target.previousSibling.textContent;
4486783ee6SSchplurtz le Déboulonné        text = text.replace( /\r\n/g, '\n' ); // can happen if page files are prepared on win and dropped in doku tree...
45eeae6715SSchplurtz le Déboulonné      }
4686783ee6SSchplurtz le Déboulonné      // Why replace \u00A0 ??? geshi adds an NBSP on each empty line. This is an issue
47eeae6715SSchplurtz le Déboulonné      // with python, perl... when you want to run copied code, you get a
48eeae6715SSchplurtz le Déboulonné      // syntax error "unexpected \xC2 character" or similar... So remove this
49eeae6715SSchplurtz le Déboulonné      // crap. And yes it could remove a legitimate NBSP ; chances are low though.
50eeae6715SSchplurtz le Déboulonné      text = text.replace(/^\u00A0$/gm, "");
5186783ee6SSchplurtz le Déboulonné      // if you paste \n separated lines with right button in powershell, the lines are
5286783ee6SSchplurtz le Déboulonné      // fed in reverse order ! Most stupidly funny bug by MS ever. Anyway, just make sure
5386783ee6SSchplurtz le Déboulonné      // we use \r\n separated lines under windows. It just makes sense.
5486783ee6SSchplurtz le Déboulonné      // see powershell bugs https://github.com/PowerShell/PowerShell/issues/3816 and
5586783ee6SSchplurtz le Déboulonné      // https://github.com/PowerShell/PSReadLine/issues/496 or
5686783ee6SSchplurtz le Déboulonné      // https://github.com/PowerShell/PSReadLine/issues/579 , they're all the same...
5786783ee6SSchplurtz le Déboulonné      if( iswin ) {
5886783ee6SSchplurtz le Déboulonné        text=text.replace(/\n/g, '\r\n' );
5986783ee6SSchplurtz le Déboulonné      }
60eeae6715SSchplurtz le Déboulonné      await navigator.clipboard.writeText(text);
61f20dc62bSSchplurtz le Déboulonné      // console.log( "copié >>>" + text + "<<<" );
62eeae6715SSchplurtz le Déboulonné      messageBox('cp2clipok', LANG.plugins.copy2clipboard.copied);
63eeae6715SSchplurtz le Déboulonné    } catch (err) {
64f20dc62bSSchplurtz le Déboulonné      // console.error('Failed to copy!', err);
65eeae6715SSchplurtz le Déboulonné      messageBox('cp2clipnok', LANG.plugins.copy2clipboard.error);
66eeae6715SSchplurtz le Déboulonné    }
67eeae6715SSchplurtz le Déboulonné  };
68eeae6715SSchplurtz le Déboulonné
691c306beaSSchplurtz le Déboulonné  // iterate over all <pre> node and create the needed structure.
701c306beaSSchplurtz le Déboulonné  // <pre>...</pre> ==> <div class="cp2clipcont"><pre>...</pre><button /></div>
71*2f4d862eSSchplurtz le Déboulonné  let sup='desktop';
72*2f4d862eSSchplurtz le Déboulonné  if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent))
73*2f4d862eSSchplurtz le Déboulonné    sup='mobile';
74*2f4d862eSSchplurtz le Déboulonné  let classes=['cp2clipcont', sup];
754a476730SSchplurtz le Déboulonné  document.querySelectorAll('pre.code,pre.file').forEach(function(elem) {
761c306beaSSchplurtz le Déboulonné    // wrap current node in a div. See https://stackoverflow.com/a/46595686/1831273
771c306beaSSchplurtz le Déboulonné    let container=document.createElement('div');
78*2f4d862eSSchplurtz le Déboulonné    container.classList.add(...classes);
791c306beaSSchplurtz le Déboulonné    elem.parentNode.insertBefore(container, elem);
801c306beaSSchplurtz le Déboulonné    elem.previousElementSibling.appendChild(elem);
811c306beaSSchplurtz le Déboulonné
821c306beaSSchplurtz le Déboulonné    let cpbutton = document.createElement('button');
831c306beaSSchplurtz le Déboulonné    cpbutton.setAttribute( 'title', LANG.plugins.copy2clipboard.title);
841c306beaSSchplurtz le Déboulonné    //cpbutton.classList.add('cp2clip');
851c306beaSSchplurtz le Déboulonné    container.appendChild(cpbutton);
861c306beaSSchplurtz le Déboulonné    cpbutton.addEventListener('click', response)
874a476730SSchplurtz le Déboulonné  })
8895208031SSchplurtz le Déboulonné});
894a476730SSchplurtz le Déboulonné
90