اذهب إلى المحتوى

لوحة المتصدرين

  1. Ali Ahmed55

    Ali Ahmed55

    الأعضاء


    • نقاط

      5

    • المساهمات

      1352


  2. عبد الوهاب بومعراف

    • نقاط

      3

    • المساهمات

      927


  3. Hussain Abd Aljalil

    Hussain Abd Aljalil

    الأعضاء


    • نقاط

      2

    • المساهمات

      13


  4. ابراهيم الخضور

    • نقاط

      1

    • المساهمات

      164


المحتوى الأكثر حصولًا على سمعة جيدة

المحتوى الأعلى تقييمًا في 12/16/24 في كل الموقع

  1. السلام عليكم هو اي افضل حل لتعامل مع القيمه المفقود في بيانات طبيه ؟ وهل ان لو فيه عمود ناقص عندي فيه بيانات مفقود فا هل ان اجيب بيانات مريض تاني ده حل مناسب ؟
    2 نقاط
  2. السلام عليكم هو اي الفرق مابين العمودين دول ؟ عمود ال tce_div_match tce_div_match Bi-directional non-permissive 61 GvH non-permissive 353 HvG non-permissive 190 Permissive mismatched 1569 وعمود ال tce_match tce_match Fully matched 227 GvH non-permissive 348 HvG non-permissive 146 Permissive 1452 وهل اقدر استغني عن واحد وكمان العمود ال tce_match فيه 60% من البيانات مفقود ؟
    1 نقطة
  3. السلام عليكم انا عاوز امسح عمود فا هل الداله dropna بتمسح عمود والا صف ؟
    1 نقطة
  4. الدالة dropna في مكتبة pandas تستخدم بشكل أساسي لمسح الصفوف التي تحتوي على قيم مفقودة (NaN) لذلك إذا كنت ترغب في مسح عمود بالكامل، يمكنك استخدام drop مع تحديد اسم العمود كالآتي: df = df.drop(columns=['اسم العمود']) أما لمسح الصفوف نستخدم: df = df.dropna()
    1 نقطة
  5. وعليكم السلام ورحمة الله وبركاته. لا هذا ليس حلا جيدا وخاصة في البيانات الطبية حيث أنه ليس طبيعيا أن نقوم بوضع بيانات مريض إلى مريض أخر حيث كل شخص مختلف عن الأخر في الظروف الصحية و بنيته الجسدية والوراثية. فتخيل أن هناك بعض البيانات المفقودة لشخص ما وهذه البيانات المفقودة من المفترض أن لا تشخص هذا الإنسان بالمرض . ولكنك تقوم بوضع بيانات شخص أخر مريض في تلك البيانات . إذا أنت قمت بتزييف بيانات أو وضع بيانات خاطئة مما ستسبب مشاكل في المهمة التي تريد تنفيذها بناء على تلك البيانات الخاطئة وستجعل النموذج منحاز لبعض الفئات التي قمت بإستخدام بياناتها لمريض أخر. وتوجد لديك عدة طرق للتعامل مع تلك البيانات. فإذا كان لديك عدد قليل من القيم المفقودة في صفوف أو أعمدة معينة فهنا الطريقة المناسبة هي إزالة هذه الصفوف أو الأعمدة بالكامل حتى لا تؤثر على البيانات الأخرى. ولكن عيب هذه الطريقة أنه إذا كانت البيانات المفقودة كثيرة بالنسبة للبيانات الأخرى التي لديك فهنا ستفقد بيانات كثيرة مهمة ولن تكون جيدة. الطريقة الثانية هي إستبدال تلك القيم بالقيم الوسطية أو المتوسطة (Mean/Median) أو (Mode) وهذه الطريقة مناسبة إذا كانت البيانات التي لديك هي بيانات عددية مثل العمر أو ضغط الدم أو مستوى السكر في الدم فهنا يمكنك إستخدام أى قيم بديلة سواء المتوسط أو ال mean أو القيم اللتي تتكرر كثيرا وغيرها . ولكن من عيوب تلك الطريقة إذا كانت البيانات لا تتبع توزيع طبيعي بل توزيع عشوائي أو تحتوي قيم متطرفة (outliers) كثيرة. إذا كانت البيانات لديك قليلة وتوجد قيم مفقودة بها هنا يفضل البحث عن قيم جديدة أخرى والبحث عن مصادر جديدة حتي تكون لديك بيانات كثيرة تسمح لك بالتعامل معها.
    1 نقطة
  6. التعامل مع القيم المفقودة هو تحد شائع في مختلف مجالات البيانات وليس البيانات الطبية فقط فحتى المالية، الاجتماعية، والبيئية بل تشمل جميع أنواع البيانات التي تتأثر بفقدان المعلومات يمكنك مراجعة الإجابتين على هذا السؤال الذي يتعلق حول كيفية التعامل مع القيم المفقودة: أما بشأن استخدام بيانات مريض آخر لملء عمود مفقود يمكن أن يكون حلا مناسبا في بعض الحالات، بشرط أن تكون البيانات متشابهة من حيث الشروط السريرية والتجريبية لذا يجب أن تكون حذرا لأن هذا قد يؤدي إلى إدخال تحيزات أو أخطاء إذا كانت البيانات تختلف بشكل كبير لذا من المهم تقييم مدى تماثل البيانات والتأكد من عدم التأثير السلبي على جودة التحليل.
    1 نقطة
  7. السلام عليكم لدي سؤال وهو هل هناك في اكاديمية حسوب مجتمع خاص بالطلاب حتى استطيع التحدث معهم وحل المشكلات والمنافسة مابيننا واذا لم لكن هناك كيف اجد هذا المجتمعات؟
    1 نقطة
  8. انا لا اقصد على الاسئلة بشكل خاص بل اقصد على التواصل والمنافسة بين بعضنا لإن من الممكن جداً الشعور بالملل والخمول من فترة الى اخرى وهنا المنافسة بين بعضنا قد تشكل حالة جيدة للاستمرار والاندفاع اكثر للتعلم!
    1 نقطة
  9. هل يمكنك ان تدلني على مصدر موثوق لاتعلم منه الاندرويد استديو من A to Z وكيفية التعامل مع قواعد البيانات / حتى لو كان مدفوع المهم ان يكون مصدر ثقة
    1 نقطة
  10. الف شكراا لحضرتك جدا جزاك الله كل خير الف شكراا لحضرتك جدا بس سوال هل الازم اصلان ان اعمل الشرط ده يعني هيحصل اي لو معملتيش كده ؟
    1 نقطة
  11. قم بتعديل استعلام SQL الخاص بك لتنسيق حقل التاريخ بحيث يعرض التاريخ فقط بدون الوقت على سبيل المثال، يمكنك استخدام وظيفة CONVERT() في SQL لتحويل حقل "date" إلى "varchar" وتنسيقه كما تريد: SELECT CONVERT(VARCHAR(10), [date_field], 120) AS [formatted_date], ... FROM items هذا سيعيد حقل التاريخ بتنسيق "YYYY-MM-DD"، والذي من المفترض أن يتم عرضه بشكل صحيح في تقرير Crystal Reports.
    1 نقطة
  12. يصف هذا القسم مجموعةً من المعايير الحديثة لمكونات الويب، وهذه المعايير بصدد التطوير حاليًا. تُدعم بعض الميزات وتتكامل ضمن معايير HTML/DOM، بينما يبقى البعض الآخر في مرحلة الإعداد. ويمكنك تجربة الأمثلة في أي متصفح، لكن يبقى المتصفح كروم Chrome الأكثر حداثةً فيما يتعلق بدعم هذه الميزات، والسبب طبعًا هو أنّ أشخاصًا من Google هم من وضعوا العديد من هذه المواصفات. ما هو الشيء المشترك بين محطة الفضاء ومكونات الويب إن فكرة المكونات ليست جديدة، فقد استُعملت في العديد من إطارات العمل وفي منصات مختلفة، وذلك قبل الانتقال إلى تفاصيل إنجاز تلك الميزات. لنلقي نظرةً على الصورة التالية، والتي تمثل إنجازًا عظيمًا للإنسانية: إنها محطة الفضاء الدولية، وتمثل الصورة التالية المكوِّنات التي تتألف منها -تقريبيًا طبعًا-: نلاحظ الآتي: تتألف المحطة من مكوِّنات عديدة. يمتلك كل مكوِّن بدوره أجزاءً أصغر في داخله. المكوّنات معقدّة جدًا، وهي بالطبع أعقد بكثير من معظم مواقع الويب. طوّرت مكونات المحطة على صعيد عالمي، ومن قِبل فرق من دول مختلفة تتحدث بلغات مختلفة. تحلق المحطة في مدارها حول الأرض وتبقي من في داخلها على قيد الحياة، فكيف بني هذا الجهاز المعقد؟ وما هي المبادئ التي يمكن أن نستعيرها لنطوّر مكوّنات ويب لها نفس مستوى الوثوقية وقابلة للنمو، أو قريبة من ذلك على الأقل؟ معمارية المكون تنص القاعدة الشهيرة في تطوير البرمجيات المعقدة على أن لا تطوّر برمجيات معقّدة، فإذا وصل بك الأمر إلى أمر معقد، فافصله إلى أجزاء أبسط واربطها ببعضها بأكثر الطرق وضوحًا، فالمعماري الأمهر هو من يستطيع تحويل المعقد إلى بسيط. يمكن تقسيم واجهة المستخدم إلى مكوّنات مرئية لكلٍّ منها موقعه في الصفحة، وتُنفِّذ مهمةً محددةً بعناية وتكون مفصولةً عن بعضها البعض، لنلق نظرةً على موقع ويب، وليكن تويتر مثلًا، يُقسم الموقع إلى مكوّنات: مكوّن للتنقل. معلومات المستخدم. اقتراحات المتابعة. نموذج إرسال. رسائل. غيرها من المكوِّنات. قد يكون للمكوّنات مكوّنات فرعيةً أيضًا، فقد تكون الرسائل مكوّنات فرعيةً من مكوّن أعلى مستوىً مثل قائمة الرسائل، كما قد تكون صورة المستخدم التي تقبل النقر مكوّنًا.. وهكذا. كيف نحدد ما هو المكوِّن إذًا؟ يأتي ذلك من حسن البديهة والخبرة والمنطق، حيث تشكًل المكوّنات عادةً كيانات مرئيةً نميزها وفقًا لوظيفتها وكيفية تتفاعلها مع الصفحة، ففي حالة الصفحة السابقة، سنجد أنها تحوي وحدات يلعب كل منها دوره الخاص، ومن المنطق إذًا أن نجعلها مكوّنات. للمكوِّن: صنف JavaScript خاص به. بنية DOM تُدار منفردةً من قبل الصنف الخاص بها، ولا يمكن الوصول إليها من قبل شيفرة خارجية (مبدأ التغليف). تنسيق CSS يُطبَّق على المكوّن. واجهة برمجية API، أحداث وتوابع يستخدمها الصنف وغيره من الكائنات التي تتفاعل مع المكوّنات الأخرى. تذكر أنّ فكرة الكائن ككل لا تفرض وجود أي شيء خاص. تتواجد الكثير من المنصات وإطارات العمل التي تقدم وسائل لإنشاء المكوّنات، وتستخدم أصناف CSS بالإضافة إلى ترتيبات أخرى لتعزيز المكوّنات وتحديد مجال تطبيق CSS وتغليف DOM. تزوّدنا مكوِّنات الويب بإمكانيات تصفّح مدمجةً معها ولا حاجة لمحاولة تقليدها بعد الآن. عناصر مخصصة Custom elements: لتعريف عناصر HTML مخصصة. شجرة DOM مخفية Shadow DOM: لإنشاء شجرة داخلية للمكوّن مخفية عن بقية المكوّنات. مجال لتطبيق أوراق التنسيق CSS Scoping: لتعريف قواعد تنسيق يمكن تطبيقها على الشجرة الداخلية لمكوّن. إعادة توجيه الحدث Event retargeting وغيره من الأمور الثانوية: لتحسين قدرة المكوّنات على التلاؤم مع عملية التطوير. كل الميزات المدعومة جيدًا لمكوّنات الويب جيدة في الأمور التي تقدر على تنفيذها. عناصر HTML المخصصة يمكننا إنشاء عناصر HTML مخصصة يصفها الصنف الذي ننشئه لهذا الغرض مزوّدًا بتوابعه وخصائصه وأحداثه الخاصة، وسنتمكن من استخدام العنصر ضمن عناصر HTML الأصلية بعد أن نعرّفه، وهذا أمر جيد، فعلى الرغم من غنى HTML بالعناصر، إلا أنها لا تحوي عناصرًا مثل علامة جداول سهلة التعامل <easy-tabs> أو سير دائري منزلق <sliding-carousel> أو الرفع بطريقة جذابة <beautiful-upload> أو أي عناصر أخرى قد نحتاجها. يمكن تعريف العناصر المخصصة ضمن أصناف خاصة، واستخدامها كما لو أنها جزء من HTML، ويوجد نوعان من هذه العناصر المخصصة، وهما: عناصر مخصصة ذاتية التصرف Autonomous: وهي عناصر جديدة توّسع عمل الصنف المجرّد HTMLElement. عناصر أصلية مخصصة customized: توسّع العناصر الأصلية، لإنجاز أزرار مخصصة مبنية على أساس الصنف HTMLButtonElement مثلًا. سنغطي أولًا العناصر ذاتية التصرف، ثم سننتقل إلى العناصر المخصصة، ولإنشاء عنصر مخصص لا بدّ من إخبار المتصفح عن جملة من التفاصيل حوله، مثل كيف سيُظهره؟ وماذا سيفعل عند إضافته أو إزالته من الصفحة؟ يجري ذلك بإنشاء صنف له توابعه الخاصة، وسيكون الأمر بسيطًا، فهي عدة توابع فقط وجميعها اختيارية. إليك تصورًا مع قائمة كاملة من التوابع: class MyElement extends HTMLElement { constructor() { super(); // إنشاء العنصر } connectedCallback() { //يستدعيه المتصفح عند إضافة عنصر ويمكن استدعاؤه عدة مرات إن أضيف أو حذف العنصر } disconnectedCallback() { //يستدعيه المتصفح عند حذف عنصر ويمكن استدعاؤه عدة مرات إن أضيف أو حذف العنصر } static get observedAttributes() { return [/* مصفوفة من أسماء السمات التي تراقب التغيرات */]; } attributeChangedCallback(name, oldValue, newValue) { // يُستدعى عندما تتغير صفة من السمات المذكوره أعلاه } adoptedCallback() { // يُستدعى عندما يُنقل العنصر إلى صفحة أخرى } // إن كان هناك عناصر أو سمات أخرى } نحتاج بعد ذلك إلى تسجيل العنصر: // سيُخدّم من قبل الصنف الجديد <my-element> أبلغ المتصفح أن customElements.define("my-element", MyElement); ستتولد الآن نسخة عن الصنف MyElement لكل عنصر HTML له الوسم <my-element>، وستستدعى التوابع المذكورة. كما يمكن تنفيذ ذلك باستخدام شيفرة JavaScript كالتالي: document.createElement('my-element') مثال عنصر لتنسيق الوقت يُستخدم العنصر الأصلي <time> لإظهار الوقت والتاريخ، لكنه لا يقدم أي تنسيق للبيانات التي يعطيها، لننشئ إذًا العنصر <time-formatted> الذي يعرض الوقت بتنسيق جميل يأخذ اللغة بالحسبان: <script> class TimeFormatted extends HTMLElement { // (1) connectedCallback() { let date = new Date(this.getAttribute('datetime') || Date.now()); this.innerHTML = new Intl.DateTimeFormat("default", { year: this.getAttribute('year') || undefined, month: this.getAttribute('month') || undefined, day: this.getAttribute('day') || undefined, hour: this.getAttribute('hour') || undefined, minute: this.getAttribute('minute') || undefined, second: this.getAttribute('second') || undefined, timeZoneName: this.getAttribute('time-zone-name') || undefined, }).format(date); } } customElements.define("time-formatted", TimeFormatted); // (2) </script> <!-- (3) --> <time-formatted datetime="2019-12-01" year="numeric" month="long" day="numeric" hour="numeric" minute="numeric" second="numeric" time-zone-name="short" ></time-formatted> See the Pen JS-p3-06-Custom-elements -ex1 by Hsoub (@Hsoub) on CodePen. تشير (1) إلى الصنف تابع واحد فقط هو ()connectedCallback، حيث يستدعيه المتصفح عندما يُضاف العنصر إلى الصفحة، أو عندما يكتشف مفسّر HTML وجوده، ويستخدم العنصر تابع تنسيق البيانات المدمج Intl.DateTimeFormat الذي يلقى دعمًا جيدًا من معظم المتصفحات لعرض الوقت بتنسيق جميل. تعني (2) أنه لا بدّ من تسجيل العنصر الجديد باستخدام الأمر (customElements.define(tag, class). تعني (3) أنه يمكن الآن استخدام العنصر في أي مكان. تحديث العنصر المخصص إذا صادف المتصفح العنصر <time-formatted> قبل عبارة التعريف customElements.define فلن يعدّ ذلك خطأً، بل سيعدّه مجرد عنصر غير معروف مثل أي وسم غير معياري، ويمكن تنسيق هذه العناصر غير المعروفة باستخدام المحدد (not(:defined:، وهو أحد محددات CSS. ستُحدّث هذه العناصر عندما يُستدعى التابع customElement.define، وستتولد نسخة من الصنف TimeFormatted لكلٍّ منها، ثم يُستدعى التابع connectedCallback وتتحول إلى عناصر معرّفة defined:. توجد توابع عدة للحصول على معلومات عن عناصر مخصصة: (customElements.get(name: يعيد الصنف الخاص بالعنصر الذي يحمل الاسم المحدد name. (customElements.whenDefined(name: يعيد وعدًا promise يحَلَّ -دون قيمة- عندما يُعرَّف العنصر المخصص الذي له الاسم name المحدد. التصيير داخل connectedCallback لا في constructor رأينا في المثال السابق كيف جرى تصيير محتوى العنصر ضمن التابع connectedCallback، لكن لماذا لم يُصيّر ضمن الدالة البانية constructor؟ إنّ السبب بسيط، لأنه من المبكر جدًا تصيير المكوّن عند استدعاء constructor، فعندما يُنشأ العنصر في هذه المرحلة، فلن يُعالجه المتصفح أو يسند إليه السمات الخاصة به، فاستدعاء getAttribute سيعيد القيمة "لاشيء" null، وبالتالي لن نتمكن من تصيير شيء، ولو فكرنا بالأمر قليلًا فسنجد أنّ هذا الأداء أفضل لتأخير العمل حتى يكون كل شيء جاهزًا. يقع الحدث connectedCallback عندما يُضاف العنصر إلى الصفحة، ولن يُضاف إلى عنصر آخر مثل ابن فقط، بل سيغدو عمليًا جزءًا من الصفحة، وهكذا سنتمكن من بناء شجرة DOM منفصلة، وإنشاء عناصر وتحضيرها للعمل لاحقًا، وستصيّر هذه العناصر فعليًا عندما تُضاف إلى الصفحة. مراقبة السمات ليس لتغير السمات attribute في الطريقة الحالية لتنفيذ العنصر <time-formatted> أي تأثير بعد تصييره، وهذا غريب بالنسبة إلى عنصر HTML، فعندما نغيّر في صفة مثل a.href، فسنتوقع عادةً أن نرى التغير مباشرةً. نصلح هذا الأمر إذًا. يمكن مراقبة السمات بتزويد دالة الإحضار الساكنة ()observedAttributes بقائمة تضم أسماءهم، وهكذا ستُستدعى الدالة attributeChangedCallback عندما نجري أي تعديلات على تلك السمات. لن يقع هذا الحدث بالطبع عندما تتغير سمات غير مدرجة في القائمة، لأسباب تتعلق بالأداء. إليك شيفرة العنصر <time-formatted> الذي يُحدَّث تلقائيًا عندما تتغير سماته: <script> class TimeFormatted extends HTMLElement { render() { // (1) let date = new Date(this.getAttribute('datetime') || Date.now()); this.innerHTML = new Intl.DateTimeFormat("default", { year: this.getAttribute('year') || undefined, month: this.getAttribute('month') || undefined, day: this.getAttribute('day') || undefined, hour: this.getAttribute('hour') || undefined, minute: this.getAttribute('minute') || undefined, second: this.getAttribute('second') || undefined, timeZoneName: this.getAttribute('time-zone-name') || undefined, }).format(date); } connectedCallback() { // (2) if (!this.rendered) { this.render(); this.rendered = true; } } static get observedAttributes() { // (3) return ['datetime', 'year', 'month', 'day', 'hour', 'minute', 'second', 'time-zone-name']; } attributeChangedCallback(name, oldValue, newValue) { // (4) this.render(); } } customElements.define("time-formatted", TimeFormatted); </script> <time-formatted id="elem" hour="numeric" minute="numeric" second="numeric"></time-formatted> <script> setInterval(() => elem.setAttribute('datetime', new Date()), 1000); // (5) </script> See the Pen JS-p3-06-Custom-elements -ex2 by Hsoub (@Hsoub) on CodePen. يُقصَد بـ (1) أنه قد نُقل منطق التصيير إلى التابع المساعد <time-formatted>. تعني (2) أن هذا التابع يُستدعى مباشرةً في اللحظة التي يضاف فيها العنصر إلى الصفحة. تعني (3) أنه يقع الحدث attributeChangedCallback عند حدوث أي تغير في السمات التي مررت على شكل قائمة إلى ()observedAttributes تعني (4) أنه يُعاد تصيير العنصر بعد ذلك. تعني (5) أنه في النهاية يمكننا إنشاء مؤقت مباشر بكل سهولة. تسلسل التصيير عندما يبني مفسِّر HTML الشجرة DOM، تعالَج العناصر الواحد تلو الآخر والأب قبل الابن، فلو كان لدينا العنصر: <outer><inner></inner></outer> فسيتولد العنصر <outer> أولًا ويضاف إلى DOM، ثم العنصر <inner>، وسيقود ذلك إلى تبعات بالنسبة للعناصر المخصصة، فإذا أراد العنصر المخصص الوصول إلى innerHTML ضمن connectedCallback مثلًا، فلن يحصل على شيء. <script> customElements.define('user-info', class extends HTMLElement { connectedCallback() { alert(this.innerHTML); // empty (*) } }); </script> <user-info>محمد</user-info> إذا نفّذت الشيفرة السابقة فستظهر الرسالة alert فارغة، والسبب في ذلك هو عدم وجود عناصر أبناء في هذه المرحلة، وستكون الشجرة DOM غير مكتملة، يربط مفسِّر HTML العنصر المخصص <user-info> وسيستأنف العمل بعدها لربط أبنائه لكنه لم يفعلها بعد. إذا أردنا تمرير معلومات إلى عنصر مخصص، فيمكننا استخدام السمات فهي متاحة مباشرةً، وإذا كنا بحاجة فعلًا إلى الأبناء، فيمكن تأجيل الوصول إليهم باستخدام الحدث setTimeoutدون تأخير زمني Zero-delay. <script> customElements.define('user-info', class extends HTMLElement { connectedCallback() { setTimeout(() => alert(this.innerHTML)); // محمد (*) } }); </script> <user-info>John</user-info> وهكذا ستُظهر الرسالة alert في السطر (*) الكلمة "محمد" طالما أننا ننفذ الأمر دون تزامن، وذلك بعد اكتمال تفسير شيفرة HTML، ويمكن معالجة الأبناء إذا اقتضى الأمر ثم إنهاء مرحلة التهيئة، لكن هذا الحل ليس مثاليًا. فإذا استخدمت العناصر المخصصة الحدث لتهيئة نفسها، فإنها ستصطف بحيث يقع الحدث setTimeout للعنصر الخارجي ثم الداخلي، وبالتالي ستنهي العناصر الخارجية تهيئة نفسها قبل الداخلية، لنشرح ذلك من خلال المثال التالي: <script> customElements.define('user-info', class extends HTMLElement { connectedCallback() { alert(`${this.id} connected.`); setTimeout(() => alert(`${this.id} initialized.`)); } }); </script> <user-info id="outer"> <user-info id="inner"></user-info> </user-info> تسلسل الخرج: يُربط العنصر الخارجي بالشجرة. يُربط العنصر الداخلي. يُهيأ العنصر الخارجي. يُهيأ العنصر الداخلي. يمكننا أن نرى بوضوح أن العنصر الخارجي سينهي تهيئة نفسه (الخطوة 3) قبل الداخلي (الخطوة 4)، ولا يوجد استدعاء مدمج يمكن أن يقع بعد أن يصبح العنصر ضمن الشجرة، كما يمكن تنفيذ استدعاء مثل هذا عند الحاجة بأنفسنا، حيث يمكن للعناصر الداخلية إرسال أحداث مثل initialized تستمع إليها العناصر الخارجية وتتفاعل معها. العناصر الأصلية المخصصة ليس للعناصر المخصصة -مثل <time-formatted>- أي دلالات تتعلق بها، فهي غير معروفة لمحركات البحث مثلًا، ولا تستطيع الأجهزة التي تدعم مبدأ الوصول السهل accessibility التعامل معها. قد تكون هذه الأشياء مهمةً، فقد يرغب محرّك البحث بمعرفة أن هذا العنصر سيظهر الوقت، فإذا أنشأنا نوعًا خاصًا من الأزرار، فلماذا لا يمكننا إعادة استخدام وظيفة الزر الأصلي <button>؟ يمكننا توسيع وتخصيص العناصر الأصلية بالوراثة من أصنافها، فالأزرار مثلًا هي نسخ عن الصنف HTMLButtonElement، ولإنشاء عنصر يرث منه ويوسّعه عليك باتباع الآتي: وسِّع الصنف HTMLButtonElement عن طريق الصنف الذي سننشئه: class HelloButton extends HTMLButtonElement { /* custom element methods */ } أعط قيمةً للوسيط الثالث للدالة customElements.define والذي يمثّل الوسم tag المستهدف: customElements.define('hello-button', HelloButton, {extends: 'button'}); يمكن أن تشترك وسوم مختلفة بصنف DOM، لذلك سنحتاج إلى استخدام التعليمة extends. لكي نستخدم أخيرًا العنصر المخصص، استخدم الوسم الأصلي النظامي <button>، لكن أضف إليه الصفة "is="hello-button. <button is="hello-button">...</button> إليك المثال كاملًا: <script> // عند ضغطه "hello" الزر الذي يظهر class HelloButton extends HTMLButtonElement { constructor() { super(); this.addEventListener('click', () => alert("Hello!")); } } customElements.define('hello-button', HelloButton, {extends: 'button'}); </script> <button is="hello-button">Click me</button> <button is="hello-button" disabled>Disabled</button> See the Pen JS-p3-06-Custom-elements -ex3 by Hsoub (@Hsoub) on CodePen. يوسِّع الزر الجديد الزر الأصلي، وبالتالي سيحتفظ بتنسيق وميزات الزر الأصلي مثل الصفة disabled. قوالب HTML يقدم العنصر الأصلي <template> قوالبًا لتخزين شيفرة HTML ويتجاهل محتوياتها، ويتحقق من صحة التركيب اللغوي للشيفرة ضمنها حصرًا، لكن يمكن الوصول إليها واستخدامها في إنشاء عناصر أخرى. يمكن نظريًا إنشاء أي عناصر مخفية ضمن ملف HTML لتخزين شيفرة HTML، فما الغاية من <template>؟ أولًا: قد يحتوي على أي شيفرة HTM صالحة، حتى تلك التي تتطلب عادةً وسم إغلاق Closing tag، فيمكن أن نضع ضمنها أسطر جدول <tr>: <template> <tr> <td>Contents</td> </tr> </template> عندما نحاول عادةً وضع <tr> ضمن <div> مثلًا، فسيكتشف المتصفح الخطأ في بنية DOM ويصلحها بإضافة الوسم <table> وجعل السطر ضمنه تلقائيًا. من الناحية الأخرى سيُبقي <template> ما وضعناه في المكان الذي وضعناه فيه دون تعديل. يمكننا وضع تنسيقات وسكربتات ضمن <template> أيضًا: <template> <style> p { font-weight: bold; } </style> <script> alert("Hello"); </script> </template> يَعُد المتصفح محتويات <template> "خارج المستند"، أي لن تُطبق قواعد التنسيق الموجودة ضمنه ولن يعمل <video autoplay>، كما سيُصبح المحتوى حيًا -أي يُطبَّق التنسيق وتنفَّذ السكربتات- عندما ندرجه ضمن المستند. إدراج القالب يُتاح محتوى قالب ضمن الخاصية content العائدة له على شكل عقدة من النوع DocumentFragment، وهي نوع خاص من عقد DOM، ويمكن التعامل معها مثلما نتعامل مع أي عقدة DOM عدا خاصية واحدة مميزة، وهي إدراج الأبناء بدلًا من العقدة عندما نحاول إدراجها، فعلى سبيل المثال: <template id="tmpl"> <script> alert("Hello"); </script> <div class="message">Hello, world!</div> </template> <script> let elem = document.createElement('div'); // انسخ محتوى القالب لاستخدامه مرات عدة elem.append(tmpl.content.cloneNode(true)); document.body.append(elem); // سيعمل الآن السكربت الموجود ضمن القالب </script> دعونا نعيد كتابة مثال شجرة DOM الخفية في الفصل السابق باستخدام القالب <template>: <template id="tmpl"> <style> p { font-weight: bold; } </style> <p id="message"></p> </template> <div id="elem">Click me</div> <script> elem.onclick = function() { elem.attachShadow({mode: 'open'}); elem.shadowRoot.append(tmpl.content.cloneNode(true)); // (*) elem.shadowRoot.getElementById('message').innerHTML = "Hello from the shadows!"; }; </script> See the Pen JS-p3-06-Template-element -ex1 by Hsoub (@Hsoub) on CodePen. عندما ننسخ وندرج tmpl.content في السطر (*) مثل عقدة من النوع DocumentFragment، فسيُدرج أبناؤها (<style> و<p>) بدلًا منها، وسيشكلان شجرة DOM الخفية: <div id="elem"> #shadow-root <style> p { font-weight: bold; } </style> <p id="message"></p> </div> خلاصة للعناصر المخصصة نوعان: الأول عناصر مخصصة ذاتية التصرف Autonomous، لها وسم خاص جديد وتوسع الصنف HTMLElement، وإليك تخطيط التعريف لهذه العناصر: class MyElement extends HTMLElement { constructor() { super(); /* ... */ } connectedCallback() { /* ... */ } disconnectedCallback() { /* ... */ } static get observedAttributes() { return [/* ... */]; } attributeChangedCallback(name, oldValue, newValue) { /* ... */ } adoptedCallback() { /* ... */ } } customElements.define('my-element', MyElement); /* <my-element> */ أما النوع الثاني، فهو عناصر أصلية معدَّلة customized: توّسع عناصرًا أصليةً موجودة، وتتطلب وسيطًا ثالثًا للدالة define.، وإلى الصفة "..."=is ضمن وسمها. class MyButton extends HTMLButtonElement { /*...*/ } customElements.define('my-button', MyElement, {extends: 'button'}); /* <button is="my-button"> */ تدعم معظم المتصفحات العناصر المخصصة جيدًا، كما يوجد موائم polyfill أي تعويض نقص الدعم للمتصفحات غير المدعومة. قد يكون محتوى <template> أي عناصر HTML صالحة قواعديًا. يعُد المتصفح محتويات <template> خارج المستند، إذ لن يكون لها أي تأثير. يمكن الوصول إلى محتوى القالب template.content من JavaScript، ونسخها لإعادة استخدامها في مكوَّن جديد. الوسم فريد لأن: محتويات القالب <template> ستتعرض إلى تدقيق قواعدي من قِبل المتصفح، وهذا مخالف لاستخدام قالب نصي ضمن سكربت. يُسمح باستخدام وسوم HTML عالية المستوى حتى تلك التي لا يجب استخدامها دون عنصر يغلّفها، مثل <tr> التي ينبغي تغليفها بالوسم <table>. تصبح المحتويات حيّةً -أي تُطبَّق وتُنفَّذ- عندما تُدرج ضمن المستند. لا يدعم العنصر <template> المُكررات iterator، ولا آليات الربط بقواعد البيانات أو تبديل المتغيرات، لكن يمكن إدراجها في أعلى القالب. مهام لإنجازها عنصر توقيت مباشر أنشئ العنصر <live-timer> الذي يعرض الوقت الحالي: ينبغي أن يستخدم عنصر التوقيت العنصر <time-formatted> الذي أنشأناه سابقًا، بصورة ضمنية وليس بنسخ وظيفته. يُحدَّث المؤقت كل ثانية. مع كل تحديث للمؤقت سيتولد حدث خاص يُدعى tick يحمل التاريخ الحالي ضمن الخاصية event.detail، راجع فصل "إنشاء أحداث مخصصة في المتصفح عبر جافاسكربت". طريقة الاستخدام: <live-timer id="elem"></live-timer> <script> elem.addEventListener('tick', event => console.log(event.detail)); </script> إليك المثال النموذجي: يمكنك فتح المثال في بيئة تجريبية لاحظ أن: صفرنا المؤقت setInterval عند إزالة العنصر من الصفحة وهذا أمر مهم إذ بدونه سيستمر الحدث بالعمل كل ثانية في الوقت الذي لا يُستعمَل فيه، ولا يمكن للمتصفح أيضًا أن يمسح الذاكرة من تلقاء نفسه. يمكن الوصول إلى القيمة الحالية عبر الخاصية elem.date، إذ كل توابع الصنف وخاصياته هي توابع للعنصر وخاصياته. ويمكنك فتح الحل في بيئة تجريبية. المراجع HTML Living Standard Compatiblity ترجمة -وبتصرف- للفصول Custom elements وFrom Orbital Height وTemplate element من سلسلة The Modern JavaScript Tutorial. اقرأ أيضًا المقال السابق: إنشاء الحركات عبر جافاسكربت المقال التالي: مكونات الويب: التعامل مع شجرة DOM الخفية iframe { border: 1px solid #e7e5e3 !important; width: 100%; } iframe div#path { margin: auto; }
    1 نقطة
×
×
  • أضف...