Difference between revisions of "Google Slides - Creating an Add On"

From NoskeWiki
Jump to navigation Jump to search
(Created page with "==About== {{DaughterPage|mother=Google Slides, and is related to: JavaScript}} This demos a simple "<b>Google Slides Acknowledgement Slide Generator</b>" which insert...")
 
 
(9 intermediate revisions by the same user not shown)
Line 2: Line 2:
 
{{DaughterPage|mother=[[Google Slides]], and is related to: [[JavaScript]]}}
 
{{DaughterPage|mother=[[Google Slides]], and is related to: [[JavaScript]]}}
  
This demos a simple "<b>Google Slides Acknowledgement Slide Generator</b>" which inserts a bunch of images into . a new slide via a <b>Google Slides Add On</b>.
+
This demos a <b>Google Slides Add On</b> I call "<b>Acknowledgement Slide Generator</b>" which inserts new slide then a grid of images and text boxes.
 +
 
  
 
==Background and Instructions==
 
==Background and Instructions==
Line 8: Line 9:
 
This is similar to instructions from the [https://developers.google.com/gsuite/add-ons/editors/slides/quickstart/translate Google Slides Quickstart (Translate)]... and then the rest I figured out from the [https://developers.google.com/slides/ Slides API].
 
This is similar to instructions from the [https://developers.google.com/gsuite/add-ons/editors/slides/quickstart/translate Google Slides Quickstart (Translate)]... and then the rest I figured out from the [https://developers.google.com/slides/ Slides API].
  
[[image:Google_sites_page_example.png|thumb|center|500px|Google Sites example page (about to click "HTML" button)]] [[image:Google_sites_page_example_messy_html.png|thumb|center|500px|Same Google Sites page showing messy HTML]]
+
{{Warning|message=The code works, but I never managed to actually get this published, because the documentation for that was nasty. I work at Google and I couldn't figure it out. Similar to this is my page: [[JavaScript - Generating Image Boxes from a Text Area]].}}
 +
 
 +
[[image:Google_slides_addon_acknowledges_slide_generator_1200x559.png|thumb|center|1200px|What the thing looks like after run]]
  
  
Line 14: Line 17:
  
 
# Create a new Google Presentation.
 
# Create a new Google Presentation.
# From within your new presentation, select the menu item <b>Tools > Script</b> editor. If you are presented with a welcome screen, click Blank Project.
+
# From within your new presentation, select the menu item <b>Tools > Script editor</b>. If you are presented with a welcome screen, click <b>Blank Project</b>.
# Delete any code in the script editor and rename Code.gs to <b>ackgenerator.gs</b>.
+
# Delete any code in the script editor and rename Code.gs to <b>ackgenerator.gs</b>. You may be prompted to give a project name first (call it "<b>Acknowledgement Slide Generator</b>").
# Create a new file by selecting the menu item <b>File > New > HTML</b> file. Name this file sidebar (Apps Script adds the .html extension automatically).
+
# Create a new file by selecting the menu item <b>File > New > HTML file</b>. Name this file <b>sidebar.html</b>.
 
# Replace any code in these two files with the following content, respectively:
 
# Replace any code in these two files with the following content, respectively:
  
Line 25: Line 28:
 
<syntaxhighlight lang="HTML5">
 
<syntaxhighlight lang="HTML5">
  
...
+
<html>
 +
  <head>
 +
    <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
 +
    <style>
 +
      .logo { vertical-align: middle; }
 +
      ul { list-style-type: none; padding: 0; }
 +
      h4 { margin: 0; }
 +
    </style>
 +
 +
    <script>
 +
      /**
 +
      * Runs generator (in ackgenerator.gs).
 +
      */
 +
      function runGenerator() {
 +
        this.disabled = true;  // Disable buttons, etc, until done.
 +
       
 +
        var numPeople = parseInt(document.getElementById("txt-num-people").value);
 +
        var picWidth = parseInt(document.getElementById("txt-pic-width").value);
 +
        var picHeight = parseInt(document.getElementById("txt-pic-height").value);
 +
        var maxCols = parseInt(document.getElementById("txt-max-cols").value);
 +
 
 +
        google.script.run
 +
            .withUserObject(this)
 +
            .addAcknowledgmentSlide(numPeople, picWidth, picHeight, maxCols);
 +
 
 +
        this.disabled = false;  // Re-enable buttons.
 +
      }
 +
    </script>
 +
 +
  </head>
 +
  <body>
 +
 
 +
    <form class="sidebar branding-below">
 +
      Number people: <input type="number" name="txt-num-people" id="txt-num-people"
 +
                            min="1" max="30" value="4">
 +
      <br>
 +
      Picture size:  <input type="number" name="txt-pic-width" id="txt-pic-width"
 +
                            min="10" max="300" value="100" step="5" style="width:60px"> x
 +
                    <input type="number" name="txt-pic-height" id="txt-pic-height"
 +
                            min="10" max="300" value="100" step="5" style="width:60px">
 +
      <br>
 +
      Max columns:  <input type="number" name="txt-max-cols" id="txt-max-cols"\
 +
                            min="1" max="30" value="6"><br>
 +
 
 +
      <div class="block" id="button-bar">
 +
        <button class="blue" id="run-generator" onclick="runGenerator()">Generate</button>
 +
      </div>
 +
      <h5 class="error" id="txt-feedback"></h5>
 +
    </form>
 +
    <div class="sidebar bottom">
 +
      <img alt="Add-on logo" class="logo"
 +
        src="https://www.gstatic.com/images/branding/product/1x/translate_48dp.png" width="27" height="27">
 +
      <span class="gray branding-text">Ack Generator</span>
 +
    </div>
 +
 
 +
  </body>
 +
</html>
  
 
</syntaxhighlight>
 
</syntaxhighlight>
Line 34: Line 93:
 
<syntaxhighlight lang="JavaScript">
 
<syntaxhighlight lang="JavaScript">
  
...
 
  
</syntaxhighlight>
+
/**
 +
* @OnlyCurrentDoc Limits the script to only accessing the current presentation.
 +
*
 +
* CREDIT: Andrew Noske. 2019.
 +
* SOURCE: https://andrewnoske.com/wiki/Google_Slides_-_Creating_an_Add_On .
 +
*/
 +
 
 +
/**
 +
* Create an Open "Acknowledgement Generator" menu item.
 +
* @param {Event} event The open event.
 +
*/
 +
function onOpen(event) {
 +
  SlidesApp.getUi().createAddonMenu()
 +
      .addItem('Open', 'showSidebar')
 +
      .addToUi();
 +
}
 +
 
 +
/**
 +
* Open the Add-on upon install.
 +
* @param {Event} event The install event.
 +
*/
 +
function onInstall(event) {
 +
  onOpen(event);
 +
}
 +
 
 +
/**
 +
* Opens a sidebar in the document containing the add-on's user interface.
 +
*/
 +
function showSidebar() {
 +
  var ui = HtmlService
 +
      .createHtmlOutputFromFile('sidebar')
 +
      .setTitle('Acknowledgement Slide Generator');
 +
  SlidesApp.getUi().showSidebar(ui);
 +
}
 +
 
 +
/**
 +
* Insert a new blank slide at the start of the current presentation
 +
* with a title that says "Acknowledgements".
 +
*/
 +
function insertTitleSlideAtStart() {
 +
  var presentation = SlidesApp.getActivePresentation();
 +
  var slide = presentation.insertSlide(0, SlidesApp.PredefinedLayout.BLANK);
 +
 
 +
  var SLIDE_WIDTH = SlidesApp.getActivePresentation().getPageWidth();
 +
  var titleText = slide.insertTextBox("Acknowledgements", 10, 10, SLIDE_WIDTH - 20, 50);
 +
  titleText.getText().getTextStyle()
 +
      .setFontSize(30)
 +
      .setBold(true);
 +
}
 +
 
 +
/**
 +
* Inserts a new "Acknowledgement Slide at the start of the presentation.
 +
* This slide has the given number of profile images and text,
 +
* evently spaced in a grid.
 +
*
 +
* @param {number} numPeople The number of profiles to create.
 +
* @param {number} picWidth The width of each picture in pixels.
 +
* @param {number} picHeight The height of each picture in pixels.
 +
* @param {number} maxColumns The maximum number of columns to show. If numPeople
 +
*    is more than this it will start adding rows.
 +
* @return {number} The number of profiles created.
 +
*/
 +
function addAcknowledgmentSlide(numPeople, picWidth, picHeight, maxColumns) {
 +
  // Insert new slide to start of presentation.
 +
  insertTitleSlideAtStart();
 +
 
 +
  // Get first slide:
 +
  var slideDeck = SlidesApp.getActivePresentation();
 +
  var slide = slideDeck.getSlides()[0];
 +
 
 +
  // Slide dimensions:
 +
  var SLIDE_WIDTH = slideDeck.getPageWidth();
 +
  var SLIDE_HEIGHT = slideDeck.getPageHeight();
 +
  var SLIDE_TOP_BANNER = 60;  // Bedause we already added a title that says "Acknowledgements".
 +
 
 +
  // Profile dimensions:
 +
  var profileNameHeight = 30;
 +
  var profileCommentHeight = 20;
 +
  var profileHeight = picHeight + profileNameHeight + profileCommentHeight;
 +
 
 +
  var profileNameYOffset = picHeight;
 +
  var profileCommentYOffset = profileNameYOffset + profileNameHeight;
 +
 
 +
  // Determine number of rows/columns and spacing between boxes:
 +
  var cols = (numPeople > maxColumns) ? maxColumns : numPeople;
 +
  var rows = Math.ceil(numPeople / maxColumns);
 +
  var xSpacing = (SLIDE_WIDTH - (cols * picWidth)) / (cols + 1);
 +
  var ySpacing = ((SLIDE_HEIGHT - SLIDE_TOP_BANNER) - (rows * profileHeight)) / (rows + 1);
 +
 
 +
  console.log('SLIDE_WIDTH=' + SLIDE_WIDTH + ' * SLIDE_HEIGHT=' + SLIDE_HEIGHT);  // DO NOT SUBMIT.
 +
  console.log('cols=' + cols + ' * rows=' + rows);  // DO NOT SUBMIT.
 +
  console.log('xSpacing=' + xSpacing + ' * ySpacing=' + ySpacing);  // DO NOT SUBMIT.
 +
 
 +
  // For each person:
 +
  for(var i = 0; i < numPeople; i++) {
 +
    var rowIdx = Math.floor(i / maxColumns);
 +
    var colIdx = i - (rowIdx * maxColumns);
 +
   
 +
    var x = (colIdx * picWidth) + ((colIdx + 1) * xSpacing);
 +
    var y = (rowIdx * profileHeight) + ((rowIdx + 1) * ySpacing) + SLIDE_TOP_BANNER;
 +
   
 +
    console.log(' ' +  i + ':  x,y=' + x + ',' + y);  // DO NOT SUBMIT.
 +
 
 +
    // Add placeholder image:
 +
    var img = slide.insertImage(
 +
        "https://andrewnoske.com/w/images/1/16/Unknown_profile_300x300.png",
 +
        x, y, picWidth, picHeight);
 +
 
 +
    // Add text box for name:
 +
    var nameBox = slide.insertTextBox(
 +
        "First Last",
 +
        x, y + profileNameYOffset, picWidth, profileNameHeight);
 +
    nameBox.getText().getTextStyle().setBold(true);
 +
 
 +
    // Add text box for comment or email.
 +
    var commentBox = slide.insertTextBox(
 +
        "andrew.noske@",
 +
        x, y + profileCommentYOffset, picWidth, profileCommentHeight);
 +
    commentBox.getText().getTextStyle()
 +
        .setLinkUrl('http://www.andrewnoske.com')
 +
        .setFontSize(10)
 +
        .setForegroundColor('#0000dd');
 +
  }
 +
 
 +
  return numPeople;
 +
}
 +
 
 +
/**
 +
* Test function you can run in http://script.google.com without opening the menu.
 +
*/
 +
function testAddAcknowledgmentSlide() {
 +
  var numPeople = 4;
 +
  var picWidth = 100;
 +
  var picHeight = 100;
 +
  var maxColumns = 6;
 +
  addAcknowledgmentSlide(numPeople, picWidth, picHeight, maxColumns);
 +
}
 +
 
  
  
 +
</syntaxhighlight>
  
  
 +
* Save the project:
 +
** Select the menu item <b>File > Save all</b>. Name your new script "<b>Acknowledgement Slide Generator</b>" and click OK. The script's name is shown to end users in several places, including the authorization dialog.
 +
** Select the menu item <b>File > Managed versions</b> save as a first version.
 +
* Try it out:
 +
** Switch back to your presentation and reload the page.
 +
After a few seconds, a "Acknowledgement Generator" sub-menu appears under the Add-ons menu. Click <b>Add-ons > Acknowledgement Generator > Start</b>.
 +
** A dialog box indicates that the script requires authorization. Click Continue. A second dialog box requests authorization for specific Google services. Click Allow.
 +
** A sidebar appears. To test it, type some text into your presentation, then select it, and click the blue Generate button. To replace the text in the presentation, click Insert.
 +
* Publish:
 +
** If you were developing a real add-on, the last step would be to [https://developers.google.com/gsuite/add-ons/how-tos/publishing-editor-addons publish] it for other people to find and install.
  
 
==Links==
 
==Links==

Latest revision as of 20:18, 26 July 2019

About

NOTE: This page is a daughter page of: Google Slides, and is related to: JavaScript


This demos a Google Slides Add On I call "Acknowledgement Slide Generator" which inserts new slide then a grid of images and text boxes.


Background and Instructions

This is similar to instructions from the Google Slides Quickstart (Translate)... and then the rest I figured out from the Slides API.


Warning: The code works, but I never managed to actually get this published, because the documentation for that was nasty. I work at Google and I couldn't figure it out. Similar to this is my page: JavaScript - Generating Image Boxes from a Text Area.


What the thing looks like after run


Steps:

  1. Create a new Google Presentation.
  2. From within your new presentation, select the menu item Tools > Script editor. If you are presented with a welcome screen, click Blank Project.
  3. Delete any code in the script editor and rename Code.gs to ackgenerator.gs. You may be prompted to give a project name first (call it "Acknowledgement Slide Generator").
  4. Create a new file by selecting the menu item File > New > HTML file. Name this file sidebar.html.
  5. Replace any code in these two files with the following content, respectively:


Google Slides Add On - Acknowledgement Slide Generator

sidebar.html

<html>
  <head>
    <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
    <style>
      .logo { vertical-align: middle; }
      ul { list-style-type: none; padding: 0; }
      h4 { margin: 0; }
    </style>
 
    <script>
      /**
       * Runs generator (in ackgenerator.gs).
       */
      function runGenerator() {
        this.disabled = true;  // Disable buttons, etc, until done.
        
        var numPeople = parseInt(document.getElementById("txt-num-people").value);
        var picWidth = parseInt(document.getElementById("txt-pic-width").value);
        var picHeight = parseInt(document.getElementById("txt-pic-height").value);
        var maxCols = parseInt(document.getElementById("txt-max-cols").value);

        google.script.run
            .withUserObject(this)
            .addAcknowledgmentSlide(numPeople, picWidth, picHeight, maxCols);

        this.disabled = false;  // Re-enable buttons.
      }
    </script>
 
  </head>
  <body>

    <form class="sidebar branding-below">
      Number people: <input type="number" name="txt-num-people" id="txt-num-people"
                            min="1" max="30" value="4">
      <br>
      Picture size:  <input type="number" name="txt-pic-width" id="txt-pic-width"
                            min="10" max="300" value="100" step="5" style="width:60px"> x 
                     <input type="number" name="txt-pic-height" id="txt-pic-height"
                            min="10" max="300" value="100" step="5" style="width:60px">
      <br>
      Max columns:   <input type="number" name="txt-max-cols" id="txt-max-cols"\
                            min="1" max="30" value="6"><br>

      <div class="block" id="button-bar">
        <button class="blue" id="run-generator" onclick="runGenerator()">Generate</button>
      </div>
      <h5 class="error" id="txt-feedback"></h5>
    </form>
    <div class="sidebar bottom">
      <img alt="Add-on logo" class="logo"
        src="https://www.gstatic.com/images/branding/product/1x/translate_48dp.png" width="27" height="27">
      <span class="gray branding-text">Ack Generator</span>
    </div>

  </body>
</html>


ackgenerator.gs

/**
 * @OnlyCurrentDoc Limits the script to only accessing the current presentation.
 *
 * CREDIT: Andrew Noske. 2019.
 * SOURCE: https://andrewnoske.com/wiki/Google_Slides_-_Creating_an_Add_On .
 */

/**
 * Create an Open "Acknowledgement Generator" menu item.
 * @param {Event} event The open event.
 */
function onOpen(event) {
  SlidesApp.getUi().createAddonMenu()
      .addItem('Open', 'showSidebar')
      .addToUi();
}

/**
 * Open the Add-on upon install.
 * @param {Event} event The install event.
 */
function onInstall(event) {
  onOpen(event);
}

/**
 * Opens a sidebar in the document containing the add-on's user interface.
 */
function showSidebar() {
  var ui = HtmlService
      .createHtmlOutputFromFile('sidebar')
      .setTitle('Acknowledgement Slide Generator');
  SlidesApp.getUi().showSidebar(ui);
}

/**
 * Insert a new blank slide at the start of the current presentation
 * with a title that says "Acknowledgements".
 */
function insertTitleSlideAtStart() {
  var presentation = SlidesApp.getActivePresentation();
  var slide = presentation.insertSlide(0, SlidesApp.PredefinedLayout.BLANK);

  var SLIDE_WIDTH = SlidesApp.getActivePresentation().getPageWidth();
  var titleText = slide.insertTextBox("Acknowledgements", 10, 10, SLIDE_WIDTH - 20, 50);
  titleText.getText().getTextStyle()
      .setFontSize(30)
      .setBold(true);
}

/**
 * Inserts a new "Acknowledgement Slide at the start of the presentation.
 * This slide has the given number of profile images and text,
 * evently spaced in a grid.
 *
 * @param {number} numPeople The number of profiles to create.
 * @param {number} picWidth The width of each picture in pixels.
 * @param {number} picHeight The height of each picture in pixels.
 * @param {number} maxColumns The maximum number of columns to show. If numPeople
 *     is more than this it will start adding rows.
 * @return {number} The number of profiles created.
 */
function addAcknowledgmentSlide(numPeople, picWidth, picHeight, maxColumns) {
  // Insert new slide to start of presentation.
  insertTitleSlideAtStart();
  
  // Get first slide:
  var slideDeck = SlidesApp.getActivePresentation();
  var slide = slideDeck.getSlides()[0];
  
  // Slide dimensions:
  var SLIDE_WIDTH = slideDeck.getPageWidth();
  var SLIDE_HEIGHT = slideDeck.getPageHeight();
  var SLIDE_TOP_BANNER = 60;  // Bedause we already added a title that says "Acknowledgements".
  
  // Profile dimensions:
  var profileNameHeight = 30;
  var profileCommentHeight = 20;
  var profileHeight = picHeight + profileNameHeight + profileCommentHeight;

  var profileNameYOffset = picHeight;
  var profileCommentYOffset = profileNameYOffset + profileNameHeight;

  // Determine number of rows/columns and spacing between boxes:
  var cols = (numPeople > maxColumns) ? maxColumns : numPeople;
  var rows = Math.ceil(numPeople / maxColumns);
  var xSpacing = (SLIDE_WIDTH - (cols * picWidth)) / (cols + 1);
  var ySpacing = ((SLIDE_HEIGHT - SLIDE_TOP_BANNER) - (rows * profileHeight)) / (rows + 1);
  
  console.log('SLIDE_WIDTH=' + SLIDE_WIDTH + ' * SLIDE_HEIGHT=' + SLIDE_HEIGHT);  // DO NOT SUBMIT.
  console.log('cols=' + cols + ' * rows=' + rows);  // DO NOT SUBMIT.
  console.log('xSpacing=' + xSpacing + ' * ySpacing=' + ySpacing);  // DO NOT SUBMIT.
  
  // For each person:
  for(var i = 0; i < numPeople; i++) {
    var rowIdx = Math.floor(i / maxColumns);
    var colIdx = i - (rowIdx * maxColumns);
    
    var x = (colIdx * picWidth) + ((colIdx + 1) * xSpacing);
    var y = (rowIdx * profileHeight) + ((rowIdx + 1) * ySpacing) + SLIDE_TOP_BANNER;
    
    console.log(' ' +  i + ':  x,y=' + x + ',' + y);  // DO NOT SUBMIT.

    // Add placeholder image:
    var img = slide.insertImage(
        "https://andrewnoske.com/w/images/1/16/Unknown_profile_300x300.png",
        x, y, picWidth, picHeight);

    // Add text box for name:
    var nameBox = slide.insertTextBox(
        "First Last",
        x, y + profileNameYOffset, picWidth, profileNameHeight);
    nameBox.getText().getTextStyle().setBold(true);

    // Add text box for comment or email. 
    var commentBox = slide.insertTextBox(
        "andrew.noske@",
        x, y + profileCommentYOffset, picWidth, profileCommentHeight);
    commentBox.getText().getTextStyle()
        .setLinkUrl('http://www.andrewnoske.com')
        .setFontSize(10)
        .setForegroundColor('#0000dd');
  }

  return numPeople;
}

/**
 * Test function you can run in http://script.google.com without opening the menu.
 */
function testAddAcknowledgmentSlide() {
  var numPeople = 4;
  var picWidth = 100;
  var picHeight = 100;
  var maxColumns = 6;
  addAcknowledgmentSlide(numPeople, picWidth, picHeight, maxColumns);
}


  • Save the project:
    • Select the menu item File > Save all. Name your new script "Acknowledgement Slide Generator" and click OK. The script's name is shown to end users in several places, including the authorization dialog.
    • Select the menu item File > Managed versions save as a first version.
  • Try it out:
    • Switch back to your presentation and reload the page.

After a few seconds, a "Acknowledgement Generator" sub-menu appears under the Add-ons menu. Click Add-ons > Acknowledgement Generator > Start.

    • A dialog box indicates that the script requires authorization. Click Continue. A second dialog box requests authorization for specific Google services. Click Allow.
    • A sidebar appears. To test it, type some text into your presentation, then select it, and click the blue Generate button. To replace the text in the presentation, click Insert.
  • Publish:
    • If you were developing a real add-on, the last step would be to publish it for other people to find and install.

Links

  • Google Slides - official site, where you can create your own slides.