فیلدهای کشویی

فیلد کشویی یک رشته را به عنوان مقدار و یک رشته را به عنوان متن خود ذخیره می کند. این مقدار یک کلید زبان خنثی است که برای دسترسی به متن استفاده می‌شود و وقتی Blockly بین زبان‌ها جابه‌جا می‌شود، ترجمه نمی‌شود. متن یک رشته قابل خواندن توسط انسان است که به کاربر نمایش داده می شود.

یک بلوک با برچسب "drop down:"، یک فیلد کشویی با انتخاب "first"، و برچسب "اقلام".

همان بلوک با کشویی باز است. منوی کشویی شامل موارد "اول" است و "دوم".

همان بلوک پس از فروریختن. دارای برچسب "کشویی: اولین مورد" و یک لبه سمت راست دندانه دار برای نشان دادن آن است فرو ریخت.

خلقت

سازنده کشویی یک مولد منو و یک اعتبارسنجی اختیاری را می گیرد. مولد منو یا آرایه ای از گزینه ها است (که در آن هر گزینه شامل یک قسمت قابل خواندن توسط انسان و یک رشته زبان خنثی است) یا تابعی است که آرایه ای از گزینه ها را تولید می کند. بخش قابل خواندن توسط انسان هر گزینه می تواند یک رشته، یک تصویر یا یک عنصر HTML باشد و آرایه می تواند حاوی ترکیبی از گزینه های مختلف باشد.

کشویی متن ساده

کشویی را با دو گزینه متنی باز کنید

JSON

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

جاوا اسکریپت

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"]
      ]
    }
  ]
}

جاوا اسکریپت

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');
  }
};

کشویی HTML

یک گزینه ممکن است هر عنصر HTML باشد، تا زمانی که خیلی بزرگ نباشد و سعی در مدیریت رویدادهای ماوس یا صفحه کلید نداشته باشد. (مسئولیت شماست که از این قوانین پیروی کنید -- Blockly آنها را اجرا نمی کند.)

وقتی کشویی باز است، لیست عنصر HTML را نمایش می دهد. هنگامی که بسته است و عنصر گزینه انتخاب شده است، لیست (به ترتیب ترجیحی نزولی) ویژگی title عنصر، ویژگی aria-label یا ویژگی innerText آن را نشان می دهد.

فیلد کشویی حاوی متن و HTML عناصر

JSON

{
  "type": "flags_with_text_dropdown",
  "message0": "flag with text %1",
  "args0": [
    {
      "type": "field_dropdown",
      "name": "FLAG_WITH_TEXT",
      "options": [
        ["x", "X"], // Placeholder. An empty array throws an exception.
      ]
    }
  ],
  // Use an extension to add the HTML element options.
  "extensions": ["flag_with_text_extension"]
}
Blockly.Extensions.register('flag_with_text_extension',
  function() {
    function createFlagWithTextDiv(text, src) {
      const div = document.createElement('div');
      div.setAttribute('style', 'width: 75px;');
      div.setAttribute('title', text);
      const img = document.createElement('img');
      img.setAttribute('src', src);
      img.setAttribute('style', 'height: 25px; display: block; margin: auto;');
      div.appendChild(img);
      const para = document.createElement('p');
      para.innerText = text;
      para.setAttribute('style', 'text-align: center; margin: 5px;');
      div.appendChild(para);
      return div;
    }

    const canadaDiv = createFlagWithTextDiv('Canada', 'canada.png');
    const usaDiv = createFlagWithTextDiv('USA', 'usa.png');
    const mexicoDiv = createFlagWithTextDiv('Mexico', 'mexico.png');
    const options = [
      ['none', 'NONE'],
      [canadaDiv, 'CANADA'],
      [usaDiv, 'USA'],
      [mexicoDiv, 'MEXICO']
    ];
    this.getField('FLAG_WITH_TEXT').setOptions(options);
  });

این کار با استفاده از پسوند JSON انجام می شود.

جاوا اسکریپت

function createFlagWithTextDiv(text, src) {
  const div = document.createElement('div');
  div.setAttribute('style', 'width: 75px;');
  div.setAttribute('title', text);
  const img = document.createElement('img');
  img.setAttribute('src', src);
  img.setAttribute('style', 'height: 25px; display: block; margin: auto;');
  div.appendChild(img);
  const para = document.createElement('p');
  para.innerText = text;
  para.setAttribute('style', 'text-align: center; margin: 5px;');
  div.appendChild(para);
  return div;
}

const canadaDiv = createFlagWithTextDiv('Canada', 'canada.png');
const usaDiv = createFlagWithTextDiv('USA', 'usa.png');
const mexicoDiv = createFlagWithTextDiv('Mexico', 'mexico.png');

Blockly.Blocks['flags_with_text_dropdown'] = {
  init: function() {
    const input = this.appendDummyInput()
        .appendField('flag with text');
    const options = [
        ['none', 'NONE'],
        [canadaDiv, 'CANADA'],
        [usaDiv, 'USA'],
        [mexicoDiv, 'MEXICO']
    ];
    input.appendField(new Blockly.FieldDropdown(options), 'FLAG_WITH_TEXT');
  }
};

کشویی پویا

فیلد کشویی با روزهای هفته

JSON

{
  "type": "dynamic_dropdown",
  "message0": "day %1",
  "args0": [
    {
      "type": "field_dropdown",
      "name": "DAY",
      "options": [
        ["x", "X"], // Placeholder. An empty array throws an exception.
      ]
     }
  ],
  // Use an extension to set the menu function.
  "extensions": ["dynamic_menu_extension"]
}
Blockly.Extensions.register('dynamic_menu_extension',
  function() {
    this.getField('DAY').setOptions(
      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;
      });
  });

این کار با استفاده از پسوند JSON انجام می شود.

جاوا اسکریپت

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] به عنوان گزینه‌های استاتیک برگرداند. هر بار که روی منوی کشویی کلیک می شود، تابع اجرا می شود و گزینه ها دوباره محاسبه می شوند.

جداکننده ها

از رشته 'separator' برای اضافه کردن یک خط بین گزینه‌ها در منوی کشویی استفاده کنید.

فیلد کشویی با یک خط بین دوم و سوم گزینه ها

JSON

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

جاوا اسکریپت

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 فیلد حاوی رشته ای است که به یک فیلد کشویی ارجاع می دهد و متن داخلی مقداری است که باید به فیلد اعمال شود. متن داخلی باید یک کلید گزینه معتبر بدون زبان باشد.

سفارشی سازی

ویژگی Blockly.FieldDropdown.ARROW_CHAR را می توان برای تغییر کاراکتر یونیکد نشان دهنده فلش کشویی استفاده کرد.

فیلد کشویی با فلش سفارشی

ویژگی ARROW_CHAR به طور پیش‌فرض در Android روی \u25BC (▼) و در غیر این صورت \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"]
      ]
    }
  ]
}

جاوا اسکریپت

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"]
      ]
    }
  ]
}

جاوا اسکریپت

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 red car' و 'drive red truck' احتمالاً باید فقط 'drive' در نظر بگیرند، نه '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 متحرک که یک فیلد کشویی با سه مورد را نشان می‌دهد: "هیچکدام"، "بیانیه" و "ارزش". وقتی "هیچکدام" انتخاب شود، هیچ ورودی ندارد. چه زمانی "بیانیه" انتخاب شده است، یک ورودی بیانیه دارد. هنگامی که "ارزش" متصل است، آن را دارای ورودی "ارزش" است.