একটি নতুন ক্ষেত্রের ধরন তৈরি করা হচ্ছে

একটি নতুন ফিল্ড টাইপ তৈরি করার আগে, ক্ষেত্রগুলি কাস্টমাইজ করার জন্য অন্যান্য পদ্ধতিগুলির মধ্যে একটি আপনার প্রয়োজন অনুসারে কিনা তা বিবেচনা করুন। যদি আপনার অ্যাপ্লিকেশনের একটি নতুন মান টাইপ সঞ্চয় করার প্রয়োজন হয়, অথবা আপনি একটি বিদ্যমান মান প্রকারের জন্য একটি নতুন UI তৈরি করতে চান, তাহলে আপনাকে সম্ভবত একটি নতুন ফিল্ড টাইপ তৈরি করতে হবে।

একটি নতুন ক্ষেত্র তৈরি করতে, নিম্নলিখিতগুলি করুন:

  1. একটি কনস্ট্রাক্টর বাস্তবায়ন করুন
  2. একটি JSON কী নিবন্ধন করুন এবং fromJson প্রয়োগ করুন
  3. অন-ব্লক UI এবং ইভেন্ট শ্রোতাদের সূচনা পরিচালনা করুন
  4. ইভেন্ট শ্রোতাদের নিষ্পত্তি হ্যান্ডেল (ইউআই নিষ্পত্তি আপনার জন্য পরিচালনা করা হয়)।
  5. মান হ্যান্ডলিং বাস্তবায়ন .
  6. অ্যাক্সেসযোগ্যতার জন্য আপনার ক্ষেত্রের মানের একটি পাঠ্য-প্রতিনিধিত্ব যোগ করুন
  7. অতিরিক্ত কার্যকারিতা যোগ করুন যেমন:
  8. আপনার ক্ষেত্রের অতিরিক্ত দিকগুলি কনফিগার করুন, যেমন:

এই বিভাগটি অনুমান করে যে আপনি এনাটমি অফ এ ফিল্ডের বিষয়বস্তু পড়েছেন এবং তার সাথে পরিচিত।

কাস্টম ফিল্ডের উদাহরণের জন্য কাস্টম ফিল্ড ডেমো দেখুন।

একটি কনস্ট্রাক্টর বাস্তবায়ন

ক্ষেত্রের নির্মাণকারী ক্ষেত্রের প্রাথমিক মান সেট আপ করার জন্য এবং ঐচ্ছিকভাবে একটি স্থানীয় যাচাইকারী সেট আপ করার জন্য দায়ী। সোর্স ব্লক ইনিশিয়ালাইজেশনের সময় কাস্টম ফিল্ডের কনস্ট্রাক্টরকে ডাকা হয় সোর্স ব্লক JSON বা JavaScript-এ সংজ্ঞায়িত করা হোক না কেন। সুতরাং, নির্মাণের সময় কাস্টম ক্ষেত্রের উত্স ব্লকে অ্যাক্সেস নেই।

নিম্নলিখিত কোড নমুনা GenericField নামে একটি কাস্টম ক্ষেত্র তৈরি করে:

class GenericField extends Blockly.Field {
  constructor(value, validator) {
    super(value, validator);

    this.SERIALIZABLE = true;
  }
}

পদ্ধতি স্বাক্ষর

ফিল্ড কনস্ট্রাক্টররা সাধারণত একটি মান এবং একটি স্থানীয় যাচাইকারী গ্রহণ করে। মানটি ঐচ্ছিক, এবং যদি আপনি একটি মান পাস না করেন (অথবা আপনি এমন একটি মান পাস করেন যা শ্রেণী যাচাইকরণ ব্যর্থ হয়) তাহলে সুপারক্লাসের ডিফল্ট মান ব্যবহার করা হবে। ডিফল্ট Field ক্লাসের জন্য, সেই মানটি null । আপনি যদি সেই ডিফল্ট মানটি না চান, তাহলে একটি উপযুক্ত মান পাস করতে ভুলবেন না। যাচাইকারী প্যারামিটার শুধুমাত্র সম্পাদনাযোগ্য ক্ষেত্রগুলির জন্য উপস্থিত থাকে এবং সাধারণত ঐচ্ছিক হিসাবে চিহ্নিত করা হয়। ভ্যালিডেটর ডক্সে যাচাইকারীদের সম্পর্কে আরও জানুন।

গঠন

আপনার কনস্ট্রাক্টরের ভিতরের যুক্তিটি এই প্রবাহটি অনুসরণ করা উচিত:

  1. উত্তরাধিকারসূত্রে প্রাপ্ত সুপার কনস্ট্রাক্টরকে কল করুন (সমস্ত কাস্টম ক্ষেত্রগুলি Blockly.Field বা এর একটি সাবক্লাস থেকে উত্তরাধিকারসূত্রে পাওয়া উচিত) সঠিকভাবে মানটি শুরু করতে এবং আপনার ক্ষেত্রের জন্য স্থানীয় যাচাইকারী সেট করুন৷
  2. যদি আপনার ক্ষেত্রটি সিরিয়ালাইজযোগ্য হয় তবে কনস্ট্রাক্টরে সংশ্লিষ্ট সম্পত্তি সেট করুন। সম্পাদনাযোগ্য ক্ষেত্রগুলি অবশ্যই ক্রমিকযোগ্য হতে হবে এবং ক্ষেত্রগুলি ডিফল্টরূপে সম্পাদনাযোগ্য, তাই আপনার সম্ভবত এই বৈশিষ্ট্যটিকে সত্য হিসাবে সেট করা উচিত যদি না আপনি জানেন যে এটি সিরিয়ালাইজ করা উচিত নয়।
  3. ঐচ্ছিক: অতিরিক্ত কাস্টমাইজেশন প্রয়োগ করুন (উদাহরণস্বরূপ, লেবেল ক্ষেত্রগুলি একটি CSS ক্লাস পাস করার অনুমতি দেয়, যা পরে পাঠ্যে প্রয়োগ করা হয়)।

JSON এবং নিবন্ধন

JSON ব্লক সংজ্ঞায় , ক্ষেত্রগুলিকে একটি স্ট্রিং দ্বারা বর্ণনা করা হয় (যেমন field_number , field_textinput )। ব্লকলি এই স্ট্রিংগুলি থেকে ফিল্ড অবজেক্টে একটি মানচিত্র বজায় রাখে এবং নির্মাণের সময় উপযুক্ত বস্তুতে fromJson কল করে।

এই ম্যাপে আপনার ফিল্ডের ধরন যোগ করতে Blockly.fieldRegistry.register এ কল করুন, ফিল্ড ক্লাসে দ্বিতীয় আর্গুমেন্ট হিসেবে পাস করুন:

Blockly.fieldRegistry.register('field_generic', GenericField);

আপনাকে আপনার fromJson ফাংশনটিও সংজ্ঞায়িত করতে হবে। আপনার ইমপ্লিমেন্টেশনের প্রথমে রিপ্লেস মেসেজ রেফারেন্স ব্যবহার করে যেকোন স্ট্রিং টেবিলের রেফারেন্স ডিরেফার করা উচিত এবং তারপর কনস্ট্রাক্টরের কাছে মানগুলি পাস করা উচিত।

GenericField.fromJson = function(options) {
  const value = Blockly.utils.parsing.replaceMessageReferences(
      options['value']);
  return new CustomFields.GenericField(value);
};

শুরু করা হচ্ছে

যখন আপনার ক্ষেত্রটি তৈরি করা হয়, তখন এটি মূলত শুধুমাত্র একটি মান ধারণ করে। সূচনা হল যেখানে DOM তৈরি করা হয়, মডেল তৈরি করা হয় (যদি ক্ষেত্রের একটি মডেল থাকে), এবং ঘটনাগুলি আবদ্ধ থাকে।

অন-ব্লক ডিসপ্লে

ইনিশিয়ালাইজেশনের সময় আপনি ফিল্ডের অন-ব্লক ডিসপ্লের জন্য প্রয়োজনীয় কিছু তৈরি করার জন্য দায়ী।

ডিফল্ট, ব্যাকগ্রাউন্ড এবং টেক্সট

ডিফল্ট initView ফাংশন একটি হালকা রঙের rect উপাদান এবং একটি text উপাদান তৈরি করে। আপনি যদি চান যে আপনার ফিল্ডে এই দুটোই থাকুক এবং কিছু অতিরিক্ত গুডিও থাকুক, আপনার বাকি DOM উপাদান যোগ করার আগে সুপারক্লাস initView ফাংশনে কল করুন। আপনি যদি চান যে আপনার ফিল্ডে এই উপাদানগুলির মধ্যে একটি থাকুক, তবে উভয়ই না থাকুক, আপনি createBorderRect_ বা createTextElement_ ফাংশন ব্যবহার করতে পারেন।

DOM নির্মাণ কাস্টমাইজ করা হচ্ছে

যদি আপনার ক্ষেত্রটি একটি সাধারণ পাঠ্য ক্ষেত্র হয় (যেমন পাঠ্য ইনপুট ), DOM নির্মাণ আপনার জন্য পরিচালনা করা হবে। অন্যথায় আপনার ক্ষেত্রের ভবিষ্যত রেন্ডারিংয়ের সময় আপনার প্রয়োজন হবে এমন DOM উপাদানগুলি তৈরি করতে আপনাকে initView ফাংশনটি ওভাররাইড করতে হবে।

উদাহরণস্বরূপ, একটি ড্রপডাউন ক্ষেত্রে ছবি এবং পাঠ্য উভয়ই থাকতে পারে। initView এ এটি একটি একক চিত্র উপাদান এবং একটি একক পাঠ্য উপাদান তৈরি করে। তারপর render_ চলাকালীন এটি সক্রিয় উপাদানটি দেখায় এবং নির্বাচিত বিকল্পের ধরণের উপর ভিত্তি করে অন্যটিকে লুকিয়ে রাখে।

DOM উপাদান তৈরি করা হয় Blockly.utils.dom.createSvgElement পদ্ধতি ব্যবহার করে, অথবা ঐতিহ্যগত DOM তৈরির পদ্ধতি ব্যবহার করে করা যেতে পারে।

একটি ক্ষেত্রের অন-ব্লক প্রদর্শনের প্রয়োজনীয়তাগুলি হল:

  • সমস্ত DOM উপাদান অবশ্যই ক্ষেত্রের fieldGroup_ এর সন্তান হতে হবে। ক্ষেত্র গ্রুপ স্বয়ংক্রিয়ভাবে তৈরি করা হয়.
  • সমস্ত DOM উপাদানগুলিকে অবশ্যই ক্ষেত্রের রিপোর্ট করা মাত্রার মধ্যে থাকতে হবে৷

আপনার অন-ব্লক ডিসপ্লে কাস্টমাইজ এবং আপডেট করার বিষয়ে আরও বিশদ বিবরণের জন্য রেন্ডারিং বিভাগটি দেখুন।

টেক্সট সিম্বল যোগ করা হচ্ছে

আপনি যদি একটি ক্ষেত্রের পাঠ্যে প্রতীক যোগ করতে চান (যেমন কোণ ক্ষেত্রের ডিগ্রি চিহ্ন) আপনি প্রতীক উপাদানটি (সাধারণত <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 ফাংশনের ভিতরে নিবন্ধনমুক্ত হতে হবে।

আপনি যদি আপনার ক্ষেত্রের ভিউ সঠিকভাবে শুরু করেন ( fieldGroup_ এ সমস্ত DOM উপাদান যুক্ত করে), তাহলে ক্ষেত্রের 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 তে সেট করা উচিত এবং অন-ব্লক ডিসপ্লের জন্য রেন্ডার_ ওভাররাইড করা উচিত যাতে value_ এর পরিবর্তে displayValue_ এর উপর ভিত্তি করে আপডেট করা যায়।

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_ প্রপার্টিতে ক্যাশ করা হয়। স্বতন্ত্রভাবে যাচাইকৃত বৈশিষ্ট্য সহ অবজেক্টকে ক্যাশ করার ফলে প্রতিটি সম্পত্তি পৃথকভাবে পুনরায় যাচাই করার পরিবর্তে শুধুমাত্র একটি !this.cacheValidatedValue_.property চেক করে, doValueInvalid_ ফাংশন আলাদাভাবে তাদের পরিচালনা করতে দেয়।

বহু-অংশের মান যাচাই করার জন্য এই প্যাটার্নটি স্থানীয় যাচাইকারীদের মধ্যেও ব্যবহার করা যেতে পারে কিন্তু বর্তমানে এই প্যাটার্নটি কার্যকর করার কোন উপায় নেই।

নোংরা_

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_ কল করবে। ড্রপডাউনডিভ এবং উইজেটডিভ নামে পরিচিত দুটি বিশেষ ডিভের মধ্যে যেকোনও একটি এইচটিএমএলকে মোড়ানোর মাধ্যমে আপনি আপনার সম্পাদকে যেকোন এইচটিএমএল প্রদর্শন করতে পারেন, যা ব্লকলির বাকি UI-এর উপরে ভাসমান থাকে।

DropDownDiv একটি ক্ষেত্রের সাথে সংযুক্ত একটি বাক্সের ভিতরে বসবাসকারী সম্পাদক প্রদান করতে ব্যবহৃত হয়। দৃশ্যমান সীমার মধ্যে থাকার সময় এটি স্বয়ংক্রিয়ভাবে মাঠের কাছাকাছি অবস্থান করে। অ্যাঙ্গেল পিকার এবং কালার পিকার হল DropDownDiv ভালো উদাহরণ।

অ্যাঙ্গেল পিকারের ছবি

WidgetDiv এমন সম্পাদক সরবরাহ করতে ব্যবহৃত হয় যা বাক্সের ভিতরে থাকে না। এইচটিএমএল টেক্সট ইনপুট বক্স দিয়ে ক্ষেত্রটিকে কভার করতে নম্বর ক্ষেত্র WidgetDiv ব্যবহার করে। যখন DropDownDiv আপনার জন্য পজিশনিং পরিচালনা করে, WidgetDiv তা করে না। উপাদান ম্যানুয়ালি অবস্থান করা প্রয়োজন হবে. স্থানাঙ্ক সিস্টেমটি উইন্ডোর উপরের বাম দিকের তুলনায় পিক্সেল স্থানাঙ্কে রয়েছে। টেক্সট ইনপুট এডিটর হল WidgetDiv এর একটি ভালো উদাহরণ।

টেক্সট ইনপুট এডিটরের ছবি

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 ফাংশনটিকে DropDownDiv এ একটি null প্রসঙ্গে বলা হয়। WidgetDiv এ এটি WidgetDiv এর প্রসঙ্গে বলা হয়। উভয় ক্ষেত্রেই একটি ডিসপোজ ফাংশন পাস করার সময় bind ফাংশন ব্যবহার করা ভাল, যেমন উপরের DropDownDiv এবং WidgetDiv উদাহরণগুলিতে দেখানো হয়েছে।

→ ডিসপোজিং সম্পর্কে তথ্যের জন্য সম্পাদকদের ডিসপোজ করার জন্য নির্দিষ্ট নয় ডিসপোজিং দেখুন।

অন-ব্লক ডিসপ্লে আপডেট করা হচ্ছে

render_ ফাংশনটি ফিল্ডের অন-ব্লক ডিসপ্লে আপডেট করতে ব্যবহৃত হয় যাতে এর অভ্যন্তরীণ মানের সাথে মেলে।

সাধারণ উদাহরণ অন্তর্ভুক্ত:

  • পাঠ্য পরিবর্তন করুন (ড্রপডাউন)
  • রঙ (রঙ) পরিবর্তন করুন

পূর্ব নির্ধারিত

ডিফল্ট render_ ফাংশনটি প্রদর্শন পাঠ্যকে getDisplayText_ ফাংশনের ফলাফলে সেট করে। getDisplayText_ ফাংশনটি ফিল্ডের value_ প্রপার্টি কাস্ট করে একটি স্ট্রিং-এ ফেরত দেয়, যখন এটি সর্বাধিক পাঠ্যের দৈর্ঘ্যকে সম্মান করার জন্য কেটে ফেলা হয়।

আপনি যদি ডিফল্ট অন-ব্লক ডিসপ্লে ব্যবহার করেন এবং ডিফল্ট পাঠ্য আচরণ আপনার ক্ষেত্রের জন্য কাজ করে, তাহলে আপনাকে render_ ওভাররাইড করার দরকার নেই।

যদি ডিফল্ট টেক্সট আচরণ আপনার ক্ষেত্রের জন্য কাজ করে, কিন্তু আপনার ক্ষেত্রের অন-ব্লক ডিসপ্লেতে অতিরিক্ত স্ট্যাটিক উপাদান থাকে, আপনি ডিফল্ট render_ ফাংশনটিকে কল করতে পারেন, কিন্তু ফিল্ডের আকার আপডেট করার জন্য আপনাকে এখনও এটিকে ওভাররাইড করতে হবে।

যদি ডিফল্ট পাঠ্য আচরণ আপনার ক্ষেত্রের জন্য কাজ না করে, বা আপনার ক্ষেত্রের অন-ব্লক ডিসপ্লেতে অতিরিক্ত গতিশীল উপাদান থাকে, তাহলে আপনাকে render_ ফাংশনটি কাস্টমাইজ করতে হবে।

ফ্লোচার্ট বর্ণনা করছে যে কিভাবে রেন্ডারকে ওভাররাইড করতে হবে তার সিদ্ধান্ত নিতে হবে_

রেন্ডারিং কাস্টমাইজ করা হচ্ছে

যদি ডিফল্ট রেন্ডারিং আচরণ আপনার ক্ষেত্রের জন্য কাজ না করে, তাহলে আপনাকে কাস্টম রেন্ডারিং আচরণ সংজ্ঞায়িত করতে হবে। এতে কাস্টম ডিসপ্লে টেক্সট সেট করা থেকে শুরু করে ইমেজ এলিমেন্ট পরিবর্তন করা, পটভূমির রং আপডেট করা পর্যন্ত যেকোনো কিছু জড়িত থাকতে পারে।

সমস্ত DOM বৈশিষ্ট্য পরিবর্তন আইনী, শুধুমাত্র দুটি জিনিস মনে রাখতে হবে:

  1. DOM তৈরি শুরু করার সময় পরিচালনা করা উচিত, কারণ এটি আরও দক্ষ।
  2. অন-ব্লক ডিসপ্লের আকারের সাথে মেলে আপনার সর্বদা 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 সেট করতে হবে।

ব্লকলি ক্ষেত্রগুলির জন্য দুটি সেট সিরিয়ালাইজেশন হুক সরবরাহ করে। এক জোড়া হুক নতুন 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 দ্বারা সংজ্ঞায়িত কার্সারের সাথে ডিফল্ট হয়, যা গ্র্যাব কার্সার।