حقول القائمة المنسدلة

يخزِّن الحقل المنسدلة سلسلة كنصّه وسلسلة كقيمة له. القيمة هي مفتاح محايد من حيث اللغة سيتم استخدامه للوصول إلى النص، ولن تتم ترجمته عند تبديل Blockly بين اللغات. النص هو سلسلة يمكن لشخص عادي قراءتها وسيتم عرضها على المستخدم.

عنصر يتضمّن التصنيف "قائمة منسدلة"، وحقل قائمة منسدلة تم اختيار "الأول" فيه،
والتصنيف "عنصر"

الكتلة نفسها مع القائمة المنسدلة مفتوحة تحتوي القائمة المنسدلة على العنصرَين "first"
و "second".

الكتلة نفسها بعد تصغيرها يحمل التصنيف "العنصر الأول في القائمة المنسدلة"
ويحوي حافة يسرى متعرّجة للإشارة إلى أنّه
مُدمَج.

الإنشاء

يأخذ مُنشئ القائمة المنسدلة مُنشئ قائمة وأداة التحقّق اختيارية. يتمتع أداة إنشاء القوائم بقدرٍ كبير من المرونة، ولكنها في الأساس مصفوفة من الخيارات، يحتوي كل خيار منها على جزء يسهل قراءته وسلسلة محايدة من حيث اللغة.

القوائم المنسدلة النصية البسيطة

فتح قائمة منسدلة تتضمّن خيارَين نصيَّين

JSON

{
  "type": "example_dropdown",
  "message0": "drop down: %1",
  "args0": [
    {
      "type": "field_dropdown",
      "name": "FIELDNAME",
      "options": [
        [ "first item", "ITEM1" ],
        [ "second item", "ITEM2" ]
      ]
    }
  ]
}

JavaScript

Blockly.Blocks['example_dropdown'] = {
  init: function() {
    this.appendDummyInput()
        .appendField('drop down:')
        .appendField(new Blockly.FieldDropdown([
            ['first item', 'ITEM1'],
            ['second item', 'ITEM2']
        ]), 'FIELDNAME');
  }
};

إنّ فصل المعلومات القابلة للقراءة عن المفتاح المحايد من حيث اللغة يسمح بحفظ إعدادات القائمة المنسدلة بين اللغات. على سبيل المثال، قد تحدّد النسخة الإنجليزية من أحد الكتل [['left', 'LEFT'], ['right', 'RIGHT]] بينما تحدّد النسخة الألمانية من الكتلة نفسها [['links', 'LEFT'], ['rechts', 'RIGHT]].

القوائم المنسدلة للصور

قد تكون الخيارات في القائمة المنسدلة صورًا أيضًا بدلاً من نص. يتم تحديد عناصر الصور باستخدام السمات src وwidth وheight وalt.

يُرجى العِلم أنّه على الرغم من أنّ القائمة المنسدلة يمكن أن تتضمّن مزيجًا من خيارات النصوص وخيارات الصور، فإنه لا يمكن أن يحتوي خيار فردي حاليًا على صورة ونص معًا.

حقل متداخل يحتوي على صور ونصوص

JSON

{
  "type": "image_dropdown",
  "message0": "flag %1",
  "args0": [
    {
      "type": "field_dropdown",
      "name": "FLAG",
      "options": [
        ["none", "NONE"],
        [{"src": "canada.png", "width": 50, "height": 25, "alt": "Canada"}, "CANADA"],
        [{"src": "usa.png", "width": 50, "height": 25, "alt": "USA"}, "USA"],
        [{"src": "mexico.png", "width": 50, "height": 25, "alt": "Mexico"}, "MEXICO"]
      ]
    }
  ]
}

JavaScript

Blockly.Blocks['image_dropdown'] = {
  init: function() {
    var input = this.appendDummyInput()
        .appendField('flag');
    var options = [
        ['none', 'NONE'],
        [{'src': 'canada.png', 'width': 50, 'height': 25, 'alt': 'Canada'}, 'CANADA'],
        [{'src': 'usa.png', 'width': 50, 'height': 25, 'alt': 'USA'}, 'USA'],
        [{'src': 'mexico.png', 'width': 50, 'height': 25, 'alt': 'Mexico'}, 'MEXICO']
    ];
    input.appendField(new Blockly.FieldDropdown(options), 'FLAG');
  }
};

القوائم المنسدلة الديناميكية

حقل قائمة منسدلة يتضمّن أيام الأسبوع

JSON

{
  "type": "dynamic_dropdown",
  "message0": "day %1",
  "args0": [
    {
      "type": "input_dummy",
      "name": "INPUT"
    }
  ],
  "extensions": ["dynamic_menu_extension"]
}
Blockly.Extensions.register('dynamic_menu_extension',
  function() {
    this.getInput('INPUT')
      .appendField(new Blockly.FieldDropdown(
        function() {
          var options = [];
          var now = Date.now();
          for(var i = 0; i < 7; i++) {
            var dateString = String(new Date(now)).substring(0, 3);
            options.push([dateString, dateString.toUpperCase()]);
            now += 24 * 60 * 60 * 1000;
          }
          return options;
        }), 'DAY');
  });

ويتم ذلك باستخدام إضافة ملف JSON.

JavaScript

Blockly.Blocks['dynamic_dropdown'] = {
  init: function() {
    var input = this.appendDummyInput()
      .appendField('day')
      .appendField(new Blockly.FieldDropdown(
        this.generateOptions), 'DAY');
  },

  generateOptions: function() {
    var options = [];
    var now = Date.now();
    for(var i = 0; i < 7; i++) {
      var dateString = String(new Date(now)).substring(0, 3);
      options.push([dateString, dateString.toUpperCase()]);
      now += 24 * 60 * 60 * 1000;
    }
    return options;
  }
};

يمكن أيضًا توفير قائمة منسدلة باستخدام دالة بدلاً من قائمة بالخيارات الثابتة، ما يسمح بجعل الخيارات ديناميكية. يجب أن تعرِض الدالة [human-readable-value, language-neutral-key] صفيفًا من الخيارات بالتنسيق نفسه [human-readable-value, language-neutral-key] للخيارات الثابتة. في كل مرة يتم فيها النقر على القائمة المنسدلة، يتم تنفيذ الدالة ويعاد احتساب الخيارات.

الفواصل

استخدِم السلسلة 'separator' لإضافة خط بين الخيارات في قائمة منسدلة.

حقل متداخل مع خط بين الخيارين الثاني والثالث

JSON

{
  "type": "separator_dropdown",
  "message0": "food %1",
  "args0": [
    {
      "type": "field_dropdown",
      "name": "FOOD",
      "options": [
        ["water", "WATER"],
        ["juice", "JUICE"],
        "separator",
        ["salad", "SALAD"],
        ["soup", "SOUP"],
      ]
    }
  ]
}

JavaScript

Blockly.Blocks["separator_dropdown"] = {
  init: function() {
    var input = this.appendDummyInput()
        .appendField("food1");
    var options = [
        ["water", "WATER"],
        ["juice", "JUICE"],
        "separator",
        ["salad", "SALAD"],
        ["soup", "SOUP"],
    ];
    input.appendField(new Blockly.FieldDropdown(options), "FOOD");
  }
};

نشر الحلقات على نحو متسلسِل

JSON

يظهر تنسيق JSON الخاص بحقل القائمة المنسدلة على النحو التالي:

{
  "fields": {
    "FIELDNAME": "LANGUAGE-NEUTRAL-KEY"
  }
}

حيث يكون FIELDNAME سلسلة تشير إلى حقل قائمة منسدلة، و القيمة هي القيمة التي سيتم تطبيقها على الحقل. يجب أن تكون القيمة مفتاح خيار غير متحيّز للغة.

XML

يظهر تنسيق XML الخاص بحقل القائمة المنسدلة على النحو التالي:

<field name="FIELDNAME">LANGUAGE-NEUTRAL-KEY</field>

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

التخصيص

يمكن استخدام السمة Blockly.FieldDropdown.ARROW_CHAR لتغيير حرف اليونيكود الذي يمثّل سهم القائمة المنسدلة.

حقل قائمة منسدلة مع سهم مخصّص

تكون السمة ARROW_CHAR تلقائيًا \u25BC (▼) على Android و\u25BE (▾) بخلاف ذلك.

هذا سمة عامة، لذا سيُعدّل جميع الحقول المنسدلة عند ضبطه.

يمكن استخدام السمة Blockly.FieldDropdown.MAX_MENU_HEIGHT_VH لتغيير الحد الأقصى للارتفاع في القائمة. ويتم تعريفه كنسبة مئوية من ارتفاع إطار العرض، ويكون إطار العرض هو النافذة.

تكون القيمة التلقائية لسمة MAX_MENU_HEIGHT_VH هي 0.45.

هذا سمة عامة، لذا ستُعدّل جميع الحقول المنسدلة عند ضبطها.

مطابقة البادئة/اللاحقة

إذا كانت جميع خيارات القائمة المنسدلة تتشارك كلمات بادئة و/أو لاحقة شائعة، يتم استبعاد هذه الكلمات تلقائيًا وإدراجها كنص ثابت. على سبيل المثال، إليك طريقتان لإنشاء الكتلة نفسها (هذه الأولى بدون مطابقة اللاحقة، والثانية مع):

بدون مطابقة اللاحقة:

JSON

{
  "type": "dropdown_no_matching",
  "message0": "hello %1",
  "args0": [
    {
      "type": "field_dropdown",
      "name": "MODE",
      "options": [
        ["world", "WORLD"],
        ["computer", "CPU"]
      ]
    }
  ]
}

JavaScript

Blockly.Blocks['dropdown_no_matching'] = {
  init: function() {
    var options = [
      ['world', 'WORLD'],
      ['computer', 'CPU']
    ];

    this.appendDummyInput()
        .appendField('hello')
        .appendField(new Blockly.FieldDropdown(options), 'MODE');
  }
};

باستخدام مطابقة اللاحقة:

JSON

{
  "type": "dropdown_with_matching",
  "message0": "%1",
  "args0": [
    {
      "type": "field_dropdown",
      "name": "MODE",
      "options": [
        ["hello world", "WORLD"],
        ["hello computer", "CPU"]
      ]
    }
  ]
}

JavaScript

Blockly.Blocks['dropdown_with_matching'] = {
  init: function() {
    var options = [
      ['hello world', 'WORLD'],
      ['hello computer', 'CPU']
    ];

    this.appendDummyInput()
        .appendField(new Blockly.FieldDropdown(options), 'MODE');
  }
};

حقل قائمة منسدلة يتضمّن

من مزايا هذا الأسلوب أنّه من الأسهل ترجمة القسم إلى لغات أخرى. يتضمّن الرمز السابق السلاسل 'hello' و'world' و 'computer'، في حين يتضمّن الرمز المعدَّل السلاسل 'hello world' و 'hello computer'. يجد المترجمون أنّ ترجمة العبارات أسهل بكثير من ترجمة الكلمات بشكل منفصل.

ومن المزايا الأخرى لهذا النهج أنّ ترتيب الكلمات يتغيّر غالبًا بين اللغات. تخيل لغة تستخدم 'world hello' و'computer hello'. سترصد خوارزمية مطابقة اللاحقة 'hello' الشائعة وتعرضها بعد القائمة المنسدلة.

ومع ذلك، قد يتعذّر أحيانًا مطابقة البادئة/اللاحقة. هناك بعض الحالات التي ينبغي فيها استخدام كلمتَين معًا دائمًا وعدم استبعاد البادئة. على سبيل المثال، يمكن القول إنّه يجب استبعاد 'drive' فقط من 'drive red car' و'drive red truck'، وليس 'drive red'. يمكن استخدام المساحة غير القابلة للانقطاع '\u00A0' في يونيكود بدلاً من المساحة العادية لإيقاف مطابقة البادئة/اللاحقة. وبالتالي، يمكن إصلاح المثال أعلاه باستخدام 'drive red\u00A0car' و'drive red\u00A0truck'.

لا يمكن أيضًا مطابقة البادئة/اللاحقة في اللغات التي لا تُميز بين الكلمات الفردية باستخدام المسافات. واللغة الصينية هي مثال جيد على ذلك. تشير السلسلة '訪問中國' إلى 'visit China'، مع ملاحظة عدم وجود مسافات بين الكلمات. يشكّل الحرفان الأخيران ('中國') معًا كلمة 'China'، ولكن في حال تقسيمهما، سيعنيان 'centre' و'country' على التوالي. لكي تعمل ميزة مطابقة البادئة/اللاحقة في لغات مثل الصينية، ما عليك سوى إدراج مسافة في المكان الذي يجب أن يكون فيه الفاصل. على سبيل المثال، سيؤدي الجمع بين '訪問 中國' و '訪問 美國' إلى "visit [China/USA]"، في حين سيؤدي الجمع بين '訪問 中 國' و '訪問 美 國' إلى "visit [centre/beautiful] country".

إنشاء أداة التحقّق من القائمة المنسدلة

قيمة حقل القائمة المنسدلة هي سلسلة محايدة لغويًا، لذا يجب أن يقبل أيّ مدقّق صحة سلسلة ويعرض سلسلة تمثل خيارًا متاحًا أو null أو undefined.

إذا عرض مدقّق الصحة أي شيء آخر، سيكون سلوك Blockly غير محدّد وقد يؤدي ذلك إلى تعطُّل البرنامج.

على سبيل المثال، يمكنك تحديد حقل منسدل يتضمّن ثلاثة خيارات وأحد أدوات التحقّق التالية:

validate: function(newValue) {
  this.getSourceBlock().updateConnections(newValue);
  return newValue;
},

init: function() {
  var options = [
   ['has neither', 'NEITHER'],
   ['has statement', 'STATEMENT'],
   ['has value', 'VALUE'],
  ];

  this.appendDummyInput()
  // Pass the field constructor the options list, the validator, and the name.
      .appendField(new Blockly.FieldDropdown(options, this.validate), 'MODE');
}

تعرض الدالة validate دائمًا القيمة التي تم تمريرها إليها، ولكنها تستدعي الدالة المساعِدة updateConnection التي تضيف مدخلات أو تزيلها استنادًا إلى قيمة القائمة المنسدلة:

updateConnections: function(newValue) {
  this.removeInput('STATEMENT', /* no error */ true);
  this.removeInput('VALUE', /* no error */ true);
  if (newValue == 'STATEMENT') {
    this.appendStatementInput('STATEMENT');
  } else if (newValue == 'VALUE') {
    this.appendValueInput('VALUE');
  }
}

صورة GIF متحركة تعرض حقلًا منسدلًا يتضمّن ثلاثة عناصر: &quot;لا أحد&quot;،
&quot;بيان&quot;، و &quot;قيمة&quot;. عند اختيار &quot;لا أحد&quot;، لا تتوفّر أي إدخالات. عند اختيار
&quot;بيان&quot;، يكون له إدخال بيان. عند ربط &quot;value&quot;،
يكون لديه إدخال &quot;value&quot;.