ٹائپ رائٹر ایفیکٹ کسی کو اونچی آواز میں سوچتے ہوئے دیکھنے کا ڈیجیٹل متبادل ہے۔ متن ایک ایک کر کے ظاہر ہوتا ہے، جیسے کوئی حقیقی ہاتھ حقیقی بٹن دبا رہا ہو۔ آپ اسے پورٹ فولیو سائٹس کے ہیرو سیکشنز میں، براؤزر پر مبنی ٹرمینل ایمولیٹرز میں، اور اے آئی اسسٹنٹس کے چیٹ ونڈوز میں دیکھتے ہیں جو یہ ثابت کرنا چاہتے ہیں کہ وہ کوئی پہلے سے تیار شدہ متن دکھانے کے بجائے جواب "ٹائپ" کر رہے ہیں۔ جب اسے اچھے طریقے سے کیا جائے تو یہ تجسس پیدا کرتا ہے۔ جب اسے بری طرح کیا جائے تو یہ ایسا محسوس ہوتا ہے جیسے 1987 میں کوئی پرنٹر پھنس گیا ہو۔

یہ پیٹرن کیوں برقرار رہتا ہے

کمپیوٹر معلومات فوری طور پر فراہم کرتے ہیں۔ انسان ایسا نہیں کرتے۔ ان دونوں رفتاروں کے درمیان کا فرق مفید ہے۔ ٹائپ رائٹر ایفیکٹ انسانی رفتار کی نقل کر کے اس فرق کو پاٹتا ہے۔ ایک لینڈنگ پیج پر، یہ نظر کو لفظ بہ لفظ ہیڈ لائن پر لے جا سکتا ہے تاکہ وزٹرز صرف سرسری نظر ڈالنے کے بجائے اصل ویلیو پروپوزیشن کو پڑھیں۔ ایک ٹرمینل ایمولیٹر میں، یہ یہ وہم پیدا کرتا ہے کہ کمانڈز ریئل ٹائم میں چل رہی ہیں۔ ایک چیٹ بوٹ انٹرفیس میں، یہ تال (rhythm) یہ اشارہ دیتی ہے کہ جواب ڈیٹا بیس سے نکالنے کے بجائے اسی وقت تیار کیا جا رہا ہے۔

لیکن یہ ایفیکٹ صرف تب ہی کام کرتا ہے جب اس کے میکانزم صارف کا احترام کریں۔ ایک ہی جیسے وقفوں کا یکساں ٹک-ٹک-ٹک روبوٹک محسوس ہوتا ہے۔ اس سے بھی بدتر، ایک ایسا نفاذ جو اسسٹسو ٹیکنالوجی کو نظر انداز کرتا ہے، ایک دلچسپ بصری سجاوٹ کو ایک پریشان کن رکاوٹ میں بدل سکتا ہے۔ مقصد صارف کی رفتار کو کم کرنا نہیں ہے؛ بلکہ صرف اتنی رکاوٹ پیدا کرنا ہے کہ انٹرفیس زندہ محسوس ہو۔

اسے Recursive setTimeout کے ساتھ بنائیں

setTimeout سے شروع کریں، اور setInterval کو ہاتھ نہ لگائیں۔ اس کا فرق اس سے کہیں زیادہ ہے جتنا یہ نظر آتا ہے۔

setInterval ضدی ہے۔ یہ آپ کے اسکرپٹ یا براؤزر کے مین تھریڈ میں ہو رہی دیگر چیزوں سے قطع نظر ہر n ملی سیکنڈ بعد چلتا ہے۔ اگر آپ کے لاجک کو عام کی اسٹروکس کے درمیان 50 ملی سیکنڈ کا وقفہ چاہیے لیکن وقفہ (punctuation) کے بعد 150 ملی سیکنڈ کا وقفہ چاہیے، تو setInterval اس کے مطابق ڈھل نہیں سکتا۔ آپ اسے اضافی کنڈیشنل لاجک میں لپیٹتے چلے جاتے ہیں، ریس کنڈیشنز سے لڑتے ہیں، اور آخر کار اسے اتنی بار کلیئر اور ری سیٹ کرتے ہیں کہ کوڈ اسٹیٹ مینجمنٹ کا ڈراونا خواب بن جاتا ہے۔ فکسڈ انٹرویلز اس وقت ناکام ہو جاتے ہیں جب آپ کو متغیر رفتار (variable speeds) کی ضرورت ہوتی ہے۔

Recursive setTimeout اس مسئلے کو حل کرتا ہے کیونکہ یہ ہر مرحلے کو اگلے مرحلے کے اصول خود طے کرنے کی اجازت دیتا ہے۔ اسے ایک چھوٹی اسٹیٹ مشین کے طور پر سمجھیں۔ آپ چند ویری ایبلز برقرار رکھتے ہیں: موجودہ اسٹرنگ، موجودہ کریکٹر انڈیکس، ایک بولین فلیگ کہ آپ ٹائپ کر رہے ہیں یا ڈیلیٹ، اور ایک textIndex کاؤنٹر تاکہ آپ متعدد اسٹرنگز کے ذریعے لوپ کر سکیں۔ فنکشن ایک کریکٹر شامل کرتا ہے، چیک کرتا ہے کہ وہ جملے میں کہاں ہے، پھر سیاق و سباق کے مطابق وقفے کے ساتھ اپنی اگلی کال شیڈول کرتا ہے۔

مثال کے طور پر، آپ زیادہ تر کریکٹرز کو 50 ملی سیکنڈ پر ٹائپ کر سکتے ہیں، کوما کے بعد 150 ملی سیکنڈ تک سست ہو سکتے ہیں، اور ڈیلیٹ موڈ پر منتقل ہونے سے پہلے ایک مکمل جملے کے اختتام پر 800 ملی سیکنڈ کے لیے رک سکتے ہیں۔ آپ setInterval کے ساتھ یہ کام صفائی سے نہیں کر سکتے۔ Recursive setTimeout کے ساتھ، لاجک سادہ ہے:

if typing:
  append next character
  if at end of string:
    switch to pause mode
    schedule next call after 1000ms
if deleting:
  remove last character
  if string empty:
    increment textIndex
    load next string
    switch to typing mode

یہ ڈھانچہ صفائی (cleanup) کو بھی انتہائی آسان بنا دیتا ہے۔ ٹائم آؤٹ آئی ڈی (timeout ID) کو محفوظ رکھیں۔ جب کمپوننٹ ان ماؤنٹ ہو یا صارف صفحہ چھوڑ دے، تو ایک بار clearTimeout کال کریں۔ پس منظر میں بغیر مقصد کے چلنے والے انٹرویلز نہیں رہیں گے۔

کرسر کو خود بخود چمکنا چاہیے

چمکتا ہوا کرسر ایک بصری تفصیل ہے، ڈیٹا کا مسئلہ نہیں۔ اسے اپنے جاوا اسکرپٹ اسٹیٹ انجن سے دور رکھیں۔ ایک علیحدہ CSS اینیمیشن استعمال کریں جو ::after سوڈو ایلیمنٹ سے منسلک ہو یا آپ کے ٹیکسٹ کنٹینر کے آخر میں موجود ایک مخصوص <span پر ہو۔

ایک سادہ @keyframes blink جو step-end ٹائمنگ کے ساتھ opacity یا border-color کو تبدیل کرتا ہے، آپ کو ایک واضح اور ہارڈ ویئر کے لیے موزوں پلس دیتا ہے جو کمپوزٹر پر چلتا ہے۔ جاوا اسکرپٹ کا کرسر کی نظر آنے کی صلاحیت کی مائیکرو مینجمنٹ کرنے سے کوئی لینا دینا نہیں ہونا چاہیے۔ اگر آپ اپنے setTimeout ریکرژن کے اندر سے ڈسپلے پراپرٹیز کو تبدیل کرتے ہیں، تو آپ ہر ایک کریکٹر پر غیر ضروری اسٹائل ری کیلکولیشنز پر مجبور کرتے ہیں۔ CSS کو جمالیات (aesthetics) سنبھالنے دیں۔ جاوا اسکرپٹ کو ترتیب (sequence) سنبھالنے دیں۔

textIndex کاؤنٹر کے ساتھ متعدد اسٹرنگز کے ذریعے لوپ کرنا بالکل سیدھا کام ہے۔ اپنی اسٹرنگز کو ایک ایرے (array) میں محفوظ کریں۔ جب اینیمیشن اپنا ڈیلیٹ مرحلہ مکمل کر لے اور کنٹینر خالی ہو جائے، تو ایرے کی لمبائی کے مطابق textIndex کو بڑھائیں، کریکٹر پوائنٹر کو صفر پر ری سیٹ کریں، اور دوبارہ ٹائپ کرنا شروع کریں۔ پورٹ فولیو سائٹس اسی طرح پیج کو ری لوڈ کیے بغیر اپنے کرداروں—["Developer", "Designer", "Writer"]—کے درمیان گردش کرتی ہیں۔

غلطیاں جو وہم کو توڑ دیتی ہیں

غیر پیشہ ورانہ نفاذ میں تین غلطیاں بار بار سامنے آتی ہیں۔

setInterval کا استعمال۔ ہم پہلے ہی متغیر رفتار (variable-speed) کے مسئلے پر بات کر چکے ہیں، لیکن ایک باریک مسئلہ بھی موجود ہے۔ اگر آپ کا DOM اپ ڈیٹ کبھی سست ہو جائے—مثال کے طور پر اس لیے کہ براؤزر لے آؤٹ شفٹ (layout shift) پینٹ کر رہا ہے—تو setInterval مسلسل چلتا رہتا ہے۔ اس کے نتیجے میں آپ کو اوورلیپنگ رائٹس (overlapping writes)، ڈپلکیت حروف، یا ایسی رائٹس کا سامنا کرنا پڑ سکتا ہے جو براؤزر کی رینڈرنگ کی رفتار سے زیادہ تیز ہوں۔ ریکرسو setTimeout اگلے مرحلے کے بارے میں سوچنے سے پہلے موجودہ مرحلے کے مکمل ہونے کا انتظار کرتا ہے۔

HTML کو ایسکیپ (escape) کرنا بھول جانا۔ اگر آپ کی سورس اسٹرنگز میں اینگل بریکٹس (angle brackets) شامل ہیں، اور آپ innerHTML کے ذریعے ایک وقت میں ایک حرف شامل کر رہے ہیں، تو آپ ٹیگز کو آدھا کر دیں گے۔ براؤزر پہلے <, پھر <s اور پھر <st دیکھے گا۔ یہ صحیح ٹیگ پارسنگ (tag parsing) کو روکتا ہے اور آپ کے پاس ٹوٹے ہوئے DOM نوڈز یا غیر متوقع اسٹائلنگ کیسیڈز (styling cascades) چھوڑ سکتا ہے۔ اگر آپ چاہتے ہیں کہ حروف بالکل ویسے ہی نظر آئیں، تو پہلے انہیں ایسکیپ کریں یا، اس سے بھی بہتر یہ کہ innerHTML کے بجائے textContent میں لکھیں۔ اگر آپ کو ٹائپ رائٹر آؤٹ پٹ کے اندر اسٹائل شدہ <span> ٹیگز کی واقعی ضرورت ہے، تو اسٹرنگ کو پہلے سے پروسیس کریں تاکہ کیریکٹر لوپ شروع کرنے سے پہلے آپ کو معلوم ہو کہ ٹیگز کہاں سے شروع اور ختم ہو رہے ہیں۔

رسائی (accessibility) کو نظر انداز کرنا۔ اسکرین ریڈرز کو ایک وقت میں ایک حرف پڑھنا پسند نہیں ہوتا۔ جیسے ہی آپ کا اسکرپٹ DOM میں ہر نیا حرف شامل کرتا ہے، کچھ معاون ٹیکنالوجیز (assistive technologies) پورے نوڈ کا دوبارہ اعلان کرتی ہیں، جس سے ادھورے الفاظ کی ایک مسلسل اور ٹوٹ پھوٹ والی آواز پیدا ہوتی ہے۔ یہ ان لوگوں کے لیے ایک ڈراؤنا خواب ہے جو سمعی نیویگیشن (auditory navigation) پر انحصار کرتے ہیں۔ اس کا حل پیچیدہ نہیں ہے: اس کنٹینر میں ایک aria-label شامل کریں جس میں مکمل اور حتمی متن موجود ہو۔ آپ aria-hidden="true" کے ذریعے اینیمیٹڈ ایلیمنٹ کو معاون ٹیکنالوجی سے مکمل طور پر چھپا بھی سکتے ہیں اور اسکرین ریڈرز کے لیے ایک بصری طور پر چھپی ہوئی (visually hidden) ساکن کاپی فراہم کر سکتے ہیں۔ بہر حال، صارفین کو اپنی کارکردگی دکھانے کے بجائے مکمل جملہ پہلے ہی فراہم کر دیں۔

اپنے ورژن کو بہتر بنانے کے طریقے

جب بنیادی لوپ درست طریقے سے کام کرنے لگے، تو آپ اضافی فیچرز شامل کر سکتے ہیں۔ لیکن جب تک بنیادی اصول مضبوط نہ ہوں، انہیں شامل کرنے کی خواہش سے پرہیز کریں۔

کی اسٹروک ساؤنڈ ایفیکٹس۔ ہر حرف پر ایک ہلکی سی کلک کی آواز اطمینان بخش ہو سکتی ہے، لیکن ویب صفحات پر آڈیو کا استعمال ایک خطرناک کام ہے۔ Web Audio API یا مختصر بفر کے ساتھ ایک ہلکے پھلکے Audio ایلیمنٹ کا استعمال کریں۔ پلے بیک ریٹ میں تھوڑا سا فرق لائیں—0.95 اور 1.05 کے درمیان—تاکہ ایک جیسی کلکس مصنوعی نہ لگیں۔ ہمیشہ براؤزر کی آٹو پلے پالیسیوں کا احترام کریں اور میوٹ (mute) ٹوگل فراہم کریں۔ صبح 9 بجے ایک ایسی پورٹ فولیو پیج جو خود بخود ٹائپنگ کی آوازیں نکال رہا ہو، صارفین کو سب سے تیزی سے دور بھگاتی ہے۔

ملٹی لائن ٹائپنگ۔ حقیقی ٹرمینل ونڈوز میں ٹیکسٹ ریپ (wrap) ہوتا ہے۔ اگر آپ کا متن لائن بریک سے گزرتا ہے، تو ایک سادہ border-right کرسر عجیب طریقے سے چھلانگ لگائے گا جب تک کہ آپ کا لے آؤٹ قابلِ پیش گوئی نہ ہو۔ اسٹرنگز کو نیو لائن (newline) کریکٹرز کے ذریعے تقسیم کریں اور ہر لائن کو اپنے الگ <span> میں رینڈر کریں، یا ایک پوزیشنڈ سوڈو ایلیمنٹ (positioned pseudo-element) استعمال کریں جو مواد کے اختتام کو ٹریک کرے۔ ٹیکسٹ ریپنگ کے معاملے میں محتاط رہیں؛ اگر کنٹینر کی چوڑائی تبدیل ہو جائے تو ان لائن بارڈر کے طور پر نافذ کردہ کرسر متن سے الگ ہو سکتا ہے۔ ٹرمینل اسٹائل کے لیے white-space: pre-wrap اور مونو اسپیسڈ (monospaced) فونٹ استعمال کرنے پر غور کریں، کیونکہ فکسڈ ویڈتھ حروف کرسر کی حساب کتاب کو بہت زیادہ قابلِ پیش گوئی بنا دیتے ہیں۔

ریئل ٹائم مارک ڈاؤن رینڈرنگ۔ یہ وہ جگہ ہے جہاں چیزیں پیچیدہ ہو جاتی ہیں۔ اگر آپ **bold** ٹائپ کرتے ہیں، تو آپ کے پاس ایک انتخاب ہے: یا تو اینٹرسک (asterisks) کو بالکل ویسے ہی رینڈر کریں جیسے وہ نظر آتے ہیں، یا انہیں فوری طور پر بولڈ اسٹائل میں تبدیل کر دیں۔ اگر آپ دوسرا راستہ چنتے ہیں، تو عمل کے دوران textContent سے innerHTML پر منتقل ہونے کا مطلب ہے کہ آپ کے ٹیکسٹ نوڈ کی حدود تبدیل ہو جائیں گی۔ کرسر کی پوزیشن ایک سردرد بن جاتی ہے کیونکہ HTML ٹیگز آپ کے نیچے DOM ٹری کو ہلا دیتے ہیں۔ ایک محفوظ طریقہ یہ ہے کہ خام مارک ڈاؤن اسٹرنگ کو عام طریقے سے ٹائپ کریں، پھر جب پوری اسٹرنگ اسکرین پر آ جائے تو رینڈر پاس (render pass) شروع کریں۔ اگر آپ کو واقعی لائیو فارمیٹنگ کی ضرورت ہے، تو دو تہیں برقرار رکھیں: ایک چھپا ہوا ٹائپ شدہ بفر اور ایک پارس شدہ بصری اوورلے (visual overlay)۔

ریورس ایفیکٹس۔ متن کو حذف کرنے کا مطلب یہ نہیں ہے کہ ہر بار ایک ایک کر کے بیک سپیس کیا جائے۔ آپ "سب کو منتخب کریں، پھر حذف کریں" (select all, then delete) جیسا ری سیٹ کر سکتے ہیں جو اگلی اسٹرنگ ٹائپ ہونے سے پہلے فوری طور پر فیلڈ کو صاف کر دے۔ یہ بہت زیادہ مشینی محسوس ہوتا ہے۔ متبادل کے طور پر، فی حرف 30 ملی سیکنڈ کی رفتار سے سست بیک سپیسنگ تناؤ پیدا کرتی ہے۔ دونوں کا امتزاج استعمال کریں: ٹائپنگ کی غلطی کو تیزی سے مٹائیں، تھوڑا رکیں، پھر عام رفتار سے حذف کرنا دوبارہ شروع کریں۔ یہ تبدیلی اس اثر میں انسانیت کا احساس پیدا کرتی ہے۔

اصل حاصلِ کلام

ٹائپ رائٹر ایفیکٹ ان UI سجاوٹوں میں سے ایک ہے جو سطح پر معمولی نظر آتی ہے اور اپنی پیچیدگی صرف تب ظاہر کرتی ہے جب آپ اسے بنا چکے ہوں۔ شروع کریں