Google Sheets/Google Scripts button to copy the contents of active cell to the Android (or Windows) clipboard so the data can be pasted to another app

I want a simple method (I’m thinking a shape on the Google Sheets worksheet used as a button to execute a Google Script) to, with a single click, copy the contents of the active cell or range (priority on a single cell for now) to the Android (and Windows) clipboard, so the data can be quickly and easily copied and pasted to another app. My primary concern for now is that this work on a mobile device.

I’ve made a button on my Google Sheet, and tried several variations of Google Scripts to accomplish the task. I’ve searched for a solution via Google, DuckDuckGo, StackOverflow, and ChatGPT. So far, all sources except ChatGPT seem to indicate this may not be possible at all, due to Google Scripts running on the server side, and therefore having no access to my local environment, consequently being unable to push anything to my local clipboard.

ChatGPT keeps suggesting a few main tacks that all give errors along the lines of “That isn’t really a command that exists or it is not defined”.

  1. ClipboardService.getClipboard()
  2. Utilities.copyToClipboard(value);
  3. document.execCommand(‘copy’);

#2 seems like it might possibly be a library or add-in that I could link to my script, but I haven’t been able to verify that, and if it is true, I don’t know how/where to find it.

#3 seems to be related specifically to the browser environment itself, and not specific to either Google Sheets or the Windows clipboard environment.

Here are a couple functions I’ve found as suggestions for this problem. The concept and code seem very straightforward, but so far nothing is working.

function copyActiveCellValueToClipboard8() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var cell = ss.getActiveCell();
  var value = cell.getValue();
  Utilities.copyToClipboard(value);
}
function copyToClipboard9() {
  var text="Hey it is working!";
  Utilities.setClipboard(text);
}

I found a suggestion that a temporary text area could be created, and the cell contents placed in that text area. From there, it could be pushed to the clipboard, and afterwards the text area could be destroyed. This method is failing with the claim that the document.execCommand(‘copy’); command isn’t a real thing. I think the command is for programming Chrome, but isn’t known or available to Google Scripts.

function copyToClipboard7() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var value = sheet.getActiveCell().getValue();
  
  var textarea = document.createElement('textarea');
  textarea.value = value;
  document.body.appendChild(textarea);
  textarea.select();
  document.execCommand('copy');
  document.body.removeChild(textarea);
  
  SpreadsheetApp.getUi().alert('Copied to clipboard: ' + value);
}

The closest thing I’ve found so far is to have the button launch an HTML sidebar, push whatever data I want copied into a hidden div or some such in the HTML, then have an HTML button in the sidebar that copies the desired data to the clipboard. If I could get that working on a mobile device it would certainly be an acceptable solution, even if it does require two clicks and a sidebar.

Javascript – Trouble integrating login with Outlook using Azure Portal client ID and unable to obtain user credentials

I am currently working on integrating login with Outlook using Azure Portal client ID in my web application. I have followed the documentation and registered an application in the Azure Portal, obtaining a client ID. However, I have encountered several difficulties and have been unable to successfully retrieve user credentials.

Here is an overview of the steps I have taken and the issues I am facing:

I registered an application in the Azure Portal and obtained the client ID.
I implemented the necessary code in my web application, following the provided documentation.
When I click on the "Login with Outlook" button, I expected a login prompt to appear, but nothing happens.
I have checked the console for any error messages and found no relevant information.
I have also reviewed the Azure Portal settings multiple times to ensure the configuration is correct.
I have attempted to troubleshoot the issue by modifying the code and trying different approaches, but none have been successful.

I am unsure why the login prompt is not appearing and why I am unable to obtain user credentials. Could anyone with experience in integrating login with Outlook using Azure Portal client ID provide guidance on what might be causing this issue and suggest potential solutions?

I appreciate any assistance or insights you can provide. Thank you!

<html>
<head>
  <title>Outlook Login Integration</title>
  <script src="https://alcdn.msauth.net/browser/2.18.0/js/msal-browser.min.js"></script>
</head>
<body>
  <button id="loginButton">Login with Outlook</button>

  <script>
    const msalConfig = {
      auth: {
        clientId: 'clientid',
        authority: 'https://login.microsoftonline.com/common',
        redirectUri: 'my url', // Replace with your redirect URI
        clientSecret: 'client secret'
      },
      cache: {
        cacheLocation: 'localStorage',
        storeAuthStateInCookie: true,
      }
    };

    const msalInstance = new msal.PublicClientApplication(msalConfig);

    const loginRequest = {
      scopes: ['openid', 'profile', 'offline_access', 'https://outlook.office.com/Mail.Read'],
    };

    const login = async () => {
      try {
        const response = await msalInstance.loginPopup(loginRequest);
        console.log('Login successful', response);

        const accessTokenResponse = await msalInstance.acquireTokenSilent(loginRequest);
        const accessToken = accessTokenResponse.accessToken;
        console.log('Access token:', accessToken);

        // Use the access token to make API requests to Outlook
        // Example: fetchOutlookMail(accessToken);

      } catch (error) {
        console.error('Login error', error);
      }
    };

    const loginButton = document.getElementById('loginButton');
    loginButton.addEventListener('click', login);

    const fetchOutlookMail = async (accessToken) => {
      const response = await fetch('https://outlook.office.com/api/v2.0/me/messages', {
        headers: {
          'Authorization': `Bearer ${accessToken}`
        }
      });

      if (response.ok) {
        const data = await response.json();
        console.log('Emails:', data.value);
      } else {
        console.error('Error fetching emails:', response.status, response.statusText);
      }
    };
  </script>
</body>
</html>

livewire child component value null

Parent component input value after form submit not null but child component value null.

<div class="row g-4">
 <div class="col-lg-4 col-sm-6">
    <div class="single-info-input">
       <label class="label_title">{{ __('Title') }} </label>
        <input class="form--control" type="text" wire:model.defer="title">
    </div>
 </div>
</div>
          
<!-- child component -->
<div class="row g-4">
    <div class="col-lg-4 col-sm-6">
        <div class="single-info-input">
           <livewire:include-service>
        </div>
    </div>
 </div>
   public function serviceStore()
    {      
        dd($this->include_service_title);
}

Closure Issue in React Custom Hook

I wonder what’s going on here. I finally moved the variable curPage to the global scope in my custom hook as the closure doesn’t work for some weird reason. So well… the problem is solved but it doesn’t look elegant and I’m really concerned why?

This hook is responsible for pagination but it doesn’t really matter what it does. The variable let curPage = 1; that holds the value matters as it’s the value that increments everytime the function getItems runs.

import { useState } from 'react';

// let curPage = 1; I MOVED IT HERE AND WORKS BUT ... well

const usePagination = items => {
  const [itemsToRender, setItemsToRender] = useState(items.slice(0, 4));

  let curPage = 1;
  let maximumItems = 4;
  let totalPages = Math.ceil(items.length / maximumItems);

  //get 4 items per each page;
  const getItems = () => {
    curPage += 1;

    const min = (curPage - 1) * maximumItems;
    const max = curPage * maximumItems;

    setItemsToRender(state => state.concat(items.slice(min, max)));
  };

  return { getItems, itemsToRender, curPage, totalPages };
};

export default usePagination;

The hook is called in some React component function and I immediately destructure returned object.

const { getItems, itemsToRender } = usePagination(articles);

TO SUM UP THE PROBLEM: everytime the function getItems is called, the variable curPage is always 1 by default. So it will always return 2 when curPage += 1; so the logic fails as within every click for example it should grow – 1,2,3,4,5 etc.

The hook is called once and the returned function getItems is called multiple times but the variable curPage is enclosed within custom hook function body so should mutate everytime the function runs.

I don’t understand what’s going on. I will appreciate your suggestions. Thanks in advance! Maciej

How do I disable other values in a column when one is selected?

I am using datatables that cascades information from one column to another. Data is directly pulled from the table except for first column (name) as the requirement is to show the dropdown values in certain way and not ascending order. Datatables puts the values in ascending order.

Problem: Everything works fine except when I choose a value from ‘Name’ column such as Ashton, and then the related position, I am still given the option to choose another name, such as Test1 or Garrett. Changing the name causes the cascading to break down.

The behavior should be – When I choose a Name, simply keep that choice and prevent the user from selecting any other option in the Name column just like other drop-downs or disable other values only for Name column until user selects Reset button.

Is this possible? Here is the link to my code – https://live.datatables.net/yamifera/14/edit

$(document).ready(function() {
  var table = $('#example').DataTable({
    responsive: true,
    searching: true,
    columnDefs: [
            {
                target: 6,
                visible: false,
                searchable: true,
            }
      ],
    dom: 'Bfrtip',
        buttons: [
            {
                extend: 'excelHtml5',
                exportOptions: {
                    columns: ':visible'
                }
            },
            {
                extend: 'pdfHtml5',
                orientation: 'landscape',
                exportOptions: {
                    columns: ':visible'
                     }
              },           
            {
                extend: 'print',
                exportOptions: {
                    columns: ':visible'
                }
               },
        //  'colvis'
        ],
  });

  buildSelect(table);
 
  table.on('draw', function() {
    buildSelect(table);
  });
  $('#test').on('click', function() {
    table.search('').columns().search('').draw();
  });
});

function buildSelect(table) {
  var counter = 0;
  table.columns([0, 1, 2]).every(function() {
    var column = table.column(this, {
      search: 'applied'
    });
    counter++;
    var select = $('<select><option value="">select me</option></select>')
      .appendTo($('#dropdown' + counter).empty())
      .on('change', function() {
        var val = $.fn.dataTable.util.escapeRegex(
          $(this).val()
        );

        column
          .search(val ? '^' + val + '$' : '', true, false)
          .draw();
      });

    if ( column.index() === 0 ) {
      ['Garrett', 'Test1', 'Ashton'].forEach((d) => {
        select.append('<option value="' + d + '">' + d + '</option>');
      });
    } else {
      column.data().unique().sort().each(function(d, j) {
        select.append('<option value="' + d + '">' + d + '</option>');
      });
    }

    // The rebuild will clear the exisiting select, so it needs to be repopulated
    var currSearch = column.search();
    if (currSearch) {
      // ** MY CHANGE **
      // Use RegEx to find the selected value from the unique values of the column.
      // This will use the Regular Expression returned from column.search to find the first matching item in column.data().unique
      select.val(column.data().unique().toArray().find((e) => e.match(new RegExp(currSearch))));
    }
  });
}
<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" type="text/css"  href="https://cdn.datatables.net/1.10.15/css/jquery.dataTables.min.css" />
<link rel="stylesheet" type="text/css"  href="https://cdn.datatables.net/buttons/1.4.0/css/buttons.dataTables.min.css" />

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script>
<script src="https://cdn.rawgit.com/bpampuch/pdfmake/0.1.27/build/pdfmake.min.js"></script>
<script src="https://cdn.rawgit.com/bpampuch/pdfmake/0.1.27/build/vfs_fonts.js"></script>
<script src="https://cdn.datatables.net/1.10.15/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/buttons/1.4.0/js/dataTables.buttons.min.js"></script>
<script src="https://cdn.datatables.net/buttons/1.4.0/js/buttons.flash.min.js"></script>
<script src="https://cdn.datatables.net/buttons/1.4.0/js/buttons.html5.min.js"></script>
<script src="https://cdn.datatables.net/buttons/1.4.0/js/buttons.print.min.js"></script>

    
    
    <meta charset=utf-8 />
    <title>DataTables - JS Bin</title>
  </head>
<div class="searchbox">
<p>Name: 
  
  <span id="dropdown1">
  </span>
</p>

<p>Postion: <span id="dropdown2">
  </span>
</p>

<p>Office: <span id="dropdown3">
</span>
</p>
  <button type="button" id="test">Clear Filters</button>
</div>
  <table id="example" class="cell-border row-border stripe dataTable no-footer dtr-inline" role="grid" style=" width: 100%; padding-top: 10px;"><thead>
<tr>

<th>&#160;</th>
<th>&#160;</th>
<th>&#160;</th>
<th colspan="3" style=" text-align: center;">Information</th>
  <th>&#160;</th>
</tr>


          <tr>
            <th>Name</th>
            <th>Position</th>
            <th>Office</th>
            <th>Age</th>
            <th>Start date</th>
            <th>Salary</th>
            <th>Hidden Column</th>
          </tr>
        </thead>
        
        <tbody>
          <tr>
            <td>
Test1</td>


            <td>test</td>
            <td>test3</td>
            <td>test4</td>
            <td>2011/04/25</td>
            <td>$3,120</td>
            <td>Sys Architect</td>
          </tr>
          <tr>
            <td>Garrett</td>
            <td>Director: fgghghjhjhjhkjkj</td>
            <td>Edinburgh</td>
            <td>63</td>
            <td>2011/07/25</td>
            <td>$5,300</td>
            <td>Director:</td>
          </tr>
          <tr>
            <td>Ashton</td>
            <td>Technical Authorjkjkjk fdfd h gjjjhjhk</td>
            <td>San Francisco</td>
            <td>66</td>
            <td>2009/01/12</td>
            <td>$4,800</td>
            <td>Tech author</td>
          </tr>
          
            
          </tr></tbody></table>
</div>

Here is my code –
https://live.datatables.net/yamifera/14/edit

Describe, It, Before, After, Arrow Functions, unnamed functions and “this”, utility or futility?

We are currently updating our linting to match the Front End Developers’ idea of linting. Mostly because they want to be able to look at and understand our testing code. We are all working in JavaScript.
No big deal… or is it?
We have found, in our “old way” of doing WDIO “Describes” and “Its” that we could simply use an unnamed function, and it simply worked.
it('No Place Like Home', async function () {
We have started updating to the arrow functions, which, on the surface, “look the same(ish)”, but don’t work the same.
Our problem comes with the usage of “this”…
We are using a method of “retry”, and we set the number of retries in our config file. In some of the tests, we need to know if the current run is the first run, or the first retry.
To do this, we grab this.wdioRetries which will tell us “0” for primary run, or “1” for first retry, or “2”, for the second retry, etc.
Wouldn’t you know it? The “unnamed function” lets us use “this” without trouble. The linting gives us a warning about “no unnamed functions”…
When we convert it to the “arrow function”, we get “this.wdioRetries === undefined”. “this” doesn’t exist in the scope of the arrow function. But the linting LOVES the arrow function, even though the test now fails.
We also, at times, need to override certain test values, like default timeout. Which we can’t do without access to “this.test”…

So. The question is, how do we get “this” in an arrow function? Is there a way to pass it in? A way to call it in by another way (process, browser, driver…)? Some built in function to make a call (const thing = whatever.getThis())?

Or, is it futile? We should stay with the unnamed functions?

I’ve tried:
it('No Place Like Home', async () => {
it('No Place Like Home', async (this) => {
it('No Place Like Home', async this => {
I’ve tried simple functions, etc. The problem is the scope, which needs to be at the TEST level, not GLOBAL.
Hoping someone else has blazed this trail before me and has found the solution.

JavaScript Keyboard repeat delay problems

I would like to create game controlled by wasd keys but it doesn’t work as i thought. At any movement it make at first small step and then it’s repeating movement without delay. Here’s the code:

var Player = document.getElementById("Player");
const SpeedX = 35;
const SpeedY = 20;
var x = parseInt(getComputedStyle(Player).marginLeft);
var y = parseInt(getComputedStyle(Player).marginTop); 

var keysPressed = {};

document.addEventListener("keydown", (e) => {
        keysPressed[e.key] = true;

        if(e.key == 'w') {
        if(y > 30 && y < 950) {
            y -= SpeedY;
            Player.style.marginTop = y + "px";
            console.log(y);
        } else if(y == 950) Player.style.marginTop = (y -= SpeedY) + "px";
    }
        if(e.key == 'a') {
        if(x > -5 && x < 1780) {
            x -= SpeedX;
            Player.style.marginLeft = x + "px";
            console.log(x);
        } else if(x == 1780) Player.style.marginLeft = (x -= SpeedX) + "px";
    }
        if(e.key == 's') {
        if(y > 30 && y < 950) {
            y += SpeedY;
            Player.style.marginTop = y + "px";
            console.log(y);
        } else if(y == 30) Player.style.marginTop = (y += SpeedY) + "px";
    }
        if(e.key == 'd') {
        if(x > -5 && x < 1780) {
            x += SpeedX;
            Player.style.marginLeft = x + "px";
            console.log(x);
        } else if(x == -5) Player.style.marginLeft = (x += SpeedX) + "px";
    }
        if(e.key == 'w' && keysPressed['a']) {
            if(x > -5 && x < 1780 && y > 30 && y < 950) {
            y -= SpeedY;
            x -= SpeedX;
            Player.style.marginLeft = x + "px";
            Player.style.marginTop = y + "px";
        }}
        if(e.key == 'w' && keysPressed['d']) {
            if(x > -5 && x < 1780 && y > 30 && y < 950) {
            y -= SpeedY;
            x += SpeedX;
            Player.style.marginLeft = x + "px";
            Player.style.marginTop = y + "px";
        }}
        if(e.key == 's' && keysPressed['a']) {
            if(x > -5 && x < 1780 && y > 30 && y < 950) {
            y += SpeedY;
            x -= SpeedX;
            Player.style.marginLeft = x + "px";
            Player.style.marginTop = y + "px";
        }}
        if(e.key == 's' && keysPressed['d']) {
            if(x > -5 && x < 1780 && y > 30 && y < 950) {
            y += SpeedY;
            x += SpeedX;
            Player.style.marginLeft = x + "px";
            Player.style.marginTop = y + "px";
        }}
        if(e.key == 'a' && keysPressed['w']) {
            if(x > -5 && x < 1780 && y > 30 && y < 950) {
            y -= SpeedY;
            x -= SpeedX;
            Player.style.marginLeft = x + "px";
            Player.style.marginTop = y + "px";
        }}
        if(e.key == 'd' && keysPressed['w']) {
            if(x > -5 && x < 1780 && y > 30 && y < 950) {
            y -= SpeedY;
            x += SpeedX;
            Player.style.marginLeft = x + "px";
            Player.style.marginTop = y + "px";
        }}
        if(e.key == 'a' && keysPressed['s']) {
            if(x > -5 && x < 1780 && y > 30 && y < 950) {
            y += SpeedY;
            x -= SpeedX;
            Player.style.marginLeft = x + "px";
            Player.style.marginTop = y + "px";
        }}
        if(e.key == 'd' && keysPressed['s']) {
            if(x > -5 && x < 1780 && y > 30 && y < 950) {
            y += SpeedY;
            x += SpeedX;
            Player.style.marginLeft = x + "px";
            Player.style.marginTop = y + "px";
        }}
    })

document.addEventListener('keyup', (event) => {
    delete keysPressed[event.key];
});

It looks not so nice when it’s not moving smoothly. Please Help

I’ve looked for some solutions in browser but i can’t find anything useful at my case

adaptar codigo em java scrips

I’m not a programmer, I understand very little code, but I need to create a link in one that hides and shows several objects with the same class (doubt it)… Could someone help me, please?
I found this code fragment that apparently works, but my limitations do not allow me to adapt it to be used with {class}, not {id} as it appears there


function myFunction() {
  var x = document.getElementById("SoftExpert");
  if (x.style.display === "none") {
    x.style.display = "block";
  } else {
    x.style.display = "none";
  }
}

Displaying data in a jsp form using JavaScript

I want to display selected object using query selector and javascript.

From here:

<c:forEach items="${institution}" var="institution">
            <div class="form-group form-group--checkbox">
              <label>
                <form:radiobutton path="institution" name="organization"/>
                <span class="checkbox radio"></span>
                <span class="description">
                  <div class="title">${institution.name}</div>
                  <div class="subtitle">
                    ${institution.description}
                  </div>
                </span>
              </label>
            </div>
            </c:forEach>

            <div class="form-group form-group--buttons">
              <button type="button" class="btn prev-step">Back</button>
              <button type="button" class="btn next-step">Next</button>
            </div>

to here:

                  <li>
                    <span class="icon icon-hand"></span>
                    <span class="summary--text" id="selected-institution">
"nameOfTheInstitution"
                    </span>
                  </li>

Also from

<div class="form-group form-group--inline">
                  <label> STREET <form:input path="street" type="text" name="address" /> </label>
                </div>

to here:

                  <ul>
                    <li>"STREET"</li>
                  </ul>

and

              <label>
                <form:input path="quantity" type="number" name="bags" step="1" min="1" />
              </label>

to here:

                  <li>
                    <span class="icon icon-bag"></span>
                    <span class="summary--text">"QUANTITY"</span>
                  </li>

I tried few things, but they did not work.