التعامل مع علامات التبويب

تتيح لك "برمجة تطبيقات Google" في "مستندات Google" الوصول إلى المحتوى من أي علامة تبويب في المستند.

ما هي علامات التبويب؟

تتضمّن "مستندات Google" طبقة تنظيمية تُعرف باسم علامات التبويب. تتيح "مستندات Google" للمستخدمين إنشاء علامة تبويب واحدة أو أكثر ضمن مستند واحد، على غرار علامات التبويب المتوفّرة حاليًا في "جداول بيانات Google". يحتوي كل تبويب على عنوان ومعرّف (يتم إلحاقهما بعنوان URL). يمكن أن تحتوي علامة التبويب أيضًا على علامات تبويب فرعية، وهي علامات تبويب متداخلة ضمن علامة تبويب أخرى.

علامات التبويب الخاصة بإمكانية الوصول

يمكن الوصول إلى خصائص علامة التبويب ومحتواها باستخدام Document.getTabs()، التي تعرض قائمة Tab. تقدّم الأقسام اللاحقة نظرة عامة موجزة على فئة Tab، كما يوفّر مستند فئة Tab معلومات أكثر تفصيلاً.

خصائص علامة التبويب

يمكن استرداد خصائص علامة التبويب باستخدام طرق مثل Tab.getId() و Tab.getTitle().

محتوى علامة التبويب

يمكن استرداد محتوى المستند ضمن كل علامة تبويب باستخدام Tab.asDocumentTab(). يوضّح قسم التغييرات على بنية فئة المستند كيفية استخدام ذلك.

التسلسل الهرمي لعلامات التبويب

يتم عرض علامات تبويب العناصر التابعة في "برمجة تطبيقات Google" من خلال Tab.getChildTabs(). يتطلّب الوصول إلى المحتوى من جميع علامات التبويب التنقّل في "شجرة" علامات التبويب الثانوية. على سبيل المثال، لنفترض أنّ لديك مستندًا يتضمّن بنية علامات تبويب على النحو التالي:

واجهة مستخدم قائمة علامات التبويب التي تحتوي على ثلاث علامات تبويب من المستوى الأعلى، بعضها يحتوي على علامات تبويب فرعية

للوصول إلى علامة التبويب 3.1.2، يمكنك اتّباع الخطوات التالية:

// Print the ID of Tab 3.1.2.
const doc = DocumentApp.getActiveDocument();
const tab = doc.getTabs()[2].getChildTabs()[0].getChildTabs()[1];
console.log(tab.getId());

راجِع نماذج مقاطع الرموز في الأقسام اللاحقة التي توفّر نموذج رمز لتكرار جميع علامات التبويب في مستند.

طُرق أخرى لاسترداد علامات التبويب

هناك طريقتان أخريان لاسترداد علامات التبويب:

  • Document.getTab(tabId): تعرض علامة التبويب التي تحمل رقم التعريف المحدّد.
  • Document.getActiveTab(): تعرض هذه السمة علامة التبويب النشطة للمستخدم. تعمل هذه الطريقة فقط في البرامج النصية المرتبطة بمستند. توضّح الأقسام اللاحقة هذه العملية بمزيد من التفصيل.

التغييرات في بنية فئة المستند

في السابق، لم تكن المستندات تتضمّن مفهوم علامات التبويب، لذا كانت "فئة المستند" تعرض طرقًا للوصول إلى محتوى النص في المستند وتعديله مباشرةً. تندرج الطرق التالية ضمن هذه الفئة:

مع التسلسل الهرمي الإضافي للعلامات، لم تعُد هذه الطرق تمثّل دلاليًا المحتوى النصي من جميع علامات التبويب في المستند. سيتم الآن تمثيل المحتوى النصي في طبقة مختلفة، ويمكن الوصول إلى جميع طرق النص المذكورة أعلاه من خلال DocumentTab.

ستتمكّن هذه الطرق الحالية في الفئة Document من الوصول إلى المحتوى أو تعديله من علامة التبويب النشطة (في النصوص البرمجية المرتبطة بمستند معيّن) أو علامة التبويب الأولى (في حال عدم توفّر علامة تبويب نشطة).

الوصول إلى محتوى نصي ضمن علامة تبويب معيّنة

بدلاً من استخدام طرق النص من Document، يُنصح باستخدام الطرق المتاحة من الفئة DocumentTab (المتاحة من خلال الطريقة Tab.asDocumentTab()). على سبيل المثال:

// Print the text from the body of the active tab.
const doc = DocumentApp.getActiveDocument();
const documentTab = doc.getActiveTab().asDocumentTab();
const body = documentTab.getBody();
console.log(body.getText());

التغييرات في اختيار المستخدم

طُرق تحديد النص

يوفر صف Document دوال جلب وتعيين لإدارة موضع النص الذي يحدده المستخدم ضمن المستند النشط. تعمل هذه الطرق ضمن سياق علامة التبويب النشطة للمستخدم الذي يشغّل البرنامج النصي.

  • Document.getCursor(): تعرض هذه السمة موضع مؤشر المستخدم في علامة التبويب النشطة.
  • Document.getSelection(): تعرض هذه الدالة نطاق التحديد الخاص بالمستخدم في علامة التبويب النشطة.
  • Document.setCursor(position): يضبط موضع مؤشر المستخدم في المستند النشط. إذا كان الموضع في علامة تبويب غير نشطة، سيتم أيضًا التبديل إلى علامة التبويب النشطة المرتبطة بهذا الموضع.
  • Document.setSelection(range): تضبط هذه السمة نطاق التحديد الخاص بالمستخدم في المستند النشط. إذا كان النطاق في علامة تبويب غير نشطة، سيتم أيضًا تبديل علامة التبويب النشطة للمستخدم إلى علامة التبويب المرتبطة بهذا النطاق.

طُرق اختيار علامات التبويب وحالات استخدامها

مع طرح علامات التبويب، قد يكون من المفيد الحصول على علامة التبويب النشطة للمستخدم الذي يشغّل النص البرمجي وتحديدها. يمكن إجراء ذلك باستخدام الطرق التالية:

  • استبدِل Document.getActiveTab() بـ Document.getActiveTab(): تعرض هذه السمة Tab النشط للمستخدم في المستند النشط.
  • Document.setActiveTab(tabId): يضبط هذا العنصر Tab الذي اختاره المستخدم في المستند الحالي على علامة التبويب التي تحمل المعرّف المحدّد.

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

يمكن تغيير علامة التبويب النشطة للمستخدم بشكل صريح باستخدام Document.setActiveTab(tabId). بدلاً من ذلك، سيؤدي استدعاء Document.setCursor(position) أو Document.setSelection(range) باستخدام Position أو Range من علامة تبويب غير نشطة إلى تنشيط علامة التبويب هذه.

إذا كان السلوك المقصود للنص البرمجي هو استخدام علامة التبويب النشطة للمستخدم بدون تغييرها، لن تكون السمة Document.setActiveTab(tabId) ضرورية. سيعمل كل من الطريقتَين Document.getCursor() وDocument.getSelection() على علامة التبويب النشطة، استنادًا إلى علامة التبويب التي ينفّذ المستخدم النص البرمجي منها.

يُرجى العِلم أنّ المستند لا يتيح تحديد علامات تبويب أو مواضع أو نطاقات متعدّدة في علامات تبويب مختلفة. لذلك، سيؤدي استخدام Document.setActiveTab(tabId) إلى محو موضع المؤشر السابق أو نطاق التحديد.

طُرق تحديد الموضع والنطاق لعلامة تبويب معيّنة

إنّ علامة التبويب المحدّدة هي التي تمنح معنى لمفهومَي اختيار النص Position وRange. بعبارة أخرى، لا يكون موضع المؤشر أو نطاق التحديد مفيدًا إلا إذا كان النص البرمجي يعرف علامة التبويب المحدّدة التي يقع فيها الموضع أو النطاق.

ويتم تحقيق ذلك باستخدام الطريقتَين DocumentTab.newPosition(element, offset) و DocumentTab.newRange()، اللتَين تنشئان كائن Position أو Range يستهدفان DocumentTab المحدّد الذي يتم استدعاء الطريقة منه. في المقابل، Document.newPosition(element, offset) وDocument.newRange() ستنشئان Position أو Range يستهدفان علامة التبويب النشطة (أو علامة التبويب الأولى، إذا لم يكن النص البرمجي مرتبطًا).

راجِع أقسام الرموز النموذجية في الأقسام اللاحقة التي توفّر رموزًا نموذجية للتعامل مع عمليات التحديد.

أنماط الاستخدام الشائعة لعلامات التبويب

توضّح نماذج الرموز التالية طرقًا مختلفة للتفاعل مع علامات التبويب.

قراءة محتوى علامة التبويب من جميع علامات التبويب في المستند

يمكن نقل الرمز الحالي الذي كان ينفّذ هذه العملية قبل توفّر ميزة علامات التبويب إلى علامات التبويب من خلال الانتقال إلى شجرة علامات التبويب واستدعاء طرق الحصول على البيانات من Tab وDocumentTab بدلاً من Document. يوضّح نموذج الرمز الجزئي التالي كيفية طباعة كل محتوى النص من كل علامة تبويب في مستند. يمكن تكييف رمز التنقّل هذا بين علامات التبويب مع العديد من حالات الاستخدام الأخرى التي لا تهتم بالبنية الفعلية لعلامات التبويب.

/** Logs all text contents from all tabs in the active document. */
function logAllText() {
  // Generate a list of all the tabs in the document, including any
  // nested child tabs. DocumentApp.openById('abc123456') can also
  // be used instead of DocumentApp.getActiveDocument().
  const doc = DocumentApp.getActiveDocument();
  const allTabs = getAllTabs(doc);

  // Log the content from each tab in the document.
  for (const tab of allTabs) {
    // Get the DocumentTab from the generic Tab object.
    const documentTab = tab.asDocumentTab();
    // Get the body from the given DocumentTab.
    const body = documentTab.getBody();
    // Get the body text and log it to the console.
    console.log(body.getText());
  }
}

/**
 * Returns a flat list of all tabs in the document, in the order
 * they would appear in the UI (i.e. top-down ordering). Includes
 * all child tabs.
 */
function getAllTabs(doc) {
  const allTabs = [];
  // Iterate over all tabs and recursively add any child tabs to
  // generate a flat list of Tabs.
  for (const tab of doc.getTabs()) {
    addCurrentAndChildTabs(tab, allTabs);
  }
  return allTabs;
}

/**
 * Adds the provided tab to the list of all tabs, and recurses
 * through and adds all child tabs.
 */
function addCurrentAndChildTabs(tab, allTabs) {
  allTabs.push(tab);
  for (const childTab of tab.getChildTabs()) {
    addCurrentAndChildTabs(childTab, allTabs);
  }
}

قراءة محتوى علامة التبويب من علامة التبويب الأولى في المستند

وهذا يشبه قراءة جميع علامات التبويب.

/** 
 * Logs all text contents from the first tab in the active 
 * document. 
 */
function logAllText() {
  // Generate a list of all the tabs in the document, including any
  // nested child tabs.
  const doc = DocumentApp.getActiveDocument();
  const allTabs = getAllTabs(doc);

  // Log the content from the first tab in the document.
  const firstTab = allTabs[0];
  // Get the DocumentTab from the generic Tab object.
  const documentTab = firstTab.asDocumentTab();
  // Get the body from the DocumentTab.
  const body = documentTab.getBody();
  // Get the body text and log it to the console.
  console.log(body.getText());
}

تعديل محتوى علامة التبويب في علامة التبويب الأولى

يوضّح نموذج الرمز الجزئي التالي كيفية استهداف علامة تبويب معيّنة عند إجراء تعديلات.

/** Inserts text into the first tab of the active document. */
function insertTextInFirstTab() {
  // Get the first tab's body.
  const doc = DocumentApp.getActiveDocument();
  const firstTab = doc.getTabs()[0];
  const firstDocumentTab = firstTab.asDocumentTab();
  const firstTabBody = firstDocumentTab.getBody();

  // Append a paragraph and a page break to the first tab's body
  // section.
  firstTabBody.appendParagraph("A paragraph.");
  firstTabBody.appendPageBreak();
}

تعديل محتوى علامة التبويب النشطة أو المحدّدة

يوضّح نموذج الرمز البرمجي الجزئي التالي كيفية استهداف علامة التبويب النشطة عند إجراء التعديلات.

/**
 * Inserts text into the active/selected tab of the active
 * document.
 */
function insertTextInActiveTab() {
  // Get the active/selected tab's body.
  const doc = DocumentApp.getActiveDocument();
  const activeTab = doc.getActiveTab();
  const activeDocumentTab = activeTab.asDocumentTab();
  const activeTabBody = activeDocumentTab.getBody();

  // Append a paragraph and a page break to the active tab's body
  // section.
  activeTabBody.appendParagraph("A paragraph.");
  activeTabBody.appendPageBreak();
}

ضبط موضع المؤشر أو نطاق التحديد في علامة التبويب النشطة

يوضّح نموذج الرمز الجزئي التالي كيفية تعديل موضع المؤشر أو نطاق التحديد ضمن علامة التبويب النشطة للمستخدم. لا ينطبق ذلك إلا على البرامج النصية المرتبطة.

/**
 * Changes the user's selection to select all tables within the tab
 * with the provided ID.
 */
function selectAllTables(tabId) {
  const doc = DocumentApp.getActiveDocument();
  const tab = doc.getTab(tabId);
  const documentTab = tab.asDocumentTab();

  // Build a range that encompasses all tables within the specified
  // tab.
  const rangeBuilder = documentTab.newRange();
  const tables = documentTab.getBody().getTables();
  for (let i = 0; i < tables.length; i++) {
    rangeBuilder.addElement(tables[i]);
  }
  // Set the document's selection to the tables within the specified
  // tab. Note that this actually switches the user's active tab as
  // well.
  doc.setSelection(rangeBuilder.build());
}

ضبط علامة التبويب النشطة أو المحدّدة

يوضّح نموذج الرمز الجزئي التالي كيفية تغيير علامة التبويب النشطة للمستخدم. لا ينطبق ذلك إلا على النصوص البرمجية المرتبطة.

/**
 * Changes the user's selected tab to the tab immediately following
 * the currently selected one. Handles child tabs.
 *
 * 

Only changes the selection if there is a tab following the * currently selected one. */ function selectNextTab() { const doc = DocumentApp.getActiveDocument(); const allTabs = getAllTabs(doc); const activeTab = doc.getActiveTab(); // Find the index of the currently active tab. let activeTabIndex = -1; for (let i = 0; i < allTabs.length; i++) { if (allTabs[i].getId() === activeTab.getId()) { activeTabIndex = i; } } // Update the user's selected tab if there is a valid next tab. const nextTabIndex = activeTabIndex + 1; if (nextTabIndex < allTabs.length) { doc.setActiveTab(allTabs[nextTabIndex].getId()); } }