مربّعات الحوار والأشرطة الجانبية في مستندات Google Workspace

يمكن أن تعرض النصوص البرمجية المرتبطة بـ "مستندات Google" أو "جداول بيانات Google" أو "نماذج Google" عدة أنواع من عناصر واجهة المستخدم، مثل التنبيهات والطلبات المنشأة مسبقًا، بالإضافة إلى مربّعات الحوار والأشرطة الجانبية التي تحتوي على صفحات خدمة HTML المخصّصة. عادةً ما يتم فتح هذه العناصر من عناصر القائمة. (يُرجى العلم أنّه في "نماذج Google"، لا تكون عناصر واجهة المستخدم مرئية إلّا للمحرِّر الذي يفتح النموذج لتعديله، وليس للمستخدم الذي يفتح النموذج للردّ عليه).

مربّعات حوار التنبيهات

التنبيه هو مربّع حوار مضمَّن مسبقًا يتم فتحه داخل أداة تحرير "مستندات Google" أو "جداول بيانات Google" أو "العروض التقديمية من Google" أو "نماذج Google". يعرض رسالة وزر "موافق"؛ ويكون العنوان والأزرار البديلة اختيارية. وهو يشبه استدعاء window.alert() في JavaScript من جهة العميل داخل متصفح ويب.

تُعلّق التنبيهات النص البرمجي من جهة الخادم أثناء فتح مربع الحوار. يستأنف النص البرمجي بعد أن يغلق المستخدم مربّع الحوار، ولكن لا تستمر اتصالات JDBC خلال فترة التعليق.

كما هو موضح في المثال أدناه، تستخدم كل من "مستندات Google" و"نماذج Google" و"العروض التقديمية من Google" و"جداول بيانات Google" الطريقة Ui.alert() المتوفرة بثلاث خيارات مختلفة. لإلغاء زر "حسنًا" التلقائي، أدخِل قيمة من التعداد Ui.ButtonSet كوسيطة buttons. لتقييم الزر الذي نقر عليه المستخدم، قارِن القيمة المعروضة لـ alert() بتعداد Ui.Button.

function onOpen() {
  SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
      .createMenu('Custom Menu')
      .addItem('Show alert', 'showAlert')
      .addToUi();
}

function showAlert() {
  var ui = SpreadsheetApp.getUi(); // Same variations.

  var result = ui.alert(
     'Please confirm',
     'Are you sure you want to continue?',
      ui.ButtonSet.YES_NO);

  // Process the user's response.
  if (result == ui.Button.YES) {
    // User clicked "Yes".
    ui.alert('Confirmation received.');
  } else {
    // User clicked "No" or X in the title bar.
    ui.alert('Permission denied.');
  }
}

مربّعات حوار الطلبات

الطلب هو مربّع حوار مصمم مسبقًا يتم فتحه داخل أداة تحرير "مستندات Google" أو "جداول بيانات Google" أو "العروض التقديمية من Google" أو "نماذج Google". ويعرض رسالة وحقل إدخال نص وزر "حسنًا"؛ أما العنوان والأزرار البديلة، فهي اختيارية. وهو يشبه استدعاء window.prompt() في JavaScript من جهة العميل داخل متصفح ويب.

تؤدي الطلبات إلى تعليق النص البرمجي من جهة الخادم عندما يكون مربّع الحوار مفتوحًا. يستأنف النص البرمجي بعد أن يغلق المستخدم مربّع الحوار، ولكن لا تستمر اتصالات JDBC خلال فترة التعليق.

كما هو موضّح في المثال أدناه، تستخدم كل من "نماذج Google" و"العروض التقديمية من Google" و"جداول بيانات Google" الطريقة Ui.prompt() المتوفرة بثلاث خيارات مختلفة. لإلغاء زر "حسنًا" التلقائي، مرِّر قيمة من التعداد Ui.ButtonSet كوسيطة buttons. لتقييم ردّ المستخدم، سجِّل القيمة المعروضة لـ prompt()، ثم استدعِ PromptResponse.getResponseText() لاسترداد البيانات التي أدخلها المستخدم، وقارن القيمة المعروضة لـ PromptResponse.getSelectedButton() بتعداد Ui.Button.

function onOpen() {
  SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
      .createMenu('Custom Menu')
      .addItem('Show prompt', 'showPrompt')
      .addToUi();
}

function showPrompt() {
  var ui = SpreadsheetApp.getUi(); // Same variations.

  var result = ui.prompt(
      'Let\'s get to know each other!',
      'Please enter your name:',
      ui.ButtonSet.OK_CANCEL);

  // Process the user's response.
  var button = result.getSelectedButton();
  var text = result.getResponseText();
  if (button == ui.Button.OK) {
    // User clicked "OK".
    ui.alert('Your name is ' + text + '.');
  } else if (button == ui.Button.CANCEL) {
    // User clicked "Cancel".
    ui.alert('I didn\'t get your name.');
  } else if (button == ui.Button.CLOSE) {
    // User clicked X in the title bar.
    ui.alert('You closed the dialog.');
  }
}

مربّعات الحوار المخصّصة

يمكن لمربع الحوار المخصص عرض واجهة مستخدم خدمة HTML داخل أداة تحرير المستندات أو جداول البيانات أو العروض التقديمية أو النماذج من Google.

لا تعلِّق مربعات الحوار المخصّصة النص البرمجي من جهة الخادم عندما يكون مربّع الحوار مفتوحًا. يمكن للمكوِّن من جهة العميل إجراء استدعاءات غير متزامنة للنص البرمجي من جهة الخادم باستخدام واجهة برمجة التطبيقات google.script API لواجهات خدمة HTML.

يمكن أن يتم إغلاق مربّع الحوار تلقائيًا عن طريق طلب الرمز google.script.host.close() من جهة العميل في واجهة خدمة HTML. لا يمكن إغلاق مربّع الحوار من خلال واجهات أخرى، بل المستخدم أو المستخدم وحده.

كما هو موضح في المثال أدناه، تستخدم كل من "مستندات Google" و"نماذج Google" و"العروض التقديمية من Google" و"جداول بيانات Google" الطريقة Ui.showModalDialog() لفتح مربّع الحوار.

Code.gs

function onOpen() {
  SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
      .createMenu('Custom Menu')
      .addItem('Show dialog', 'showDialog')
      .addToUi();
}

function showDialog() {
  var html = HtmlService.createHtmlOutputFromFile('Page')
      .setWidth(400)
      .setHeight(300);
  SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
      .showModalDialog(html, 'My custom dialog');
}

Page.html

Hello, world! <input type="button" value="Close" onclick="google.script.host.close()" />

الأشرطة الجانبية المخصصة

يمكن للشريط الجانبي عرض واجهة مستخدم خدمة HTML داخل أداة تحرير "مستندات Google" و"نماذج Google" و"العروض التقديمية من Google" و"جداول بيانات Google".

لا تعلّق الأشرطة الجانبية النص البرمجي من جهة الخادم عندما يكون مربّع الحوار مفتوحًا. يمكن للمكوِّن من جهة العميل إجراء استدعاءات غير متزامنة للنص البرمجي من جهة الخادم باستخدام واجهة برمجة التطبيقات google.script لواجهات خدمة HTML.

يمكن أن يتم إغلاق الشريط الجانبي تلقائيًا عن طريق طلب الرمز google.script.host.close() من جهة العميل ضِمن واجهة خدمة HTML. لا يمكن إغلاق الشريط الجانبي من خلال واجهات أخرى، ولكن من قبل المستخدم فقط أو نفسه.

كما هو موضّح في المثال أدناه، تستخدم كل من "مستندات Google" و"نماذج Google" و"العروض التقديمية من Google" و"جداول بيانات Google" الطريقة Ui.showSidebar() لفتح الشريط الجانبي.

Code.gs

function onOpen() {
  SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
      .createMenu('Custom Menu')
      .addItem('Show sidebar', 'showSidebar')
      .addToUi();
}

function showSidebar() {
  var html = HtmlService.createHtmlOutputFromFile('Page')
      .setTitle('My custom sidebar');
  SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
      .showSidebar(html);
}

Page.html

Hello, world! <input type="button" value="Close" onclick="google.script.host.close()" />

مربّعات حوار فتح الملفات

منتقي Google هو مربع حوار "فتح الملف" للمعلومات المخزنة في خوادم Google، بما في ذلك Google Drive وبحث الصور من Google وبحث الفيديو من Google والمزيد.

كما هو موضح في المثال أدناه، يمكن استخدام واجهة برمجة تطبيقات JavaScript من جهة العميل لـ Picker في خدمة HTML لإنشاء مربع حوار مخصص يتيح للمستخدمين اختيار الملفات الموجودة أو تحميل ملفات جديدة، ثم تمرير هذا التحديد مرة أخرى إلى النص البرمجي الخاص بك للاستخدام مرة أخرى.

لتمكين Picker والحصول على مفتاح واجهة برمجة التطبيقات، اتبع هذه الإرشادات:

  1. تأكَّد من أنّ مشروع النص البرمجي يستخدم مشروع Google Cloud Platform عادي.
  2. فعِّل Google Picker API في مشروعك على Google Cloud.
  3. عندما لا يزال مشروعك على Google Cloud مفتوحًا، اختَر واجهات برمجة التطبيقات والخدمات، ثم انقر على بيانات الاعتماد.
  4. انقر على إنشاء بيانات اعتماد > مفتاح واجهة برمجة التطبيقات. يؤدي هذا الإجراء إلى إنشاء المفتاح، ولكن يجب تعديل المفتاح لإضافة قيود التطبيق وقيود واجهة برمجة التطبيقات إلى المفتاح.
  5. في مربّع حوار مفتاح واجهة برمجة التطبيقات، انقر على إغلاق.
  6. بجانب مفتاح واجهة برمجة التطبيقات الذي أنشأته، انقر على رمز المزيد رمز المزيد> تعديل مفتاح واجهة برمجة التطبيقات.
  7. ضمن قيود التطبيقات، أكمل الخطوات التالية:

    1. اختر مُحيلات HTTP (المواقع الإلكترونية).
    2. ضمن القيود على المواقع الإلكترونية، انقر على إضافة عنصر.
    3. انقر على المُحيل وأدخِل *.google.com.
    4. أضِف عنصرًا آخر وأدخِل *.googleusercontent.com كمُحيل.
    5. انقر على تم.
  8. ضمن قيود واجهة برمجة التطبيقات، أكمِل الخطوات التالية:

    1. اختَر تقييد المفتاح.
    2. في القسم اختيار واجهات برمجة التطبيقات، اختَر Google Picker API وانقر على حسنًا.

      ملاحظة: لا تظهر Google Picker API إلا إذا فعّلتها، لأنّ القائمة لا تعرض سوى واجهات برمجة التطبيقات التي تم تفعيلها للمشروع على السحابة الإلكترونية.

  9. ضمن مفتاح واجهة برمجة التطبيقات، انقر على رمز النسخ إلى الحافظة رمز النسخ إلى الحافظة.

  10. في أسفل الشاشة، انقر على حفظ.

code.gs

picker/code.gs
/**
 * Creates a custom menu in Google Sheets when the spreadsheet opens.
 */
function onOpen() {
  try {
    SpreadsheetApp.getUi().createMenu('Picker')
        .addItem('Start', 'showPicker')
        .addToUi();
  } catch (e) {
    // TODO (Developer) - Handle exception
    console.log('Failed with error: %s', e.error);
  }
}

/**
 * Displays an HTML-service dialog in Google Sheets that contains client-side
 * JavaScript code for the Google Picker API.
 */
function showPicker() {
  try {
    const html = HtmlService.createHtmlOutputFromFile('dialog.html')
        .setWidth(600)
        .setHeight(425)
        .setSandboxMode(HtmlService.SandboxMode.IFRAME);
    SpreadsheetApp.getUi().showModalDialog(html, 'Select a file');
  } catch (e) {
    // TODO (Developer) - Handle exception
    console.log('Failed with error: %s', e.error);
  }
}

/**
 * Gets the user's OAuth 2.0 access token so that it can be passed to Picker.
 * This technique keeps Picker from needing to show its own authorization
 * dialog, but is only possible if the OAuth scope that Picker needs is
 * available in Apps Script. In this case, the function includes an unused call
 * to a DriveApp method to ensure that Apps Script requests access to all files
 * in the user's Drive.
 *
 * @return {string} The user's OAuth 2.0 access token.
 */
function getOAuthToken() {
  try {
    DriveApp.getRootFolder();
    return ScriptApp.getOAuthToken();
  } catch (e) {
    // TODO (Developer) - Handle exception
    console.log('Failed with error: %s', e.error);
  }
}

dialog.html

picker/dialog.html
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css">
  <script>
    // IMPORTANT: Replace the value for DEVELOPER_KEY with the API key obtained
    // from the Google Developers Console.
    var DEVELOPER_KEY = 'ABC123 ... ';
    var DIALOG_DIMENSIONS = {width: 600, height: 425};
    var pickerApiLoaded = false;

    /**
     * Loads the Google Picker API.
     */
    function onApiLoad() {
      gapi.load('picker', {'callback': function() {
        pickerApiLoaded = true;
      }});
     }

    /**
     * Gets the user's OAuth 2.0 access token from the server-side script so that
     * it can be passed to Picker. This technique keeps Picker from needing to
     * show its own authorization dialog, but is only possible if the OAuth scope
     * that Picker needs is available in Apps Script. Otherwise, your Picker code
     * will need to declare its own OAuth scopes.
     */
    function getOAuthToken() {
      google.script.run.withSuccessHandler(createPicker)
          .withFailureHandler(showError).getOAuthToken();
    }

    /**
     * Creates a Picker that can access the user's spreadsheets. This function
     * uses advanced options to hide the Picker's left navigation panel and
     * default title bar.
     *
     * @param {string} token An OAuth 2.0 access token that lets Picker access the
     *     file type specified in the addView call.
     */
    function createPicker(token) {
      if (pickerApiLoaded && token) {
        var picker = new google.picker.PickerBuilder()
            // Instruct Picker to display only spreadsheets in Drive. For other
            // views, see https://developers.google.com/picker/docs/#otherviews
            .addView(google.picker.ViewId.SPREADSHEETS)
            // Hide the navigation panel so that Picker fills more of the dialog.
            .enableFeature(google.picker.Feature.NAV_HIDDEN)
            // Hide the title bar since an Apps Script dialog already has a title.
            .hideTitleBar()
            .setOAuthToken(token)
            .setDeveloperKey(DEVELOPER_KEY)
            .setCallback(pickerCallback)
            .setOrigin(google.script.host.origin)
            // Instruct Picker to fill the dialog, minus 2 pixels for the border.
            .setSize(DIALOG_DIMENSIONS.width - 2,
                DIALOG_DIMENSIONS.height - 2)
            .build();
        picker.setVisible(true);
      } else {
        showError('Unable to load the file picker.');
      }
    }

    /**
     * A callback function that extracts the chosen document's metadata from the
     * response object. For details on the response object, see
     * https://developers.google.com/picker/docs/result
     *
     * @param {object} data The response object.
     */
    function pickerCallback(data) {
      var action = data[google.picker.Response.ACTION];
      if (action == google.picker.Action.PICKED) {
        var doc = data[google.picker.Response.DOCUMENTS][0];
        var id = doc[google.picker.Document.ID];
        var url = doc[google.picker.Document.URL];
        var title = doc[google.picker.Document.NAME];
        document.getElementById('result').innerHTML =
            '<b>You chose:</b><br>Name: <a href="' + url + '">' + title +
            '</a><br>ID: ' + id;
      } else if (action == google.picker.Action.CANCEL) {
        document.getElementById('result').innerHTML = 'Picker canceled.';
      }
    }

    /**
     * Displays an error message within the #result element.
     *
     * @param {string} message The error message to display.
     */
    function showError(message) {
      document.getElementById('result').innerHTML = 'Error: ' + message;
    }
  </script>
</head>
<body>
  <div>
    <button onclick="getOAuthToken()">Select a file</button>
    <p id="result"></p>
  </div>
  <script src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
</body>
</html>