قبل از ایجاد یک نوع فیلد جدید، در نظر بگیرید که آیا یکی از روشهای دیگر برای سفارشیسازی فیلدها با نیازهای شما مطابقت دارد یا خیر. اگر برنامه شما نیاز به ذخیره یک نوع مقدار جدید دارد، یا می خواهید یک رابط کاربری جدید برای یک نوع مقدار موجود ایجاد کنید، احتمالاً باید یک نوع فیلد جدید ایجاد کنید.
برای ایجاد یک فیلد جدید، موارد زیر را انجام دهید:
- یک سازنده را پیاده سازی کنید .
- یک کلید JSON ثبت کنید و
fromJson
پیاده سازی کنید . - تنظیم اولیه رابط کاربری روی بلوک و شنوندگان رویداد را انجام دهید .
- رسیدگی به دفع شنوندگان رویداد (دفع UI برای شما انجام می شود).
- مدیریت ارزش را پیاده سازی کنید .
- برای دسترسی، یک نمایش متنی از مقدار فیلد خود اضافه کنید .
- اضافه کردن قابلیت های اضافی مانند:
- جنبه های اضافی رشته خود را پیکربندی کنید، مانند:
این بخش فرض می کند که شما مطالب موجود در آناتومی یک میدان را خوانده اید و با آن آشنا هستید.
برای مثالی از یک فیلد سفارشی ، نسخه نمایشی Custom Fields را ببینید.
پیاده سازی سازنده
سازنده فیلد مسئول تنظیم مقدار اولیه فیلد و تنظیم اختیاری یک اعتبارسنجی محلی است. سازنده فیلد سفارشی در طول مقداردهی اولیه بلوک منبع فراخوانی می شود، صرف نظر از اینکه بلوک منبع در JSON یا جاوا اسکریپت تعریف شده باشد. بنابراین، فیلد سفارشی در طول ساخت به بلوک منبع دسترسی ندارد.
نمونه کد زیر یک فیلد سفارشی به نام GenericField
ایجاد می کند:
class GenericField extends Blockly.Field {
constructor(value, validator) {
super(value, validator);
this.SERIALIZABLE = true;
}
}
امضای روش
سازندگان فیلد معمولاً یک مقدار و یک اعتبارسنجی محلی را می گیرند. مقدار اختیاری است، و اگر مقداری را ارسال نکنید (یا مقداری را ارسال کنید که اعتبار کلاس را با مشکل مواجه کند)، از مقدار پیشفرض سوپرکلاس استفاده میشود. برای کلاس Field
پیش فرض، این مقدار null
است. اگر آن مقدار پیشفرض را نمیخواهید، حتماً یک مقدار مناسب را ارسال کنید. پارامتر اعتبارسنجی فقط برای فیلدهای قابل ویرایش وجود دارد و معمولاً به عنوان اختیاری علامتگذاری میشود. در اسناد اعتبار سنجی بیشتر بدانید.
ساختار
منطق داخل سازنده شما باید از این جریان پیروی کند:
- ابر سازنده ارثی را فراخوانی کنید (همه فیلدهای سفارشی باید از
Blockly.Field
یا یکی از زیرکلاسهای آن ارث بری شوند) تا مقدار را به درستی مقداردهی اولیه کنید و اعتبارسنجی محلی را برای فیلد خود تنظیم کنید. - اگر فیلد شما قابل سریال سازی است، ویژگی مربوطه را در سازنده تنظیم کنید. فیلدهای قابل ویرایش باید سریالسازی شوند و فیلدها بهطور پیشفرض قابل ویرایش هستند، بنابراین احتمالاً باید این ویژگی را روی true تنظیم کنید، مگر اینکه بدانید نباید سریالپذیر باشد.
- اختیاری: سفارشیسازی اضافی را اعمال کنید (برای مثال، فیلدهای Label اجازه میدهند یک کلاس css ارسال شود، که سپس روی متن اعمال میشود).
JSON و ثبت نام
در تعاریف بلوک JSON ، فیلدها با یک رشته توصیف می شوند (به عنوان مثال field_number
، field_textinput
). Blockly نقشه ای را از این رشته ها به اشیاء فیلد نگه می دارد و fromJson
روی شی مناسب در حین ساخت فراخوانی می کند.
Blockly.fieldRegistry.register
را فراخوانی کنید تا نوع فیلد خود را به این نقشه اضافه کنید و در کلاس فیلد به عنوان آرگومان دوم ارسال کنید:
Blockly.fieldRegistry.register('field_generic', GenericField);
همچنین باید تابع fromJson
خود را تعریف کنید. پیاده سازی شما باید ابتدا ارجاعات جدول رشته ای را با استفاده از replaceMessageReferences لغو کند و سپس مقادیر را به سازنده ارسال کند.
GenericField.fromJson = function(options) {
const value = Blockly.utils.parsing.replaceMessageReferences(
options['value']);
return new CustomFields.GenericField(value);
};
مقدار دهی اولیه
وقتی فیلد شما ساخته می شود، اساساً فقط حاوی یک مقدار است. مقداردهی اولیه جایی است که DOM ساخته می شود، مدل ساخته می شود (اگر فیلد دارای مدل باشد)، و رویدادها محدود می شوند.
نمایشگر روی بلوک
در طول مقداردهی اولیه، شما مسئول ایجاد هر چیزی هستید که برای نمایش روی بلوک فیلد نیاز دارید.
پیشفرضها، پسزمینه و متن
تابع initView
پیش فرض یک عنصر rect
روشن و یک عنصر text
ایجاد می کند. اگر میخواهید فیلد شما هر دوی اینها را داشته باشد، به علاوه چند ویژگی اضافی، قبل از اضافه کردن بقیه عناصر DOM، تابع superclass initView
را فراخوانی کنید. اگر می خواهید فیلد شما یکی از این عناصر را داشته باشد، اما نه هر دو، می توانید از توابع createBorderRect_
یا createTextElement_
استفاده کنید.
سفارشی سازی ساخت DOM
اگر فیلد شما یک فیلد متنی عمومی است (مثلاً ورودی متن )، ساخت DOM برای شما انجام می شود. در غیر این صورت باید تابع initView
را نادیده بگیرید تا عناصر DOM را ایجاد کنید که در رندر آینده فیلد خود به آن نیاز خواهید داشت.
برای مثال، یک فیلد کشویی ممکن است هم شامل تصاویر و هم متن باشد. در initView
یک عنصر تصویر و یک عنصر متن واحد ایجاد می کند. سپس در طول render_
عنصر فعال را نشان می دهد و دیگری را بر اساس نوع گزینه انتخاب شده پنهان می کند.
ایجاد عناصر DOM می تواند با استفاده از روش Blockly.utils.dom.createSvgElement
یا با استفاده از روش های سنتی ایجاد DOM انجام شود.
الزامات نمایش روی بلوک یک فیلد عبارتند از:
- همه عناصر DOM باید فرزندان فیلد
fieldGroup_
باشند. گروه فیلد به صورت خودکار ایجاد می شود. - همه عناصر DOM باید در ابعاد گزارش شده فیلد باقی بمانند.
برای جزئیات بیشتر در مورد سفارشیسازی و بهروزرسانی صفحه نمایش روی بلوک، به بخش Rendering مراجعه کنید.
اضافه کردن نمادهای متنی
اگر میخواهید نمادهایی را به متن یک فیلد اضافه کنید (مانند علامت درجه فیلد زاویه )، میتوانید عنصر نماد (معمولاً در یک <tspan>
وجود دارد) را مستقیماً به textElement_
فیلد اضافه کنید.
رویدادهای ورودی
فیلدهای پیشفرض رویدادهای راهنمای ابزار، و رویدادهای ماوس را ثبت میکنند (برای نمایش ویرایشگرها استفاده میشوند). اگر میخواهید انواع دیگر رویدادها را گوش دهید (مثلاً اگر میخواهید کشیدن روی یک فیلد را مدیریت کنید)، باید تابع bindEvents_
فیلد را لغو کنید.
bindEvents_() {
// Call the superclass function to preserve the default behavior as well.
super.bindEvents_();
// Then register your own additional event listeners.
this.mouseDownWrapper_ =
Blockly.browserEvents.conditionalBind(this.getClickTarget_(), 'mousedown', this,
function(event) {
this.originalMouseX_ = event.clientX;
this.isMouseDown_ = true;
this.originalValue_ = this.getValue();
event.stopPropagation();
}
);
this.mouseMoveWrapper_ =
Blockly.browserEvents.conditionalBind(document, 'mousemove', this,
function(event) {
if (!this.isMouseDown_) {
return;
}
var delta = event.clientX - this.originalMouseX_;
this.setValue(this.originalValue_ + delta);
}
);
this.mouseUpWrapper_ =
Blockly.browserEvents.conditionalBind(document, 'mouseup', this,
function(_event) {
this.isMouseDown_ = false;
}
);
}
برای اتصال به یک رویداد، معمولاً باید از تابع Blockly.utils.browserEvents.conditionalBind
استفاده کنید. این روش اتصال رویدادها، لمسهای ثانویه را در طول کشیدن فیلتر میکند. اگر می خواهید کنترل کننده شما حتی در وسط کشیدن در حال انجام اجرا شود، می توانید از تابع Blockly.browserEvents.bind
استفاده کنید.
دفع کردن
اگر هر شنونده رویداد سفارشی را در تابع bindEvents_
فیلد ثبت کرده اید، باید در تابع dispose
ثبت نام نشده باشند.
اگر نمای فیلد خود را به درستی مقداردهی اولیه کرده باشید (با افزودن تمام عناصر DOM به fieldGroup_
)، DOM فیلد به طور خودکار حذف می شود.
مدیریت ارزش
← برای اطلاعات در مورد مقدار یک فیلد در مقابل متن آن به آناتومی یک فیلد مراجعه کنید.
دستور اعتبارسنجی
پیاده سازی اعتبار سنجی کلاس
فیلدها فقط باید مقادیر خاصی را بپذیرند. به عنوان مثال، فیلدهای اعداد فقط باید اعداد را بپذیرند، فیلدهای رنگی فقط باید رنگ ها را بپذیرند و غیره. این از طریق اعتبارسنجی کلاس و محلی تضمین می شود. اعتباردهنده کلاس از همان قوانین اعتبار سنجی محلی پیروی می کند با این تفاوت که در سازنده نیز اجرا می شود و به این ترتیب، نباید به بلوک منبع اشاره کند.
برای پیاده سازی اعتبار سنج کلاس فیلد خود، تابع doClassValidation_
لغو کنید.
doClassValidation_(newValue) {
if (typeof newValue != 'string') {
return null;
}
return newValue;
};
مدیریت مقادیر معتبر
اگر مقدار ارسال شده به فیلدی با setValue
معتبر باشد، یک پاسخ تماس doValueUpdate_
دریافت خواهید کرد. به طور پیش فرض تابع doValueUpdate_
:
- ویژگی
value_
رویnewValue
تنظیم می کند. - ویژگی
isDirty_
را رویtrue
تنظیم می کند.
اگر به سادگی نیاز دارید مقدار را ذخیره کنید، و نمیخواهید هیچ گونه مدیریت سفارشی انجام دهید، نیازی به لغو doValueUpdate_
ندارید.
در غیر این صورت، اگر می خواهید کارهایی مانند:
- ذخیره سازی سفارشی
newValue
. - سایر خصوصیات را بر اساس
newValue
تغییر دهید. - ذخیره کنید که آیا مقدار فعلی معتبر است یا خیر.
شما باید doValueUpdate_
را لغو کنید:
doValueUpdate_(newValue) {
super.doValueUpdate_(newValue);
this.displayValue_ = newValue;
this.isValueValid_ = true;
}
مدیریت مقادیر نامعتبر
اگر مقدار ارسال شده به فیلد دارای setValue
نامعتبر باشد، یک پاسخ تماس doValueInvalid_
دریافت خواهید کرد. به طور پیش فرض تابع doValueInvalid_
هیچ کاری انجام نمی دهد. این بدان معنی است که به طور پیش فرض مقادیر نامعتبر نشان داده نمی شوند. همچنین به این معنی است که فیلد دوباره رندر نمی شود، زیرا ویژگی isDirty_
تنظیم نمی شود.
اگر میخواهید مقادیر نامعتبر نمایش داده شود، باید doValueInvalid_
لغو کنید. در اکثر شرایط باید یک ویژگی displayValue_
را روی مقدار نامعتبر تنظیم کنید، isDirty_
روی true
تنظیم کنید، و render_ را لغو کنید تا نمایشگر روی بلوک بر اساس displayValue_
به جای value_
به روز شود.
doValueInvalid_(newValue) {
this.displayValue_ = newValue;
this.isDirty_ = true;
this.isValueValid_ = false;
}
مقادیر چند قسمتی
وقتی فیلد شما حاوی یک مقدار چند قسمتی است (مثلاً لیستها، بردارها، اشیاء) ممکن است بخواهید قسمتها مانند مقادیر جداگانه مدیریت شوند.
doClassValidation_(newValue) {
if (FieldTurtle.PATTERNS.indexOf(newValue.pattern) == -1) {
newValue.pattern = null;
}
if (FieldTurtle.HATS.indexOf(newValue.hat) == -1) {
newValue.hat = null;
}
if (FieldTurtle.NAMES.indexOf(newValue.turtleName) == -1) {
newValue.turtleName = null;
}
if (!newValue.pattern || !newValue.hat || !newValue.turtleName) {
this.cachedValidatedValue_ = newValue;
return null;
}
return newValue;
}
در مثال بالا هر ویژگی newValue
به صورت جداگانه تایید می شود. سپس در انتهای تابع doClassValidation_
، اگر هر یک از ویژگی های فردی نامعتبر باشد، قبل از بازگشت null
، مقدار به ویژگی cacheValidatedValue_
ذخیره می شود (نامعتبر). ذخیره کردن شی با خصوصیات تایید شده جداگانه به تابع doValueInvalid_
اجازه می دهد تا آنها را به طور جداگانه مدیریت کند، به سادگی با انجام یک بررسی !this.cacheValidatedValue_.property
، به جای تایید مجدد هر ویژگی به صورت جداگانه.
این الگو برای اعتبارسنجی مقادیر چند قسمتی میتواند در اعتبارسنجیهای محلی نیز استفاده شود، اما در حال حاضر راهی برای اعمال این الگو وجود ندارد.
کثیف است_
isDirty_
پرچمی است که در تابع setValue
و همچنین سایر قسمتهای فیلد استفاده میشود تا مشخص کند آیا فیلد نیاز به رندر مجدد دارد یا خیر. اگر مقدار نمایش فیلد تغییر کرده باشد، isDirty_
معمولا باید روی true
تنظیم شود.
متن
← برای اطلاعات در مورد محل استفاده از متن یک فیلد و تفاوت آن با مقدار فیلد، به آناتومی یک فیلد مراجعه کنید.
اگر متن فیلد شما با مقدار فیلد شما متفاوت است، برای ارائه متن صحیح باید تابع getText
را لغو کنید.
getText() {
let text = this.value_.turtleName + ' wearing a ' + this.value_.hat;
if (this.value_.hat == 'Stovepipe' || this.value_.hat == 'Propeller') {
text += ' hat';
}
return text;
}
ایجاد ویرایشگر
اگر تابع showEditor_
را تعریف کنید، Blockly به طور خودکار به کلیک ها گوش می دهد و showEditor_
در زمان مناسب فرا می خواند. شما می توانید هر HTML را در ویرایشگر خود با قرار دادن آن در یکی از دو div ویژه به نام های DropDownDiv و WidgetDiv نمایش دهید که در بالای بقیه رابط کاربری Blockly شناور هستند.
DropDownDiv در مقابل WidgetDiv
DropDownDiv
برای ارائه ویرایشگرهایی استفاده می شود که در داخل یک جعبه متصل به یک فیلد زندگی می کنند. به طور خودکار خود را در نزدیکی میدان قرار می دهد در حالی که در محدوده های قابل مشاهده باقی می ماند. انتخابگر زاویه و انتخابگر رنگ نمونه های خوبی از DropDownDiv
هستند.
WidgetDiv
برای ارائه ویرایشگرهایی استفاده می شود که در داخل جعبه زندگی نمی کنند. فیلدهای اعداد از WidgetDiv برای پوشاندن فیلد با کادر ورودی متن HTML استفاده می کنند. در حالی که DropDownDiv موقعیت یابی را برای شما انجام می دهد، WidgetDiv این کار را نمی کند. عناصر باید به صورت دستی قرار گیرند. سیستم مختصات در مختصات پیکسلی نسبت به سمت چپ بالای پنجره است. ویرایشگر ورودی متن نمونه خوبی از WidgetDiv
است.
کد نمونه DropDownDiv
showEditor_() {
// Create the widget HTML
this.editor_ = this.dropdownCreate_();
Blockly.DropDownDiv.getContentDiv().appendChild(this.editor_);
// Set the dropdown's background colour.
// This can be used to make it match the colour of the field.
Blockly.DropDownDiv.setColour('white', 'silver');
// Show it next to the field. Always pass a dispose function.
Blockly.DropDownDiv.showPositionedByField(
this, this.disposeWidget_.bind(this));
}
کد نمونه WidgetDiv
showEditor_() {
// Show the div. This automatically closes the dropdown if it is open.
// Always pass a dispose function.
Blockly.WidgetDiv.show(
this, this.sourceBlock_.RTL, this.widgetDispose_.bind(this));
// Create the widget HTML.
var widget = this.createWidget_();
Blockly.WidgetDiv.getDiv().appendChild(widget);
}
تمیز کردن
هر دو DropDownDiv و WidgetDiv عناصر HTML ویجت را از بین می برند، اما شما باید به صورت دستی هر شنونده رویدادی را که روی آن عناصر اعمال کرده اید، دور بریزید.
widgetDispose_() {
for (let i = this.editorListeners_.length, listener;
listener = this.editorListeners_[i]; i--) {
Blockly.browserEvents.unbind(listener);
this.editorListeners_.pop();
}
}
تابع dispose
در یک زمینه null
در DropDownDiv
فراخوانی می شود. در WidgetDiv
در متن WidgetDiv
نامیده می شود. در هر صورت، همانطور که در مثالهای DropDownDiv
و WidgetDiv
در بالا نشان داده شده است، هنگام ارسال یک تابع dispose، بهتر است از تابع bind استفاده کنید.
← برای اطلاعات در مورد دفع غیر اختصاصی به دفع سردبیران، دفع را ببینید.
به روز رسانی صفحه نمایش روی بلوک
تابع render_
برای به روز رسانی صفحه نمایش روی بلوک فیلد برای مطابقت با مقدار داخلی آن استفاده می شود.
نمونه های رایج عبارتند از:
- تغییر متن (کشویی)
- تغییر رنگ (رنگ)
پیش فرض ها
تابع render_
پیشفرض، متن نمایشگر را روی نتیجه تابع getDisplayText_
تنظیم میکند. تابع getDisplayText_
خاصیت value_
فیلد را به رشته ای باز می گرداند، پس از اینکه برای رعایت حداکثر طول متن کوتاه شد.
اگر از نمایشگر روی بلوک پیشفرض استفاده میکنید و رفتار متن پیشفرض برای فیلد شما کار میکند، نیازی به لغو render_
نیست.
اگر رفتار متن پیشفرض برای فیلد شما کار میکند، اما نمایشگر روی بلوک فیلد شما دارای عناصر ثابت اضافی است، میتوانید تابع render_
پیشفرض را فراخوانی کنید، اما همچنان باید آن را لغو کنید تا اندازه فیلد بهروزرسانی شود .
اگر رفتار متن پیشفرض برای فیلد شما کار نمیکند، یا نمایشگر روی بلوک فیلد شما دارای عناصر پویا اضافی است، باید تابع render_
سفارشی کنید .
سفارشی سازی رندر
اگر رفتار رندر پیش فرض برای فیلد شما کار نمی کند، باید رفتار رندر سفارشی را تعریف کنید. این می تواند شامل هر چیزی از تنظیم متن نمایش سفارشی گرفته تا تغییر عناصر تصویر و به روز رسانی رنگ های پس زمینه باشد.
همه تغییرات ویژگی DOM قانونی هستند، تنها دو نکته را باید به خاطر بسپارید:
- ایجاد DOM باید در طول مقداردهی اولیه انجام شود، زیرا کارآمدتر است.
- همیشه باید ویژگی
size_
برای مطابقت با اندازه نمایشگر روی بلوک به روز کنید .
render_() {
switch(this.value_.hat) {
case 'Stovepipe':
this.stovepipe_.style.display = '';
break;
case 'Crown':
this.crown_.style.display = '';
break;
case 'Mask':
this.mask_.style.display = '';
break;
case 'Propeller':
this.propeller_.style.display = '';
break;
case 'Fedora':
this.fedora_.style.display = '';
break;
}
switch(this.value_.pattern) {
case 'Dots':
this.shellPattern_.setAttribute('fill', 'url(#polkadots)');
break;
case 'Stripes':
this.shellPattern_.setAttribute('fill', 'url(#stripes)');
break;
case 'Hexagons':
this.shellPattern_.setAttribute('fill', 'url(#hexagons)');
break;
}
this.textContent_.nodeValue = this.value_.turtleName;
this.updateSize_();
}
به روز رسانی اندازه
به روز رسانی ویژگی size_
یک فیلد بسیار مهم است، زیرا به کد رندر بلوک نحوه قرار دادن فیلد را اطلاع می دهد. بهترین راه برای فهمیدن اینکه آن size_
باید دقیقاً چه باشد، آزمایش کردن است.
updateSize_() {
const bbox = this.movableGroup_.getBBox();
let width = bbox.width;
let height = bbox.height;
if (this.borderRect_) {
width += this.constants_.FIELD_BORDER_RECT_X_PADDING * 2;
height += this.constants_.FIELD_BORDER_RECT_X_PADDING * 2;
this.borderRect_.setAttribute('width', width);
this.borderRect_.setAttribute('height', height);
}
// Note how both the width and the height can be dynamic.
this.size_.width = width;
this.size_.height = height;
}
تطبیق رنگ بلوک
اگر میخواهید عناصر فیلد شما با رنگهای بلوکی که به آن وصل شدهاند مطابقت داشته باشد، باید روش applyColour
را لغو کنید. شما می خواهید از طریق ویژگی style بلوک به رنگ دسترسی داشته باشید.
applyColour() {
const sourceBlock = this.sourceBlock_;
if (sourceBlock.isShadow()) {
this.arrow_.style.fill = sourceBlock.style.colourSecondary;
} else {
this.arrow_.style.fill = sourceBlock.style.colourPrimary;
}
}
به روز رسانی قابلیت ویرایش
تابع updateEditable
می تواند برای تغییر نحوه نمایش فیلد شما بسته به اینکه آیا قابل ویرایش است یا نه استفاده می شود. تابع پیشفرض باعث میشود که پسزمینه اگر قابل ویرایش باشد/غیرقابل ویرایش باشد، پاسخ شناور (حاشیه) ندارد. اندازه صفحه نمایش روی بلوک بسته به قابلیت ویرایش آن نباید تغییر کند، اما سایر تغییرات مجاز هستند.
updateEditable() {
if (!this.fieldGroup_) {
// Not initialized yet.
return;
}
super.updateEditable();
const group = this.getClickTarget_();
if (!this.isCurrentlyEditable()) {
group.style.cursor = 'not-allowed';
} else {
group.style.cursor = this.CURSOR;
}
}
سریال سازی
سریال سازی در مورد ذخیره وضعیت فیلد شما است تا بعداً بتوان آن را دوباره در فضای کاری بارگذاری کرد.
وضعیت فضای کاری شما همیشه شامل مقدار فیلد میشود، اما میتواند وضعیت دیگری مانند وضعیت رابط کاربری فیلد شما را نیز شامل شود. به عنوان مثال، اگر فیلد شما یک نقشه قابل بزرگنمایی بود که به کاربر امکان انتخاب کشورها را می داد، می توانید سطح بزرگنمایی را نیز سریال کنید.
اگر فیلد شما قابل سریالسازی است، باید ویژگی SERIALIZABLE
را روی true
تنظیم کنید.
Blockly دو مجموعه قلاب سریال سازی را برای فیلدها فراهم می کند. یک جفت قلاب با سیستم جدید سریال سازی JSON کار می کند و جفت دیگر با سیستم سریال سازی XML قدیمی کار می کند.
saveState
و loadState
saveState
و loadState
قلاب های سریال سازی هستند که با سیستم سریال سازی جدید JSON کار می کنند.
در برخی موارد شما نیازی به ارائه این موارد ندارید، زیرا پیاده سازی های پیش فرض کار خواهند کرد. اگر (1) فیلد شما یک زیر کلاس مستقیم از کلاس پایه Blockly.Field
است، (2) مقدار شما از نوع JSON قابل سریالسازی است و (3) فقط باید مقدار را سریالسازی کنید، پیادهسازی پیشفرض به خوبی کار خواهد کرد!
در غیر این صورت، تابع saveState
شما باید یک شی/مقدار سریالسازی JSON را برگرداند که وضعیت فیلد را نشان میدهد. و تابع loadState
شما باید همان شی/مقدار سریالسازی JSON را بپذیرد و آن را در فیلد اعمال کند.
saveState() {
return {
'country': this.getValue(), // Value state
'zoom': this.getZoomLevel(), // UI state
};
}
loadState(state) {
this.setValue(state['country']);
this.setZoomLevel(state['zoom']);
}
سریال سازی کامل و داده های پشتیبان
saveState
همچنین یک پارامتر اختیاری doFullSerialization
را دریافت می کند. این مورد توسط فیلدهایی استفاده میشود که معمولاً به حالت سریالسازی شده توسط سریالساز دیگری (مانند مدلهای داده پشتیبان) اشاره میکنند. این پارامتر نشان میدهد که حالت ارجاعشده زمانی که بلوک از حالت سریال خارج میشود، در دسترس نخواهد بود، بنابراین فیلد باید تمام سریالسازی را خودش انجام دهد. به عنوان مثال، زمانی که یک بلوک مجزا سریالی می شود، یا زمانی که یک بلوک کپی پیست شده است، این درست است.
دو مورد استفاده رایج برای این عبارتند از:
- هنگامی که یک بلوک منفرد در فضای کاری بارگذاری می شود که در آن مدل داده پشتیبان وجود ندارد، فیلد در حالت خودش اطلاعات کافی برای ایجاد یک مدل داده جدید دارد.
- هنگامی که یک بلوک کپی پیست می شود، این فیلد به جای ارجاع به مدل موجود، همیشه یک مدل داده پشتیبان جدید ایجاد می کند.
یکی از زمینه هایی که از این استفاده می کند، فیلد متغیر داخلی است. معمولاً شناسه متغیری را که به آن ارجاع می دهد سریال می کند، اما اگر doFullSerialization
درست باشد، تمام حالت آن را سریالی می کند.
saveState(doFullSerialization) {
const state = {'id': this.variable_.getId()};
if (doFullSerialization) {
state['name'] = this.variable_.name;
state['type'] = this.variable_.type;
}
return state;
}
loadState(state) {
const variable = Blockly.Variables.getOrCreateVariablePackage(
this.getSourceBlock().workspace,
state['id'],
state['name'], // May not exist.
state['type']); // May not exist.
this.setValue(variable.getId());
}
فیلد متغیر این کار را انجام می دهد تا مطمئن شود که اگر در فضای کاری بارگذاری شود که متغیر آن وجود ندارد، می تواند یک متغیر جدید برای ارجاع ایجاد کند.
toXml
و fromXml
toXml
و fromXml
قلاب های سریال سازی هستند که با سیستم قدیمی سریال سازی XML کار می کنند. فقط در صورت لزوم از این هوک ها استفاده کنید (مثلاً روی یک پایگاه کد قدیمی کار می کنید که هنوز مهاجرت نکرده است)، در غیر این صورت از saveState
و loadState
استفاده کنید.
تابع toXml
شما باید یک گره XML را برگرداند که نشان دهنده وضعیت فیلد است. و تابع fromXml
شما باید همان گره XML را بپذیرد و آن را در فیلد اعمال کند.
toXml(fieldElement) {
fieldElement.textContent = this.getValue();
fieldElement.setAttribute('zoom', this.getZoomLevel());
return fieldElement;
}
fromXml(fieldElement) {
this.setValue(fieldElement.textContent);
this.setZoomLevel(fieldElement.getAttribute('zoom'));
}
ویژگی های قابل ویرایش و سریال
ویژگی EDITABLE
تعیین می کند که آیا فیلد باید دارای UI باشد تا نشان دهد که می توان با آن تعامل داشت یا خیر. پیش فرض آن true
است.
ویژگی SERIALIZABLE
تعیین می کند که آیا فیلد باید سریال شود یا خیر. پیش فرض آن false
است. اگر این ویژگی true
باشد، ممکن است لازم باشد توابع سریالسازی و سریالسازی را ارائه کنید (به سریالسازی مراجعه کنید).
سفارشی کردن مکان نما
ویژگی CURSOR
مکان نما را مشخص می کند که کاربران هنگام حرکت بر روی فیلد شما می بینند. این باید یک رشته مکان نما CSS معتبر باشد. این به طور پیشفرض به مکاننمای تعریف شده توسط .blocklyDraggable
، که نشانگر گرفتن است، تنظیم میشود.
قبل از ایجاد یک نوع فیلد جدید، در نظر بگیرید که آیا یکی از روشهای دیگر برای سفارشیسازی فیلدها با نیازهای شما مطابقت دارد یا خیر. اگر برنامه شما نیاز به ذخیره یک نوع مقدار جدید دارد، یا می خواهید یک رابط کاربری جدید برای یک نوع مقدار موجود ایجاد کنید، احتمالاً باید یک نوع فیلد جدید ایجاد کنید.
برای ایجاد یک فیلد جدید، موارد زیر را انجام دهید:
- یک سازنده را پیاده سازی کنید .
- یک کلید JSON ثبت کنید و
fromJson
پیاده سازی کنید . - تنظیم اولیه رابط کاربری روی بلوک و شنوندگان رویداد را انجام دهید .
- رسیدگی به دفع شنوندگان رویداد (دفع UI برای شما انجام می شود).
- مدیریت ارزش را پیاده سازی کنید .
- برای دسترسی، یک نمایش متنی از مقدار فیلد خود اضافه کنید .
- اضافه کردن قابلیت های اضافی مانند:
- جنبه های اضافی رشته خود را پیکربندی کنید، مانند:
این بخش فرض می کند که شما مطالب موجود در آناتومی یک میدان را خوانده اید و با آن آشنا هستید.
برای مثالی از یک فیلد سفارشی ، نسخه نمایشی Custom Fields را ببینید.
پیاده سازی سازنده
سازنده فیلد مسئول تنظیم مقدار اولیه فیلد و تنظیم اختیاری یک اعتبارسنجی محلی است. سازنده فیلد سفارشی در طول مقداردهی اولیه بلوک منبع فراخوانی می شود، صرف نظر از اینکه بلوک منبع در JSON یا جاوا اسکریپت تعریف شده باشد. بنابراین، فیلد سفارشی در طول ساخت به بلوک منبع دسترسی ندارد.
نمونه کد زیر یک فیلد سفارشی به نام GenericField
ایجاد می کند:
class GenericField extends Blockly.Field {
constructor(value, validator) {
super(value, validator);
this.SERIALIZABLE = true;
}
}
امضای روش
سازندگان فیلد معمولاً یک مقدار و یک اعتبارسنجی محلی را می گیرند. مقدار اختیاری است، و اگر مقداری را ارسال نکنید (یا مقداری را ارسال کنید که اعتبار کلاس را با مشکل مواجه کند)، از مقدار پیشفرض سوپرکلاس استفاده میشود. برای کلاس Field
پیش فرض، این مقدار null
است. اگر آن مقدار پیشفرض را نمیخواهید، حتماً یک مقدار مناسب را ارسال کنید. پارامتر اعتبارسنجی فقط برای فیلدهای قابل ویرایش وجود دارد و معمولاً به عنوان اختیاری علامتگذاری میشود. در اسناد اعتبار سنجی بیشتر بدانید.
ساختار
منطق داخل سازنده شما باید از این جریان پیروی کند:
- ابر سازنده ارثی را فراخوانی کنید (همه فیلدهای سفارشی باید از
Blockly.Field
یا یکی از زیرکلاسهای آن ارث بری شوند) تا مقدار را به درستی مقداردهی اولیه کنید و اعتبارسنجی محلی را برای فیلد خود تنظیم کنید. - اگر فیلد شما قابل سریال سازی است، ویژگی مربوطه را در سازنده تنظیم کنید. فیلدهای قابل ویرایش باید سریالسازی شوند و فیلدها بهطور پیشفرض قابل ویرایش هستند، بنابراین احتمالاً باید این ویژگی را روی true تنظیم کنید، مگر اینکه بدانید نباید سریالپذیر باشد.
- اختیاری: سفارشیسازی اضافی را اعمال کنید (برای مثال، فیلدهای Label اجازه میدهند یک کلاس css ارسال شود، که سپس روی متن اعمال میشود).
JSON و ثبت نام
در تعاریف بلوک JSON ، فیلدها با یک رشته توصیف می شوند (به عنوان مثال field_number
، field_textinput
). Blockly نقشه ای را از این رشته ها به اشیاء فیلد نگه می دارد و fromJson
روی شی مناسب در حین ساخت فراخوانی می کند.
Blockly.fieldRegistry.register
را فراخوانی کنید تا نوع فیلد خود را به این نقشه اضافه کنید و در کلاس فیلد به عنوان آرگومان دوم ارسال کنید:
Blockly.fieldRegistry.register('field_generic', GenericField);
همچنین باید تابع fromJson
خود را تعریف کنید. پیاده سازی شما باید ابتدا ارجاعات جدول رشته ای را با استفاده از replaceMessageReferences لغو کند و سپس مقادیر را به سازنده ارسال کند.
GenericField.fromJson = function(options) {
const value = Blockly.utils.parsing.replaceMessageReferences(
options['value']);
return new CustomFields.GenericField(value);
};
مقدار دهی اولیه
وقتی فیلد شما ساخته می شود، اساساً فقط حاوی یک مقدار است. مقداردهی اولیه جایی است که DOM ساخته می شود، مدل ساخته می شود (اگر فیلد دارای مدل باشد)، و رویدادها محدود می شوند.
نمایشگر روی بلوک
در طول مقداردهی اولیه، شما مسئول ایجاد هر چیزی هستید که برای نمایش روی بلوک فیلد نیاز دارید.
پیشفرضها، پسزمینه و متن
تابع initView
پیش فرض یک عنصر rect
روشن و یک عنصر text
ایجاد می کند. اگر میخواهید فیلد شما هر دوی اینها را داشته باشد، به علاوه چند ویژگی اضافی، قبل از اضافه کردن بقیه عناصر DOM، تابع superclass initView
را فراخوانی کنید. اگر می خواهید فیلد شما یکی از این عناصر را داشته باشد، اما نه هر دو، می توانید از توابع createBorderRect_
یا createTextElement_
استفاده کنید.
سفارشی سازی ساخت DOM
اگر فیلد شما یک فیلد متنی عمومی است (مثلاً ورودی متن )، ساخت DOM برای شما انجام می شود. در غیر این صورت باید تابع initView
را نادیده بگیرید تا عناصر DOM را ایجاد کنید که در رندر آینده فیلد خود به آن نیاز خواهید داشت.
برای مثال، یک فیلد کشویی ممکن است هم شامل تصاویر و هم متن باشد. در initView
یک عنصر تصویر و یک عنصر متن واحد ایجاد می کند. سپس در طول render_
عنصر فعال را نشان می دهد و دیگری را بر اساس نوع گزینه انتخاب شده پنهان می کند.
ایجاد عناصر DOM می تواند با استفاده از روش Blockly.utils.dom.createSvgElement
یا با استفاده از روش های سنتی ایجاد DOM انجام شود.
الزامات نمایش روی بلوک یک فیلد عبارتند از:
- همه عناصر DOM باید فرزندان فیلد
fieldGroup_
باشند. گروه فیلد به صورت خودکار ایجاد می شود. - همه عناصر DOM باید در ابعاد گزارش شده فیلد باقی بمانند.
برای جزئیات بیشتر در مورد سفارشیسازی و بهروزرسانی صفحه نمایش روی بلوک، به بخش Rendering مراجعه کنید.
اضافه کردن نمادهای متنی
اگر میخواهید نمادهایی را به متن یک فیلد اضافه کنید (مانند علامت درجه فیلد زاویه )، میتوانید عنصر نماد (معمولاً در یک <tspan>
وجود دارد) را مستقیماً به textElement_
فیلد اضافه کنید.
رویدادهای ورودی
فیلدهای پیشفرض رویدادهای راهنمای ابزار، و رویدادهای ماوس را ثبت میکنند (برای نمایش ویرایشگرها استفاده میشوند). اگر میخواهید انواع دیگر رویدادها را گوش دهید (مثلاً اگر میخواهید کشیدن روی یک فیلد را مدیریت کنید)، باید تابع bindEvents_
فیلد را لغو کنید.
bindEvents_() {
// Call the superclass function to preserve the default behavior as well.
super.bindEvents_();
// Then register your own additional event listeners.
this.mouseDownWrapper_ =
Blockly.browserEvents.conditionalBind(this.getClickTarget_(), 'mousedown', this,
function(event) {
this.originalMouseX_ = event.clientX;
this.isMouseDown_ = true;
this.originalValue_ = this.getValue();
event.stopPropagation();
}
);
this.mouseMoveWrapper_ =
Blockly.browserEvents.conditionalBind(document, 'mousemove', this,
function(event) {
if (!this.isMouseDown_) {
return;
}
var delta = event.clientX - this.originalMouseX_;
this.setValue(this.originalValue_ + delta);
}
);
this.mouseUpWrapper_ =
Blockly.browserEvents.conditionalBind(document, 'mouseup', this,
function(_event) {
this.isMouseDown_ = false;
}
);
}
برای اتصال به یک رویداد، معمولاً باید از تابع Blockly.utils.browserEvents.conditionalBind
استفاده کنید. این روش اتصال رویدادها، لمسهای ثانویه را در طول کشیدن فیلتر میکند. اگر می خواهید کنترل کننده شما حتی در وسط کشیدن در حال انجام اجرا شود، می توانید از تابع Blockly.browserEvents.bind
استفاده کنید.
دفع کردن
اگر هر شنونده رویداد سفارشی را در تابع bindEvents_
فیلد ثبت کرده اید، باید در تابع dispose
ثبت نام نشده باشند.
اگر نمای فیلد خود را به درستی مقداردهی اولیه کرده باشید (با افزودن تمام عناصر DOM به fieldGroup_
)، DOM فیلد به طور خودکار حذف می شود.
مدیریت ارزش
← برای اطلاعات در مورد مقدار یک فیلد در مقابل متن آن به آناتومی یک فیلد مراجعه کنید.
دستور اعتبارسنجی
پیاده سازی اعتبار سنجی کلاس
فیلدها فقط باید مقادیر خاصی را بپذیرند. به عنوان مثال، فیلدهای اعداد فقط باید اعداد را بپذیرند، فیلدهای رنگی فقط باید رنگ ها را بپذیرند و غیره. این از طریق اعتبارسنجی کلاس و محلی تضمین می شود. اعتباردهنده کلاس از همان قوانین اعتبار سنجی محلی پیروی می کند با این تفاوت که در سازنده نیز اجرا می شود و به این ترتیب، نباید به بلوک منبع اشاره کند.
برای پیاده سازی اعتبار سنج کلاس فیلد خود، تابع doClassValidation_
لغو کنید.
doClassValidation_(newValue) {
if (typeof newValue != 'string') {
return null;
}
return newValue;
};
مدیریت مقادیر معتبر
اگر مقدار ارسال شده به فیلدی با setValue
معتبر باشد، یک پاسخ تماس doValueUpdate_
دریافت خواهید کرد. به طور پیش فرض تابع doValueUpdate_
:
- ویژگی
value_
رویnewValue
تنظیم می کند. - ویژگی
isDirty_
را رویtrue
تنظیم می کند.
اگر به سادگی نیاز دارید مقدار را ذخیره کنید، و نمیخواهید هیچ گونه مدیریت سفارشی انجام دهید، نیازی به لغو doValueUpdate_
ندارید.
در غیر این صورت، اگر می خواهید کارهایی مانند:
- ذخیره سازی سفارشی
newValue
. - سایر خصوصیات را بر اساس
newValue
تغییر دهید. - ذخیره کنید که آیا مقدار فعلی معتبر است یا خیر.
شما باید doValueUpdate_
را لغو کنید:
doValueUpdate_(newValue) {
super.doValueUpdate_(newValue);
this.displayValue_ = newValue;
this.isValueValid_ = true;
}
مدیریت مقادیر نامعتبر
اگر مقدار ارسال شده به فیلد دارای setValue
نامعتبر باشد، یک پاسخ تماس doValueInvalid_
دریافت خواهید کرد. به طور پیش فرض تابع doValueInvalid_
هیچ کاری انجام نمی دهد. این بدان معنی است که به طور پیش فرض مقادیر نامعتبر نشان داده نمی شوند. همچنین به این معنی است که فیلد دوباره رندر نمی شود، زیرا ویژگی isDirty_
تنظیم نمی شود.
اگر میخواهید مقادیر نامعتبر نمایش داده شود، باید doValueInvalid_
لغو کنید. در اکثر شرایط باید یک ویژگی displayValue_
را روی مقدار نامعتبر تنظیم کنید، isDirty_
روی true
تنظیم کنید، و render_ را لغو کنید تا نمایشگر روی بلوک بر اساس displayValue_
به جای value_
به روز شود.
doValueInvalid_(newValue) {
this.displayValue_ = newValue;
this.isDirty_ = true;
this.isValueValid_ = false;
}
مقادیر چند قسمتی
وقتی فیلد شما حاوی یک مقدار چند قسمتی است (مثلاً لیستها، بردارها، اشیاء) ممکن است بخواهید قسمتها مانند مقادیر جداگانه مدیریت شوند.
doClassValidation_(newValue) {
if (FieldTurtle.PATTERNS.indexOf(newValue.pattern) == -1) {
newValue.pattern = null;
}
if (FieldTurtle.HATS.indexOf(newValue.hat) == -1) {
newValue.hat = null;
}
if (FieldTurtle.NAMES.indexOf(newValue.turtleName) == -1) {
newValue.turtleName = null;
}
if (!newValue.pattern || !newValue.hat || !newValue.turtleName) {
this.cachedValidatedValue_ = newValue;
return null;
}
return newValue;
}
در مثال بالا هر ویژگی newValue
به صورت جداگانه تایید می شود. سپس در انتهای تابع doClassValidation_
، اگر هر یک از ویژگی های فردی نامعتبر باشد، قبل از بازگشت null
، مقدار به ویژگی cacheValidatedValue_
ذخیره می شود (نامعتبر). ذخیره کردن شی با خصوصیات تایید شده جداگانه به تابع doValueInvalid_
اجازه می دهد تا آنها را به طور جداگانه مدیریت کند، به سادگی با انجام یک بررسی !this.cacheValidatedValue_.property
، به جای تایید مجدد هر ویژگی به صورت جداگانه.
این الگو برای اعتبارسنجی مقادیر چند قسمتی میتواند در اعتبارسنجیهای محلی نیز استفاده شود، اما در حال حاضر راهی برای اعمال این الگو وجود ندارد.
کثیف است_
isDirty_
پرچمی است که در تابع setValue
و همچنین سایر قسمتهای فیلد استفاده میشود تا مشخص کند آیا فیلد نیاز به رندر مجدد دارد یا خیر. اگر مقدار نمایش فیلد تغییر کرده باشد، isDirty_
معمولا باید روی true
تنظیم شود.
متن
← برای اطلاعات در مورد محل استفاده از متن یک فیلد و تفاوت آن با مقدار فیلد، به آناتومی یک فیلد مراجعه کنید.
اگر متن فیلد شما با مقدار فیلد شما متفاوت است، برای ارائه متن صحیح باید تابع getText
را لغو کنید.
getText() {
let text = this.value_.turtleName + ' wearing a ' + this.value_.hat;
if (this.value_.hat == 'Stovepipe' || this.value_.hat == 'Propeller') {
text += ' hat';
}
return text;
}
ایجاد ویرایشگر
اگر تابع showEditor_
را تعریف کنید، Blockly به طور خودکار به کلیک ها گوش می دهد و showEditor_
در زمان مناسب فرا می خواند. شما می توانید هر HTML را در ویرایشگر خود با قرار دادن آن در یکی از دو div ویژه به نام های DropDownDiv و WidgetDiv نمایش دهید که در بالای بقیه رابط کاربری Blockly شناور هستند.
DropDownDiv در مقابل WidgetDiv
DropDownDiv
برای ارائه ویرایشگرهایی استفاده می شود که در داخل یک جعبه متصل به یک فیلد زندگی می کنند. به طور خودکار خود را در نزدیکی میدان قرار می دهد در حالی که در محدوده های قابل مشاهده باقی می ماند. انتخابگر زاویه و انتخابگر رنگ نمونه های خوبی از DropDownDiv
هستند.
WidgetDiv
برای ارائه ویرایشگرهایی استفاده می شود که در داخل جعبه زندگی نمی کنند. فیلدهای اعداد از WidgetDiv برای پوشاندن فیلد با کادر ورودی متن HTML استفاده می کنند. در حالی که DropDownDiv موقعیت یابی را برای شما انجام می دهد، WidgetDiv این کار را نمی کند. عناصر باید به صورت دستی قرار گیرند. سیستم مختصات در مختصات پیکسلی نسبت به سمت چپ بالای پنجره است. ویرایشگر ورودی متن نمونه خوبی از WidgetDiv
است.
کد نمونه DropDownDiv
showEditor_() {
// Create the widget HTML
this.editor_ = this.dropdownCreate_();
Blockly.DropDownDiv.getContentDiv().appendChild(this.editor_);
// Set the dropdown's background colour.
// This can be used to make it match the colour of the field.
Blockly.DropDownDiv.setColour('white', 'silver');
// Show it next to the field. Always pass a dispose function.
Blockly.DropDownDiv.showPositionedByField(
this, this.disposeWidget_.bind(this));
}
کد نمونه WidgetDiv
showEditor_() {
// Show the div. This automatically closes the dropdown if it is open.
// Always pass a dispose function.
Blockly.WidgetDiv.show(
this, this.sourceBlock_.RTL, this.widgetDispose_.bind(this));
// Create the widget HTML.
var widget = this.createWidget_();
Blockly.WidgetDiv.getDiv().appendChild(widget);
}
تمیز کردن
هر دو DropDownDiv و WidgetDiv عناصر HTML ویجت را از بین می برند، اما شما باید به صورت دستی هر شنونده رویدادی را که روی آن عناصر اعمال کرده اید، دور بریزید.
widgetDispose_() {
for (let i = this.editorListeners_.length, listener;
listener = this.editorListeners_[i]; i--) {
Blockly.browserEvents.unbind(listener);
this.editorListeners_.pop();
}
}
تابع dispose
در یک زمینه null
در DropDownDiv
فراخوانی می شود. در WidgetDiv
در متن WidgetDiv
نامیده می شود. در هر صورت، همانطور که در مثالهای DropDownDiv
و WidgetDiv
در بالا نشان داده شده است، هنگام ارسال یک تابع dispose، بهتر است از تابع bind استفاده کنید.
← برای اطلاعات در مورد دفع غیر اختصاصی به دفع سردبیران به دفع مراجعه کنید.
به روز رسانی صفحه نمایش روی بلوک
از عملکرد render_
برای به روزرسانی صفحه نمایش در بلوک استفاده می شود تا با مقدار داخلی آن مطابقت داشته باشد.
نمونه های رایج عبارتند از:
- تغییر متن (کشویی)
- تغییر رنگ (رنگ)
پیش فرض ها
عملکرد پیش فرض render_
متن نمایش را به نتیجه عملکرد getDisplayText_
تنظیم می کند. عملکرد getDisplayText_
پس از کوتاه شدن برای احترام به حداکثر طول متن ، ویژگی value_
Field را به یک رشته باز می گرداند.
اگر از صفحه نمایش پیش فرض در بلوک استفاده می کنید و رفتار متنی پیش فرض برای زمینه شما کار می کند ، نیازی به غلبه بر render_
نیست.
اگر رفتار متنی پیش فرض برای قسمت شما کار می کند ، اما صفحه نمایش روی بلوک شما دارای عناصر استاتیک دیگری است ، می توانید عملکرد پیش فرض render_
را فراخوانی کنید ، اما برای به روزرسانی در اندازه فیلد ، باید آن را نادیده بگیرید.
اگر رفتار پیش فرض متن برای زمینه شما کار نمی کند ، یا صفحه نمایش در بلوک شما دارای عناصر پویا دیگری است ، شما نیاز به تنظیم عملکرد render_
دارید.
سفارشی سازی رندر
اگر رفتار پیش فرض رندر برای زمینه شما مؤثر نباشد ، باید رفتار رندر سفارشی را تعریف کنید. این می تواند شامل هر چیزی از تنظیم متن نمایش سفارشی ، تغییر عناصر تصویر ، به روزرسانی رنگ های پس زمینه باشد.
تمام تغییرات ویژگی DOM قانونی است ، تنها دو موردی که باید به خاطر بسپارید عبارتند از:
- ایجاد DOM باید در حین اولیه سازی انجام شود ، زیرا کارآمدتر است.
- شما همیشه باید ویژگی
size_
به روز کنید تا با اندازه صفحه نمایش بلوک مطابقت داشته باشد.
render_() {
switch(this.value_.hat) {
case 'Stovepipe':
this.stovepipe_.style.display = '';
break;
case 'Crown':
this.crown_.style.display = '';
break;
case 'Mask':
this.mask_.style.display = '';
break;
case 'Propeller':
this.propeller_.style.display = '';
break;
case 'Fedora':
this.fedora_.style.display = '';
break;
}
switch(this.value_.pattern) {
case 'Dots':
this.shellPattern_.setAttribute('fill', 'url(#polkadots)');
break;
case 'Stripes':
this.shellPattern_.setAttribute('fill', 'url(#stripes)');
break;
case 'Hexagons':
this.shellPattern_.setAttribute('fill', 'url(#hexagons)');
break;
}
this.textContent_.nodeValue = this.value_.turtleName;
this.updateSize_();
}
اندازه به روزرسانی
به روزرسانی ویژگی size_
یک فیلد بسیار مهم است ، زیرا کد ارائه بلوک را نحوه قرار دادن این قسمت به شما اطلاع می دهد. بهترین راه برای فهمیدن دقیقاً این size_
با آزمایش است.
updateSize_() {
const bbox = this.movableGroup_.getBBox();
let width = bbox.width;
let height = bbox.height;
if (this.borderRect_) {
width += this.constants_.FIELD_BORDER_RECT_X_PADDING * 2;
height += this.constants_.FIELD_BORDER_RECT_X_PADDING * 2;
this.borderRect_.setAttribute('width', width);
this.borderRect_.setAttribute('height', height);
}
// Note how both the width and the height can be dynamic.
this.size_.width = width;
this.size_.height = height;
}
تطبیق رنگهای بلوک
اگر می خواهید عناصر فیلد خود با رنگ های بلوکی که به آن وصل شده اند مطابقت داشته باشد ، باید از روش applyColour
غلبه کنید. شما می خواهید از طریق خاصیت سبک بلوک به رنگ دسترسی پیدا کنید.
applyColour() {
const sourceBlock = this.sourceBlock_;
if (sourceBlock.isShadow()) {
this.arrow_.style.fill = sourceBlock.style.colourSecondary;
} else {
this.arrow_.style.fill = sourceBlock.style.colourPrimary;
}
}
به روزرسانی ویرایش
از عملکرد updateEditable
می توان برای تغییر نحوه ظاهر شدن قسمت شما بسته به اینکه قابل ویرایش باشد یا خیر ، استفاده شود. عملکرد پیش فرض باعث می شود که پس زمینه در صورتی که قابل ویرایش نباشد ، پاسخ شناور (مرز) نداشته باشد. صفحه نمایش در بلوک بسته به قابلیت ویرایش آن نباید اندازه را تغییر دهد ، اما تمام تغییرات دیگر مجاز است.
updateEditable() {
if (!this.fieldGroup_) {
// Not initialized yet.
return;
}
super.updateEditable();
const group = this.getClickTarget_();
if (!this.isCurrentlyEditable()) {
group.style.cursor = 'not-allowed';
} else {
group.style.cursor = this.CURSOR;
}
}
سریال سازی
سریال سازی در مورد صرفه جویی در وضعیت حوزه شما است تا بعداً در فضای کاری بارگیری شود.
وضعیت فضای کاری شما همیشه شامل ارزش این زمینه است ، اما می تواند وضعیت دیگری مانند وضعیت UI حوزه شما را نیز شامل شود. به عنوان مثال ، اگر زمینه شما یک نقشه بزرگنمایی بود که به کاربر امکان انتخاب کشورها را می داد ، می توانید سطح زوم را نیز سریال کنید.
اگر فیلد شما قابل سریال است ، باید ویژگی SERIALIZABLE
را روی true
تنظیم کنید.
Blockly دو مجموعه قلاب سریال سازی را برای زمینه ها فراهم می کند. یک جفت قلاب با سیستم سریال سازی جدید JSON کار می کند و جفت دیگر با سیستم سریال سازی XML قدیمی کار می کند.
saveState
و loadState
saveState
و loadState
قلاب های سریال سازی هستند که با سیستم سریال سازی جدید JSON کار می کنند.
در بعضی موارد شما نیازی به تهیه این موارد ندارید ، زیرا اجرای پیش فرض کار خواهد کرد. اگر (1) قسمت شما یک زیر کلاس مستقیم از کلاس پایه Blockly.Field
باشد ، (2) مقدار شما یک نوع سریال JSON است ، و (3) شما فقط باید ارزش را سریال کنید ، سپس اجرای پیش فرض فقط خوب کار خواهد کرد!
در غیر این صورت ، عملکرد saveState
شما باید یک شیء/مقدار سریال JSON را که نشان دهنده وضعیت فیلد است ، برگرداند. و عملکرد loadState
شما باید همان شیء/مقدار سریال JSON را بپذیرد و آن را در قسمت اعمال کند.
saveState() {
return {
'country': this.getValue(), // Value state
'zoom': this.getZoomLevel(), // UI state
};
}
loadState(state) {
this.setValue(state['country']);
this.setZoomLevel(state['zoom']);
}
سریال سازی کامل و داده های پشتیبان
saveState
همچنین یک پارامتر اختیاری doFullSerialization
دریافت می کند. این توسط زمینه هایی استفاده می شود که به طور معمول از سریال های سریال متفاوت استفاده می کنند (مانند مدل های داده پشتیبان). این پارامتر نشان می دهد که حالت ارجاع شده در صورت عدم استفاده از بلوک در دسترس نخواهد بود ، بنابراین این زمینه باید تمام سریال سازی را انجام دهد. به عنوان مثال ، وقتی یک بلوک جداگانه سریال می شود ، یا هنگامی که یک بلوک کپی شده است ، صادق است.
دو مورد استفاده متداول برای این موارد عبارتند از:
- هنگامی که یک بلوک جداگانه در یک فضای کاری بارگیری می شود که در آن مدل داده های پشتیبان وجود ندارد ، این زمینه اطلاعات کافی در حالت خود برای ایجاد یک مدل داده جدید دارد.
- هنگامی که یک بلوک کپی شده است ، این زمینه همیشه به جای مراجعه به یک مورد موجود ، یک مدل داده پشتیبان جدید ایجاد می کند.
یک زمینه که از این استفاده می کند ، زمینه متغیر داخلی است. به طور معمول ، شناسه متغیری را که به آن اشاره می کند سریال می کند ، اما اگر doFullSerialization
درست باشد ، تمام وضعیت خود را سریال می کند.
saveState(doFullSerialization) {
const state = {'id': this.variable_.getId()};
if (doFullSerialization) {
state['name'] = this.variable_.name;
state['type'] = this.variable_.type;
}
return state;
}
loadState(state) {
const variable = Blockly.Variables.getOrCreateVariablePackage(
this.getSourceBlock().workspace,
state['id'],
state['name'], // May not exist.
state['type']); // May not exist.
this.setValue(variable.getId());
}
قسمت متغیر این کار را انجام می دهد تا اطمینان حاصل شود که اگر در یک فضای کاری که متغیر آن وجود ندارد بارگذاری شود ، می تواند متغیر جدیدی را برای مرجع ایجاد کند.
toXml
و fromXml
toXml
و fromXml
قلاب های سریال سازی هستند که با سیستم سریال سازی XML قدیمی کار می کنند. فقط در صورت لزوم از این قلاب ها استفاده کنید (به عنوان مثال در حال کار روی یک پایگاه قدیمی کد هستید که هنوز مهاجرت نکرده است) ، در غیر این صورت از saveState
و loadState
استفاده کنید.
عملکرد toXml
شما باید یک گره XML را که نشان دهنده وضعیت میدان است ، برگرداند. و عملکرد fromXml
شما باید همان گره XML را بپذیرد و آن را در قسمت اعمال کند.
toXml(fieldElement) {
fieldElement.textContent = this.getValue();
fieldElement.setAttribute('zoom', this.getZoomLevel());
return fieldElement;
}
fromXml(fieldElement) {
this.setValue(fieldElement.textContent);
this.setZoomLevel(fieldElement.getAttribute('zoom'));
}
خصوصیات قابل ویرایش و سریال
خاصیت EDITABLE
مشخص می کند که آیا این زمینه باید از UI برخوردار باشد تا نشان دهد که می توان با آن تعامل داشت. این به طور پیش فرض به true
است.
ویژگی SERIALIZABLE
تعیین می کند که آیا این زمینه باید سریال شود یا خیر. این به طور پیش فرض false
است. اگر این ویژگی true
باشد ، ممکن است شما نیاز به ارائه سریال سازی و توابع deserialization داشته باشید (به سریال سازی مراجعه کنید).
سفارشی کردن مکان نما
ویژگی CURSOR
مکان نما را که کاربران هنگام شناور در قسمت شما می بینند ، تعیین می کند. این باید یک رشته مکان نما CSS معتبر باشد. این پیش فرض به مکان نما تعریف شده توسط .blocklyDraggable
، که مکان نما Grab است.