google.script.run هي واجهة برمجة تطبيقات JavaScript غير متزامنة من جهة العميل تتيح لصفحات خدمة HTML استدعاء وظائف "برمجة تطبيقات Google" من جهة الخادم. يعرض المثال التالي الوظيفة الأساسية لـ google.script.run، وهي استدعاء وظيفة على الخادم من JavaScript من جهة العميل.
Code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index');
}
function doSomething() {
Logger.log('I was called!');
}Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
google.script.run.doSomething();
</script>
</head>
</html>إذا نشرت هذا النص البرمجي كتطبيق ويب وانتقلت إلى عنوان URL الخاص به، لن يظهر لك أي شيء، ولكن إذا اطّلعت على السجلات، ستلاحظ أنّه تم استدعاء وظيفة الخادم doSomething.
تكون عمليات الاستدعاء من جهة العميل للوظائف من جهة الخادم غير متزامنة: بعد أن يطلب المتصفّح من الخادم تشغيل الوظيفة doSomething، ينتقل المتصفّح فورًا إلى السطر التالي من الرمز بدون انتظار استجابة. هذا يعني أنّه قد لا يتم تنفيذ استدعاءات وظيفة الخادم بالترتيب الذي تتوقّعه. إذا أجريت استدعاءَين لوظيفتَين في الوقت نفسه، لا توجد طريقة لمعرفة الوظيفة التي يتم تشغيلها أولاً؛ وقد تختلف النتيجة في كل مرة يتم فيها تحميل الصفحة. في هذه الحالة،
تساعد معالِجات النجاح ومعالِجات الإخفاق
في التحكّم في تدفق الرمز.
تسمح واجهة برمجة التطبيقات google.script.run بإجراء 10 عمليات استدعاء متزامنة لوظائف الخادم. إذا أجريت عملية الاستدعاء الحادية عشرة بينما لا تزال 10 عمليات قيد التشغيل، يتم تأخير وظيفة الخادم إلى أن يتم تحرير إحدى العمليات العشر. في الواقع، نادرًا ما تحتاج إلى التفكير في هذا القيد، خاصةً أنّ معظم المتصفّحات تحدّ بالفعل من عدد الطلبات المتزامنة إلى الخادم نفسه بعدد أقل من 10.
في Firefox، على سبيل المثال، الحدّ الأقصى هو 6. تؤخّر معظم المتصفّحات بالمثل طلبات الخادم الزائدة إلى أن يكتمل أحد الطلبات الحالية.
المَعلمات والقيم المعروضة
يمكنك استدعاء وظيفة خادم باستخدام مَعلمات من جهة العميل. وبالمثل، يمكن لوظيفة الخادم عرض قيمة للعميل كمَعلمة يتم تمريرها إلى معالِج النجاح.
المَعلمات والقيم المعروضة القانونية هي أنواع JavaScript الأساسية، مثل Number أو Boolean أو String أو null، بالإضافة إلى كائنات JavaScript والمصفوفات التي تتألف من أنواع أساسية وكائنات ومصفوفات. يُعدّ عنصر form ضِمن الصفحة أيضًا مَعلمة قانونية، ولكن يجب أن يكون المَعلمة الوحيدة للوظيفة، ولا يُسمح باستخدامه كقيمة معروضة. تفشل الطلبات إذا حاولت تمرير Date أو Function أو عنصر DOM بخلاف form أو أي نوع آخر محظور، بما في ذلك الأنواع المحظورة داخل الكائنات أو المصفوفات. تفشل أيضًا الكائنات التي تنشئ مراجع دائرية، وتصبح الحقول غير المحدّدة ضِمن المصفوفات null.
يُرجى العِلم أنّ الكائن الذي يتم تمريره إلى الخادم يصبح نسخة من الكائن الأصلي. إذا تلقّت وظيفة الخادم كائنًا وغيّرت خصائصه، لا تتأثر الخصائص على العميل.
معالِجات النجاح
بما أنّ استدعاءات google.script.run غير متزامنة، ينتقل الرمز من جهة العميل إلى السطر التالي بدون انتظار استجابة. لتحديد دالة معاودة الاتصال التي يتم تشغيلها عندما يستجيب الخادم، استخدِم
withSuccessHandler(function).
إذا عرضت وظيفة الخادم قيمة، تمرِّر واجهة برمجة التطبيقات هذه القيمة إلى دالّة رد الاتصال كمَعلمة.
يعرض المثال التالي تنبيهًا في المتصفّح عندما يستجيب الخادم. تتطلب عينة التعليمات البرمجية هذه الحصول على إذن لأنّ وظيفة جهة الخادم تصل إلى حساب Gmail. لإعطاء الإذن للنص البرمجي، شغِّل الوظيفة getUnreadEmails يدويًا من أداة تعديل النصوص البرمجية مرة واحدة قبل تحميل الصفحة. بدلاً من ذلك، عند
نشر تطبيق الويب ليتم
تنفيذه باسم "المستخدم الذي يصل إلى تطبيق الويب"، ستُطلب منك إعطاء الإذن
عند تحميل التطبيق.
Code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index');
}
function getUnreadEmails() {
return GmailApp.getInboxUnreadCount();
}Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
function onSuccess(numUnread) {
var div = document.getElementById('output');
div.innerHTML = 'You have ' + numUnread
+ ' unread messages in your Gmail inbox.';
}
google.script.run.withSuccessHandler(onSuccess)
.getUnreadEmails();
</script>
</head>
<body>
<div id="output"></div>
</body>
</html>معالِجات الإخفاق
إذا تعذّر على الخادم الاستجابة أو عرض خطأ،
withFailureHandler(function)
يتيح لك تحديد معالِج إخفاق ليتم تشغيله بدلاً من معالِج النجاح.
إذا حدث خطأ، تمرِّر واجهة برمجة التطبيقات الـ
Error
كائن كحجة إلى معالِج الإخفاق.
إذا لم تحدّد معالِج إخفاق، يتم تلقائيًا تسجيل حالات الإخفاق في وحدة تحكّم JavaScript. لتجاوز ذلك، استخدِم withFailureHandler(null) أو قدِّم معالِج إخفاق لا يفعل أي شيء.
إنّ بنية معالِجات الإخفاق مطابقة تقريبًا لمعالِجات النجاح، كما يوضّح هذا المثال.
Code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index');
}
function getUnreadEmails() {
// 'got' instead of 'get' throws an error.
return GmailApp.gotInboxUnreadCount();
}Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
function onFailure(error) {
var div = document.getElementById('output');
div.innerHTML = "ERROR: " + error.message;
}
google.script.run.withFailureHandler(onFailure)
.getUnreadEmails();
</script>
</head>
<body>
<div id="output"></div>
</body>
</html>كائنات المستخدمين
لإعادة استخدام معالِج النجاح أو الإخفاق نفسه لعدة عمليات استدعاء للخادم، استخدِم
withUserObject(object)
لتحديد كائن يتم تمريره إلى المعالِج كمَعلمة ثانية.
يتيح لك "كائن المستخدم" هذا، الذي يجب عدم الخلط بينه وبين الـ
User، الاستجابة للـ
سياق الذي اتصل فيه العميل بالخادم. بما أنّه لا يتم إرسال كائنات المستخدمين إلى الخادم، يمكن أن تكون هذه الكائنات أي شيء تقريبًا، بما في ذلك الوظائف وعناصر DOM، بدون القيود المفروضة على المَعلمات والقيم المعروضة لاستدعاءات الخادم. لا يمكن أن تكون كائنات المستخدمين كائنات تم إنشاؤها باستخدام عامل التشغيل new.
في هذا المثال، يؤدي النقر على أي من الزرّين إلى تعديل هذا الزر بقيمة من الخادم مع ترك الزر الآخر بدون تغيير، على الرغم من أنّهما يشتركان في معالِج نجاح واحد. ضِمن معالِج onclick، تشير الكلمة الرئيسية this إلى button نفسه.
Code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index');
}
function getEmail() {
return Session.getActiveUser().getEmail();
}Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
function updateButton(email, button) {
button.value = 'Clicked by ' + email;
}
</script>
</head>
<body>
<input type="button" value="Not Clicked"
onclick="google.script.run
.withSuccessHandler(updateButton)
.withUserObject(this)
.getEmail()" />
<input type="button" value="Not Clicked"
onclick="google.script.run
.withSuccessHandler(updateButton)
.withUserObject(this)
.getEmail()" />
</body>
</html>النماذج
إذا استدعيت وظيفة خادم باستخدام عنصر form كمَعلمة، يصبح النموذج كائنًا واحدًا بأسماء الحقول كمفاتيح وقيم الحقول كقيم. يتم تحويل جميع القيم إلى سلاسل، باستثناء محتوى حقول إدخال الملفات، التي تصبح كائنات Blob.
يعالج هذا المثال نموذجًا، بما في ذلك حقل إدخال ملف، بدون إعادة تحميل الصفحة؛ ويحمِّل الملف إلى Google Drive ثم يطبع عنوان URL للملف في الصفحة من جهة العميل. ضِمن معالِج onsubmit، تشير الكلمة الرئيسية this إلى النموذج نفسه. يُرجى العِلم أنّه عند تحميل جميع النماذج في الصفحة، يتم إيقاف إجراء الإرسال التلقائي باستخدام preventFormSubmit. يمنع ذلك الصفحة من إعادة التوجيه إلى عنوان URL غير دقيق في حال حدوث استثناء.
Code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index');
}
function processForm(formObject) {
var formBlob = formObject.myFile;
var driveFile = DriveApp.createFile(formBlob);
return driveFile.getUrl();
}Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
// Prevent forms from submitting.
function preventFormSubmit() {
var forms = document.querySelectorAll('form');
for (var i = 0; i < forms.length; i++) {
forms[i].addEventListener('submit', function(event) {
event.preventDefault();
});
}
}
window.addEventListener('load', preventFormSubmit);
function handleFormSubmit(formObject) {
google.script.run.withSuccessHandler(updateUrl).processForm(formObject);
}
function updateUrl(url) {
var div = document.getElementById('output');
div.innerHTML = '<a href="' + url + '">Got it!</a>';
}
</script>
</head>
<body>
<form id="myForm" onsubmit="handleFormSubmit(this)">
<input name="myFile" type="file" />
<input type="submit" value="Submit" />
</form>
<div id="output"></div>
</body>
</html>مشغِّلات النصوص البرمجية
يمكنك اعتبار google.script.run أداة إنشاء "مشغِّل نصوص برمجية". إذا أضفت معالِج نجاح أو معالِج إخفاق أو كائن مستخدم إلى مشغِّل نصوص برمجية، لن تغيِّر المشغِّل الحالي، بل ستحصل على مشغِّل نصوص برمجية جديد بسلوك جديد.
يمكنك استخدام أي مجموعة وأي ترتيب من withSuccessHandler وwithFailureHandler وwithUserObject. يمكنك أيضًا استدعاء أي من وظائف التعديل على مشغِّل نصوص برمجية تم ضبط قيمة له من قبل. تتجاوز القيمة الجديدة القيمة السابقة.
يضبط هذا المثال معالِج إخفاق شائعًا لجميع استدعاءات الخادم الثلاثة، ولكن معالِجَي نجاح منفصلَين:
var myRunner = google.script.run.withFailureHandler(onFailure);
var myRunner1 = myRunner.withSuccessHandler(onSuccess);
var myRunner2 = myRunner.withSuccessHandler(onDifferentSuccess);
myRunner1.doSomething();
myRunner1.doSomethingElse();
myRunner2.doSomething();
الوظائف الخاصة
تُعدّ وظائف الخادم التي تنتهي أسماؤها بشرطة سفلية خاصة.
لا يمكن استدعاء هذه الوظائف باستخدام google.script ولا يتم إرسال أسمائها مطلقًا إلى العميل. يمكنك استخدامها لإخفاء تفاصيل التنفيذ التي يجب أن تظل سرية على الخادم. google.script لا يمكن أيضًا الاطّلاع على
الوظائف ضِمن المكتبات أو الوظائف غير
المُعلَنة على المستوى الأعلى من النص البرمجي.
في هذا المثال، تتوفّر الوظيفة getBankBalance في رمز العميل، ويمكن للمستخدم الذي يفحص رمز المصدر اكتشاف اسمها حتى إذا لم تستدعِها. ومع ذلك، فإنّ الوظيفتَين deepSecret_ وobj.objectMethod غير مرئيتَين تمامًا للعميل.
Code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index');
}
function getBankBalance() {
var email = Session.getActiveUser().getEmail()
return deepSecret_(email);
}
function deepSecret_(email) {
// Do some secret calculations
return email + ' has $1,000,000 in the bank.';
}
var obj = {
objectMethod: function() {
// More secret calculations
}
};Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
function onSuccess(balance) {
var div = document.getElementById('output');
div.innerHTML = balance;
}
google.script.run.withSuccessHandler(onSuccess)
.getBankBalance();
</script>
</head>
<body>
<div id="output">No result yet...</div>
</body>
</html>تغيير حجم مربّعات الحوار في تطبيقات Google Workspace
يمكن تغيير حجم مربّعات الحوار المخصّصة في "مستندات Google" و
"جداول بيانات Google" أو "نماذج Google" عن طريق استدعاء
google.script.host الطريقتَين
setWidth(width) أو
setHeight(height) في
الرمز من جهة العميل. (لضبط الحجم الأولي لمربّع حوار، استخدِم HtmlOutput
الطريقتَين
setWidth(width)
و
setHeight(height).)
يُرجى العِلم أنّ مربّعات الحوار لا تتم إعادة توسيطها في النافذة الرئيسية عند تغيير حجمها، ولا يمكن تغيير حجم الأشرطة الجانبية.
إغلاق مربّعات الحوار والأشرطة الجانبية في Google Workspace
إذا كنت تستخدم خدمة HTML لعرض مربّع حوار أو
شريط جانبي في "مستندات Google" أو "جداول بيانات Google" أو
"نماذج Google"، لا يمكنك إغلاق الواجهة عن طريق استدعاء
window.close. بدلاً من ذلك، عليك استدعاء
google.script.host.close.
للاطّلاع على مثال، راجِع القسم حول عرض HTML كواجهة مستخدم في Google Workspace
user
interface.
نقل تركيز المتصفّح في Google Workspace
لتبديل التركيز في متصفّح المستخدم من مربّع حوار أو شريط جانبي إلى أداة تعديل
"مستندات Google" أو "جداول بيانات Google" أو "نماذج Google"، استخدِم
الطريقة
google.script.host.editor.focus.
تكون هذه الطريقة مفيدة بشكل خاص عند استخدامها مع طريقتَي خدمة المستندات Document
service Document.setCursor(position)
و
Document.setSelection(range).