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

Bassel Alkhatib

الأعضاء
  • المساهمات

    35
  • تاريخ الانضمام

  • تاريخ آخر زيارة

كل منشورات العضو Bassel Alkhatib

  1. تُناسب بايثون الكثير من التطبيقات البرمجية نظرًا لتمتعها بالعديد من المزايا المهمة كالمرونة العالية وتوفير المكتبات الجاهزة فيها للقيام بعمليات الأتمتة وتحليل البيانات ومعالجة مسائل تعلم الآلة والتطوير الخلفي back-end وغيرها من المهام البرمجية بسرعة وسهولة. ظهرت النسخة الأولى منها في عام 1991 وسُميت تيمنًا بالفرقة الكوميدية البريطانية Monty Python هادفة جعل كتابة الكود فيها أمرًا ممتعًا، ويعد الإصدار الثالث أحدث نسخة وهو المستقبل الواعد لبايثون. يعرض هذا المقال خطوات تثبيت بيئة بايثون على الحاسوب المحلي أو الخادم البعيد لتطبيق المشاريع العملية اللاحقة في الكتاب، أما إذا كان بايثون مع أدواته pip و venv جاهزًا على حاسوبك فيُمكنك الانتقال مباشرة إلى الفصل التالي. المتطلبات الرئيسية نعمل في بيئة لينكس Linux أو الشبيهة بيونكس Unix-like ونستخدم ضمن نظام التشغيل ماكنتوش macOS سطر الأوامر command line أو بيئة الطرفية terminal environment، أما في نظام ويندوز، فيمكن استعمال بورشيل PowerShell لتحقيق نفس النتائج عمليًا. الخطوة الأولى: تثبيت بايثون يثبت بايثون على العديد من أنظمة التشغيل بشكل افتراضي. للتأكد من وجود الإصدار 3 من بايثون مثبتًا على جهازك قم بفتح نافذة طرفية واكتب فيها ما يلي: python3 -V سيظهر، في حال كون الإصدار 3 من بايثون مثبتًا، رقم الإصدار والذي يُمكن بالطبع أن يختلف حسب النسخة المُنصبة، وفي جميع الأحوال، يكون الخرج مشابهًا لما يلي: Python 3.7.2 في حال لم تحصل على الإظهار السابق، فعليك أولًا تنزيل النسخة من موقع بايثون python.org ومن ثم اتباع خطوات التثبيت المُحدّدة. بعد انتهائك من تثبيت بايثون وتأكدك من ذلك بمعاينة رقم الإصدار باتباع التعليمة السابقة يُمكنك الانتقال للخطوة التالية. الخطوة الثانية: تثبيت pip يجب تثبيت الأداة pip والتي تسمح بتثبيت وإدارة حزم البرمجيات المساندة لبايثون. ستكون هذه الأداة جاهزة فيما لو قمت بتثبيت بايثون من الموقع python.org، أما إذ كنت على خادم أو حاسوب بتوزيعة أبنتو Ubuntu أو ديبيان Debian فيُمكنك تنزيل pip بكتابة ما يلي: sudo apt install -y python3-pip من الآن فصاعدًا، يُمكنك تنزيل أي حزمة برمجيات بكتابة: pip3 install package_name حيث package_name هي اسم أي مكتبة أو حزمة برمجية لبايثون مثل جانغو Django لتطوير مواقع الويب والحزمة NumPy للحسابات العلمية، فإذا كنت مثلًا تريد استخدام المكتبة NumPy فعليك تنزيلها بكتابة الأمر التالي: install numpy يوجد بعض الحزم البرمجية الأساسية الواجب تحميلها للحصول على بيئة عمل مريحة ومرنة: sudo apt install build-essential libssl-dev libffi-dev python3-dev يُمكن الآن بعد الانتهاء من المراحل السابقة إعداد بيئة عمل افتراضية. الخطوة الثالثة: إعداد بيئة عمل افتراضية تسمح بيئة العمل الافتراضية بعزل كل مشروع مع حزمه البرمجية التابعة له عن بقية المشاريع الأخرى وذلك عن طريق تخصيص مساحة خاصة له على الخادم، مما يسمح أيضًا بتنظيم الإصدارات المختلفة للمشروع. وهو أمر ضروري لاسيما عند استخدامنا لحزم برمجية خارجية. يُمكن إنشاء بيئة عمل افتراضية لكل مشروع وهي عمليًا عبارة عن مجلد معين على الخادم مع بعض الشيفرات البرمجية ضمنه. نستخدم عادةً الأداة venv لإنشاء بيئة عمل افتراضية والتي هي جزء من مكتبة بايثون وتُثبت تلقائيًا خلال تثبيت بايثون. إذ كنت على خادم أو حاسوب Ubuntu أو Debian فيُمكنك تحميل venv بكتابة ما يلي: sudo apt install -y python3-venv انتقل لمجلد معين على حاسوبك لوضع بيئة العمل فيه أو قم بإنشاء مجلد جديد باستخدام تعليمة إنشاء مجلد mkdir ثم انتقل له باستخدام تعليمة الانتقال لمجلد cd كما يلي: mkdir environments cd environments يُمكنك الآن إنشاء بيئة العمل ضمن المجلد الذي انتقلت له وذلك بكتابة ما يلي: python3.6 -m venv my_env حيث my_env هو اسم بيئة العمل الذي تريده، مع ملاحظة كتابة القسم الأول من رقم الإصدار الذي حصلت عليه سابقًا باستخدام python -V (المثال أعلاه يستخدم الإصدار Python 3.6.3). لو كُنت مثلًا تستخدم الإصدار Python 3.7.3 فعليك كتابة: python3.7 -m venv my_env يسمح لك ويندوز بتجاهل رقم الإصدار كليةً وكتابة ما يلي: python -m venv my_env بعد تنفيذ الأمر المناسب لإنشاء بيئة العمل، يُمكن التأكد من إتمام العملية بالاستمرار في الخطوات التالية والتي من أولها معاينة الملفات التي قام venv بإنشائها في المجلد الموافق والتي يُمكن إظهارها باستخدام أمر استعراض محتوى مجلد ls: ls my_env ليكون الخرج: bin include lib lib64 pyvenv.cfg share تعمل هذه الملفات على التأكد من العزل الكامل لملفات مشروعك عن باقي ملفات حاسوبك وبذا فلن تختلط ملفاتك مع ملفات نظام التشغيل أبدًا. تسمح هذه الممارسة الجيدة في التحكم بالإصدارات المختلفة للمشروع والتأكد من أن مشروعك يستخدم الحزم البرمجية التي يحتاج إليها. يُمكن استخدام الحزمة البرمجية الجاهزة Python Wheels التي تسمح بتسريع عملية تطوير البرمجيات وتنفيذ المشروع والموجودة في المجلد share في Ubuntu 18.04، ويجب تفعيل هذه الحزمة قبل بدء استخدامها بكتابة الأمر التالي والذي يقوم باستدعاء السكربت activate: source my_env/bin/activate من الآن فصاعدًا، ستبدأ أوامرك باسم بيئة العمل (المدعوة في أمثلتنا my_env). يُمكن للبادئة أن تظهر أحيانًا بشكل مختلف وذلك حسب الإصدار المستخدم من لينكس ديبيان Debian Linux إلا أنه، وفي جميع الأحوال، يجب أن تبدأ أوامرك باسم بيئة العمل ضمن قوسين: (my_env) sammy@sammy:~/environments$ تُحدّد هذه البادئة بأن بيئة العمل my_env هي البيئة النشطة الحالية مما يعني أنه عندما نُنشئ برامج هنا فستستخدم إعدادات ومكتبات هذه البيئة. لاحظ أنه يُمكنك ضمن بيئة العمل الافتراضية استخدام python عوضًا عن python3 و pip عوضًا عن pip3 إن وجدت ذلك مناسبًا. أما خارج بيئة العمل الافتراضية فلا يُمكنك القيام بذلك بل عليك استخدام python3 و pip3. الخطوة الرابعة: إنشاء البرنامج الأول يُمكنك الآن إنشاء البرنامج التقليدي الترحيبي الأول "Hello, World" مما يسمح لك بالتأكد من جاهزية بيئة العمل. افتح مثلًا محرر النصوص nano وأنشئ ملفًا جديدًا: (my_env) sammy@sammy:~/environments$ nano hello.py ثم اكتب في نافذة المحرر المفتوحة أول برنامج بسيط في بايثون: print("Hello, World!") أغلق المحرر nano بالضغط على الاختصار Ctrl+X ولا تنسَ حفظ الملف بالإجابة بنعم y عندما تُسأل عن حفظ الملف. بعد إغلاق nano والعودة لصدفة shell النظام، يُمكنك تنفيذ البرنامج السابق hello.py: (my_env) sammy@sammy:~/environments$ python hello.py والذي سيُظهر على المحطة الطرفية: Hello, World! للخروج من بيئة العمل والعودة للمجلد الأساسي، نفذّ الأمر: deactivate النتائج لقد حصلت نتيجة تطبيقك للخطوات السابقة على بيئة بايثون جاهزة لاحتضان المشاريع البرمجية على حاسوبك ويُمكنك الآن الانطلاق في تطبيق المشاريع البرمجية في الفصول التالية! إن أردت التعرف أكثر على بايثون، فيمكنك الرجوع إلى كتاب البرمجة بلغة بايثون. اقرأ أيضًا المرجع الشامل إلى تعلم لغة بايثون التواصل مع نظام التشغيل عبر بايثون النسخة الكاملة من كتاب البرمجة بلغة بايثون
  2. تُعدّ مسألة تقييم نماذج تعلم الآلة، أي حساب مجموعة من مقاييس تقييم الأداء والتي تُبرهن على وصول النموذج المُتعلم إلى درجة جيدة من التعلم وبحيث يُمكن الاعتماد عليه واستخدامه في مسألة ما، أمرًا أساسيًا في مسائل تعلم الآلة. تسمح هذه المقاييس، في نهاية المطاف، بالمقارنة بين مختلف نماذج التعلم المُمكن استخدامها (والتي يولد كل منها باستخدام خوارزمية ما معينة)، مما يسمح باختيار الأنسب منها. نعرض في هذه المقالة مجموعة المقاييس الأكثر استخدامًا لتقييم نماذج تعلم التصنيف classification وتقييم نماذج الانحدار regression ومن ثم نعرض كيفية المقارنة بين عدة نماذج تعلم ممكنة واختيار الأفضل منها. مقاييس تقييم نماذج تعلم التصنيف تهدف نماذج تعلم التصنيف إلى بناء مُصنف يُمكن استخدامه لتصنيف غرض ما إلى صف مُعين مثلًا ليكن لدينا مسألة تعلم تصنيف صورة إلى كلب أو قط، وبفرض أن لدينا عشرة صور لها قيم الصفوف التالية (كلب أم قط): Actual values = ['cat', 'dog', 'cat', 'dog', 'cat', 'cat', 'dog', 'cat, 'dog', 'cat'] وبفرض أن نموذج تصنيف أعطى التصنيفات التالية لنفس الصور (ندعوها عادًة تنبؤ نموذج التعلم): Predicted values = ['cat', 'cat', 'cat', 'dog', 'cat', 'cat', 'dog', 'dog', 'dog', 'dog'] من الواضح أن نموذج التصنيف أصاب في بعض الحالات وأخطأ في البعض الآخر. والسؤال المطروح هنا بشكل أساسي: ما كفاءة (تقييم) هذا النموذج؟ مصفوفة الارتباك confusion matrix وهي عبارة عن جدول يُستخدم لبيان كفاءة نموذج تعلم التصنيف، إذ يعرض عدد حالات الصواب والخطأ المُمكنة المختلفة. يُبين الجدول التالي مثلًا الحالات المختلفة في المثال السابق (ندعو، للتبسيط، صف الكلب بالموجب وصف القط بالسالب): table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } تنبؤ نموذج التصنيف القيمة الحقيقية: كلب (موجب) القيمة الحقيقية: قط (سالب) كلب (موجب) 3 1 قط (سالب) 2 4 يُبين الجدول السابق أن نموذج التعلم أصاب في 3 حالات (الحقيقة: كلب / التنبؤ: كلب) + 4 حالات (الحقيقة: قط / التنبؤ: قط) = 7 حالات. وأخطأ في حالتين (الحقيقة: كلب / التنبؤ: قط) + حالة (الحقيقة: قط / التنبؤ: كلب) = 3 حالات. تنبؤ نموذج التصنيف القيمة الحقيقية: (موجب) القيمة الحقيقية: (سالب) موجب عدد الحالات الصحيحة الموجبة عدد الحالات الخاطئة الموجبة سالب عدد الحالات الخاطئة السالبة عدد الحالات الصحيحة السالبة الحالات الصحيحة الموجبة True Positive الحالات الصحيحة الموجبة True Positive وتختصر إلى TP وهي الحالات التي يكون من أجلها تنبؤ النموذج موجب والقيمة الحقيقة موجب (تنبؤ صحيح). الحالات الصحيحة السالبة True Negative الحالات الصحيحة السالبة True Negative وتختصر إلى TN وهي الحالات التي يكون من أجلها تنبؤ النموذج سالب والقيمة الحقيقة سالب (تنبؤ صحيح). الحالات الخاطئة الموجبة False Positive (FP) الحالات الخاطئة الموجبة False Positive وتختصر إلى FP وهي الحالات التي يكون من أجلها تنبؤ النموذج موجب والقيمة الحقيقة سالب (تنبؤ خاطئ). الحالات الخاطئة السالبة False Negative (FN) الحالات الخاطئة السالبة False Negative وتختصر إلى FN وهي الحالات التي يكون من أجلها تنبؤ النموذج سالب والقيمة الحقيقة موجب (تنبؤ خاطئ). مقياس الصحة Accuracy مقياس الصحة Accuracy وهو نسبة التصنيفات الصحيحة من العدد الكلي للأمثلة: ????????= (??+??)/(??+??+??+??) * 100 تكون الصحة في مثالنا السابق: ????????= (3+4)/10 * 100 = 70% مقياس الدقة Precision مقياس الدقة Precision هو نسبة التصنيفات الصحيحة للأمثلة الموجبة على العدد الكلي للأمثلة التي صُنّفت موجبة: ?????????= ??/(??+??) * 100 تكون الدقة في مثالنا السابق: ?????????= 3/(3+1) * 100 = 75% مقياس الاستذكار Recall مقياس الاستذكار Recall هو نسبة التصنيفات الصحيحة للأمثلة الموجبة على العدد الكلي للأمثلة الموجبة (يُدعى هذا المقياس أيضًا بالحساسية Sensitivity أو نسبة الموجب الصحيح True Positive Rate): ??????= ??/(??+??) * 100 يكون الاستذكار في مثالنا السابق: ??????= 3/(3+2) * 100 = 60% المقياس F1 المقياس F1 وهو مقياس يوازن بين الدقة والاستذكار في قيمة واحدة: ?1−?????= (2∗?????????∗??????)/(?????????+??????) يكون F1 في مثالنا السابق: ?1−?????= (2∗75∗60)/(75+60) = 66.66% الخصوصية Specificity الخصوصية Specificity هو نسبة التصنيفات الخاطئة للأمثلة الموجبة على العدد الكلي للأمثلة السالبة (يُدعى هذا المقياس أيضًا بنسبة الموجب الخاطئ False Positive Rate): ???= ??/(??+??) * 100 تكون الخصوصية في مثالنا السابق: ???= 1/(1+4) * 100 = 20% حساب مقاييس الأداء في بايثون توفر المكتبة sklearn.metrics في بايثون إمكانية حساب كل المقاييس السابقة، كما تُبين الشيفرة البرمجية التالية: # تقييم نماذج التصنيف from sklearn.metrics import confusion_matrix from sklearn.metrics import accuracy_score from sklearn.metrics import precision_score from sklearn.metrics import recall_score from sklearn.metrics import f1_score # الصفوف actual = ['cat', 'dog', 'cat', 'dog', 'cat', 'cat', 'dog', 'cat', 'dog', 'cat'] # التنيؤ predicted = ['cat', 'cat', 'cat', 'dog', 'cat', 'cat', 'dog', 'dog', 'dog', 'dog'] # مصفوفة الارتباك cf_matrix = confusion_matrix(actual , predicted, labels=["dog", "cat"] ) print ('Confusion Matrix :') print (cf_matrix) # مقاييس الأداء print ('Accuracy Score :{:.2f}'.format(accuracy_score(actual, predicted)*100)) print ('Precision Score :{:.2f}'.format(precision_score(actual, predicted, pos_label='dog')*100)) print ('Recall Score :{:.2f}'.format(recall_score(actual, predicted, pos_label='dog')*100)) print ('F1 Score :{:.2f}'.format(f1_score(actual, predicted, pos_label='dog')*100)) print ('Specificity :{:.2f}'.format(cf_matrix[0,1]/(cf_matrix[0,1]+cf_matrix[1,1])*100)) نستخدم في الشيفرة السابقة كل من الدوال التالية والتي يكون لها معاملين هما قائمة القيم الحقيقية وقائمة قيم التنبؤ: الوصف الدالة حساب مصفوفة الارتباك confusion_matrix حساب الصحة accuracy_score حساب الدقة precision_score حساب الاستذكار recall_score حساب F1 f1_score تكون نتائج مثالنا: Confusion Matrix : [[3 1] [2 4]] Accuracy Score :70.00 Precision Score :60.00 Recall Score :75.00 F1 Score :66.67 يُمكن أيضًا رسم مصفوفة الارتباك باستخدام المكتبة seaborn كما يلي: import seaborn as sns sns.heatmap(cf_matrix, annot=True) مما يُظهر الشكل التالي: خصائص المُستقبل التشغيلية ROC خصائص المُستقبل التشغيلية ROC -اختصار Receiver Operating Characteristic- هو منحني يُبين كفاءة نموذج التصنيف في قدرته على الفصل بين الصفوف الموجبة والسالبة. كي يكون نموذج تصنيف ممتازًا، يجب أن يصل إلى الزاوية العليا اليسارية أي أن تكون نسبة الصفوف الموجبة الصحيحة (الاستذكار) TPR أقرب للواحد، ونسبة الصفوف الموجبة الخاطئة (الخصوصية) FPR أقرب للصفر. يُبين الشكل التالي منحنيات ROC مختلفة ممكنة. كلما اقتربنا من أعلى اليسار كان المُصنّف أفضل: المساحة تحت المنحني AUC كلما كانت المساحة AUC -اختصار Area Under the Curve- تحت منحني ROC أكبر (أقرب من الواحد)، كان المُصنّف أفضل (لأن ذلك يعني أن المنحني أقرب للأعلى يسارًا). يُمكن رسم منحني ROC في بايثون وحساب المساحة تحت المنحني AUC كما تُبين الشيفرة البرمجية التالية لمثالنا السابق: # مكتبة الترميز from sklearn.preprocessing import LabelEncoder # الصفوف actual = ['cat', 'dog', 'cat', 'dog', 'cat', 'cat', 'dog', 'cat', 'dog', 'cat'] # التنيؤ predicted = ['cat', 'cat', 'cat', 'dog', 'cat', 'cat', 'dog', 'dog', 'dog', 'dog'] # ترميز الصفوف le = LabelEncoder() # ترميز الصفوف كأرقام actual=le.fit_transform(actual) # ترميز التنبؤ كأرقام predicted = le.fit_transform(predicted) # مكتبة المقاييس اللازمة from sklearn import metrics # مكتبة الرسم import matplotlib.pyplot as plt # حساب المقاييس fpr, tpr, _ = metrics.roc_curve(actual, predicted) auc = metrics.roc_auc_score(actual, predicted) # رسم المنحني plt.plot(fpr,tpr,label="AUC="+str(auc)) plt.ylabel('True Positive Rate') plt.xlabel('False Positive Rate') plt.legend(loc=4) plt.show() لاحظ استخدام الصف LabelEncoder من المكتبة sklearn.preprocessing لترميز الصفوف كأرقام. يكون الإظهار: لاحظ أن المساحة تحت المنحني تُساوي إلى 0.75 مما يعني أن المُصنف جيد نسبيًا. تقييم نماذج الانحدار نُذكّر أولًا بأن الهدف من نماذج الانحدار هو التنبؤ بقيمة رقمية y انطلاقًا من قيمة (أو مجموعة من القيم) x. ليكن لدينا مثلًا جدول بيانات التدريب التالي والذي يُعطي عدد الأعطال لآلة وفق عمر الآلة بالسنوات: Failures Age 15 10 30 20 40 40 55 50 75 70 90 90 يُبين الشكل التالي هذه النقاط على محور العمر Age والأعطال Failures: يُعدّ الانحدار الخطي linear regression من أكثر أنواع الانحدار استخدامًا نظرًا لبساطته في كل من التعلم والتنبؤ، فيُمكن مثلًا أن يتلائم fit الانحدار الخطي مع البيانات السابقة ليولد المستقيم التالي: يُمكن حساب التنبؤ Predictions لكل من قيم الجدول السابق باستخدام معادلة المستقيم الناتجة عن نموذج الانحدار، مما يُعطي: Failures Age Predictions 15 10 26 30 20 32 40 40 44 55 50 50 75 70 62 90 90 74 يُمكن الآن قياس مدى ملائمة المستقيم للبيانات بحساب المسافة بين النقاط الأساسية والمستقيم، وذلك بحساب الأخطاء Errors الحاصلة أي الفروقات بين القيم الأساسية و قيم التنبؤ، كما يُبين الجدول التالي: Errors Predictions Failures Age 11 26 15 10 2 32 30 20 4 44 40 40 -5 50 55 50 -13 62 75 70 -16 74 90 90 يُبين الشكل التالي هذه الفروقات أيضًا: تُستخدم المقاييس التالية لتقييم أداء الانحدار: الجذر التربيعي لمتوسطات مربعات الأخطاء Root Mean Square Error (ويختصر إلى RMSE) متوسط الأخطاء بالقيمة المطلقة Mean Absolute Error (ويختصر إلى MAE) الجذر التربيعي لمتوسطات مربعات الأخطاء RMSE تُستخدم عملية التربيع أولًا للتخلص من الإشارة السالبة للأخطاء: Errors2 Errors Predictions Failutres Age 121 11 26 15 10 4 2 32 30 20 16 4 44 40 40 25 -5 50 55 50 169 -13 62 75 70 256 -16 74 90 90 ومن ثم نحسب متوسط مربعات الأخطاء، مما يُعطي 89.5. وأخيًرا نجذر المتوسط السابق فيكون الناتج 9.9 قيمة المقياس RMSE أي الجذر التربيعي لمتوسطات مربعات الأخطاء Root Mean Square Error. بالطبع، كلما كان هذا العدد صغيرًا فهذا يعني أن الملائمة أفضل (الحالة المثالية هي الصفر). متوسط الأخطاء بالقيمة المطلقة MAE \Errors\ Errors Predictions Failutres Age 11 11 26 15 10 2 2 32 30 20 4 4 44 40 40 5 -5 50 55 50 13 -13 62 75 70 16 -16 74 90 90 ومن ثم نحسب المتوسط الحسابي لها، مما يُعطي: 8.5 في مثالنا وهو مقياس MAE أي متوسط الأخطاء بالقيمة المطلقة Mean Absolute Error. يُمكن حساب هذه المقاييس في بايثون باستخدام الدوال الموافقة من المكتبة sklearn.metrics، كما تُبين الشيفرة البرمجية التالية والتي نستخدم فيها بيانات مثالنا السابق: from sklearn.metrics import mean_absolute_error from sklearn.metrics import mean_squared_error from math import sqrt y_true = [15, 30, 40, 55, 75, 90] y_pred = [26, 32, 44, 50, 62, 74] print ('MAE :{:.2f}'.format(mean_absolute_error(y_true, y_pred))) print ('RMSE :{:.2f}'.format(sqrt(mean_squared_error (y_true, y_pred)))) يكون الناتج: RMSE :9.92 MAE :8.50 تقييم نماذج التعلم باستخدام طريقة التقسيم العشوائي Hold-out method لبناء نموذج مُتعلم، يجب توفير مجموعة من البيانات dataset لتنفيذ خوارزمية التعلم عليها أولًا، ومن ثم تقييم نموذج التعلم الناتج. يجب لتقييم نموذج التعلم، بشكل حيادي، أن نمرر له مجموعة من البيانات التي لم يرها خلال تدريبه وذلك تفاديًا لحصولنا على مقاييس تقييم ممتازة مزيفة نتيجة وقوع نموذج التعلم في مطب مشكلة فرط التخصيص overfitting، أي أن النموذج تعلم بشكل جيد على الأمثلة المُمره له فقط، وهو غير قادر على تعميم التعلم ليتعامل مع أمثلة جديدة بشكل جيد. تُعدّ طريقة التقسيم العشوائي من أبسط الطرق المستخدمة لتقييم نماذج التعلم والتي تُقسّم البيانات المتاحة إلى قسمين بشكل عشوائي: ندعو القسم الأول ببيانات التدريب training data (عادًة حوالي 80% من البيانات)، والقسم الآخر المتبقي (حوالي 20%) ببينات الاختبار testing data. نعمد إلى تدريب وبناء نموذج التعلم باستخدام بيانات التدريب فقط، ومن ثم تقييم النموذج الناتج باستخدام بيانات الاختبار. توفر المكتبة sklearn في بايثون كل ما يلزم للقيام بذلك كما تٌبين الشيفرة البرمجية التالية والتي نبني فيها نموذج تصنيف باستخدام مُصنّف بايز Bayes وذلك على مجموعة بيانات تصنيف أزهار السوسن iris المتاحة من المكتبة نفسها. # مجموعة بيانات # أزهار السوسن from sklearn.datasets import load_iris # مكتبة تقسيم البيانات إلى تدريب واختبار from sklearn.model_selection import train_test_split # مكتبة مُصنف بايز from sklearn.naive_bayes import GaussianNB # مكتبات مقاييس التقييم from sklearn.metrics import accuracy_score from sklearn.metrics import precision_score from sklearn.metrics import recall_score from sklearn.metrics import f1_score # تحميل البيانات X, y = load_iris(return_X_y=True) # تقسيم البيانات إلى تدريب و اختبار X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) # بناء مصنف بايز gnb = GaussianNB() # الملائمة على بيانات التدريب # والتنبؤ على بيانات الاختبار y_pred = gnb.fit(X_train, y_train).predict(X_test) # حساب مقاييس التقييم # بمقارنة بيانات الاختبار # مع تنبؤ المصنف print ('Accuracy Score :{:.2f}'.format(accuracy_score(y_test, y_pred)*100)) print ('Precision Score :{:.2f}'.format(precision_score(y_test, y_pred, average='macro')*100)) print ('Recall Score ::{:.2f}'.format(recall_score(y_test, y_pred, average='macro')*100)) print ('F1 Score ::{:.2f}'.format(f1_score(y_test, y_pred, average='macro')*100)) لاحظ أن الدالة train_test_split والتي نُمرر لها كل من: X: مصفوفة ثنائية يكون كل عنصر فيها مصفوفة من 4 عناصر (طول وعرض كل من السبال والبتلات لزهرة السوسن). y: مصفوفة أحادية (تصنيف الزهرة الموافق) test_size: النسبة المئوية لبيانات الاختبار من البيانات الكليه (20% افتراضيًا) تُعيد: X_train: بيانات التدريب المختارة عشوائيًا من X. X_test: بيانات الاختبار المختارة عشوائيًا من X. y_train: صفوف بيانات التدريب. y_test: صفوف بيانات الاختبار. يُمكن تنفيذ الشيفرة لمعاينة قيم مقاييس الأداء: Accuracy Score :93.33 Precision Score :92.59 Recall Score :93.94 F1 Score :92.50 يجب الانتباه إلى أن هذه القيم هي قيم استرشادية، بمعنى أنها ستختلف عند كل تنفيذ للشيفرة البرمجية إذ أن حسابها يعتمد في كل مرة على مجموعة مختلفة من بيانات الاختبار (إذ أن هذه البيانات تُختار كل مرة بشكل عشوائي) مثلًا يُعطي تنفيذ ثاني لنفس الشيفرة السابقة النتائج التالية: Accuracy Score :90.00 Precision Score :92.31 Recall Score :92.86 F1 Score :91.65 تقييم نماذج التعلم باستخدام طريقة التقييم المتقاطع Cross Validation method تهدف هذه الطريقة بشكل أساسي إلى استخدام كل البيانات للتدريب (بخلاف الطريقة السابقة والتي تستخدم قسمًا منها فقط)، كما أن قيم مقاييس التقييم ستكون نفسها من أجل كل تنفيذ للشيفرة (بخلاف الطريقة السابقة كما عرضنا أعلاه). عوضًا عن تقسيم البيانات إلى بيانات للتدريب وبيانات للاختبار (التقييم) مما يُخفّض من البيانات التي يُمكن لنا استخدامها للتدريب، نستخدم التقويم المتقاطع مع عدد محدّد من الحاويات K-Fold. تُقسم بيانات التدريب إلى عدد K من الحاويات ومن ثم نقوم بتكرار ما يلي K مرة: في كل مرة i نقوم بتدريب النموذج مع بيانات K-1 حاوية (كل الحاويات ما عدا الحاوية i) ومن ثم تقييمه مع بيانات الحاوية i. في النهاية، يكون مقياس الأداء النهائي هو متوسط مقياس التقييم لكل التكرارات (i:1..K). توفر المكتبة sklearn في بايثون الدالة cross_val_score لتنفيذ التقييم المتقاطع مع تحديد عدد الحاويات المطلوب، كما تُبين الشيفرة البرمجية التالية والتي نحسب فيها مقياس الدقة مثلًا: # مجموعة بيانات # أزهار السوسن from sklearn.datasets import load_iris # مكتبة تقسيم البيانات إلى تدريب واختبار from sklearn.model_selection import train_test_split # مكتبة مُصنف بايز from sklearn.naive_bayes import GaussianNB # مكتبة التقييم المتقاطع from sklearn.model_selection import cross_val_score # مكتبات مقاييس التقييم from sklearn.metrics import accuracy_score from sklearn.metrics import precision_score from sklearn.metrics import recall_score from sklearn.metrics import f1_score # تحميل البيانات X, y = load_iris(return_X_y=True) # تقسيم البيانات إلى تدريب و اختبار X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) # بناء مصنف بايز gnb = GaussianNB() # حساب مقياس الصحة scores = cross_val_score(gnb, X, y, cv=5, scoring="accuracy") print(scores) # حساب المتوسط meanScore = scores.mean() print(meanScore * 100) يكون ناتج التنفيذ (في كل مرة): [0.93333333 0.96666667 0.93333333 0.93333333 1. ] 95.33333333333334 اختيار نموذج التعلم الأفضل يُمكن استخدام طريقة التقويم المتقاطع السابقة لتقييم مجموعة من نماذج التعلم. نُعرّف في الشيفرة البرمجية التالية الدالة cv_comparison_classification والتي نُمرر لها مجموعة من نماذج التعلم models والبيانات كلها (X,y) وعدد الحاويات cv، وتُعيد هذه الدالة إطار بيانات يُظهر مقياس الدقة لكل نموذج. تدور حلقة for في الدالة على النماذج المُمرره، وتستدعي من أجل كل نموذج دالة التقويم المتقاطع من المكتبة sklearn.model والتي تُعيد قائمة بقيم مقياس الصحة (كل عنصر في القائمة هو قيمة مقياس الصحة من أجل حاوية اختبار ما). نحسب متوسط mean القائمة السابقة، ونضيف عمودًا جديدًا إلى إطار البيانات يكون اسمه اسم النموذج والقيمة في الخلية الموافقة للسطر الوحيد في إطار البيانات (والمفهرس بـ Accuracy) قيمة مقياس الصحة. # مكتبة أطر البيانات import pandas as pd # مكتبة التقييم المتقاطع from sklearn.model_selection import cross_val_score # دالة لمقارنة مجموعة من النماذج def cv_comparison_classification(models, X, y, cv): # تهيئة إطار بيانات لمقاييس التقييم cv_df = pd.DataFrame() # الدوران على النماذج # تطبيق التقييم المتقاطع for model in models: # حساب مقياس الصحة لكل حاوية acc = cross_val_score(model, X, y,scoring='accuracy', cv=cv) # حساب متوسط الصحة للنموذج acc_avg = round(acc.mean(), 4) # كتابة النتيجة في إطار البيانات cv_df[str(model)] = [ acc_avg] cv_df.index = ['Accuracy'] return cv_df نستدعي في الشيفرة البرمجية التالية الدالة السابقة للمقارنة بين ثلاثة نماذج للتصنيف: مصنف بايز GaussianNB ومصنف أشجار القرار DecisionTreeClassifier ومصنف أقرب الجيران KNeighborsClassifier. نستخدم بيانات تصنيف أزهار السوسن المتاحة من sklearn.datasets لتنفيذ نماذج التعلم عليها. # مجموعة بيانات # أزهار السوسن from sklearn.datasets import load_iris # مصنف بايز from sklearn.naive_bayes import GaussianNB # مصنف شجرة القرار from sklearn.tree import DecisionTreeClassifier # مصنف أقرب الجيران from sklearn.neighbors import KNeighborsClassifier # تحميل البيانات X, y = load_iris (return_X_y=True) # إنشاء متغيرات النماذج mlr_g = GaussianNB() mlr_d = DecisionTreeClassifier() mlr_k = KNeighborsClassifier() # وضع النماذج في قائمة models = [mlr_g, mlr_d, mlr_k] # استدعاء دالة المقارنة comp_df = cv_comparison_classification(models, X, y, 4) # إظهار إطار البيانات للمقارنه print(comp_df) يُظهر تنفيذ الشيفرة السابقة إطار البيانات التالي والذي يسمح لنا بمعاينة مقياس الصحة لكل نموذج مما يسمح لنا باختيار الأنسب منها: الخلاصة عرضنا في هذه المقالة مقاييس تقييم نماذج التعلم المختلفة وكيفية اختيار النموذج الأفضل منها لمسألة معينة. يُمكن تجربة جميع أمثلة المقالة من موقع Google Colab من الرابط أو من الملف المرفق. الملف المرفق eval.zip. دورة الذكاء الاصطناعي احترف برمجة الذكاء الاصطناعي AI وتحليل البيانات وتعلم كافة المعلومات التي تحتاجها لبناء نماذج ذكاء اصطناعي متخصصة. اشترك الآن اقرأ أيضًا المفاهيم الأساسية لتعلم الآلة تعلم الآلة: التحديات الرئيسية وكيفية التوسع في المجال النسخة الكاملة لكتاب مدخل إلى الذكاء الاصطناعي وتعلم الآلة
  3. تُعدّ مسألة استكشاف قواعد الترابط في مبيعات المتاجر من المسائل المهمة جدًا لأصحاب المتاجر الإلكترونية، إذ يسمح إيجاد هذه القواعد بإظهار توصيات recommandations الشراء المناسبة للزبائن مما يساهم في زيادة مبيعات المتجر مثلًا لو عرفنا أن معظم الزبائن تشتري السلعة B مع السلعة A دومًا، فسيكون من المناسب إظهار توصية بشراء السلعة B لكل زبون يطلب شراء السلعة A مما يُحقق، في نهاية المطاف، رضى الزبون وزيادة أرباح المتجر. نعرض في هذه المقالة استخدام تقنيات تعلم الآلة لإيجاد قواعد الترابط انطلاقًا من حركات الشراء السابقة للمتجر. بيانات التدريب نستخدم بيانات عمليات الشراء لأحد متاجر مبيعات التجزئة والمتاحة على الرابط أو يمكنك تنزيلها من الملف data.zip في المقال. تأتي هذه البيانات في الملف Groceries.csv المرفق والذي يحوي حوالي 10000 صف. يحوي كل صف بيانات عربة تسوق واحدة أي مجموعة من السلع التي اشتراها أحد الزبائن معًا كما يُبين الشكل التالي: أساسيات في التنقيب عن قواعد الترابط نعرض فيما يلي بعض التعاريف الأساسية في مسألة التنقيب عن قواعد الترابط. التنقيب عن قواعد الترابط تُعرّف مسألة التنقيب عن قواعد الترابط كما يلي: بفرض أن لدينا مجموعة من الإجراءات transactions، يتألف كل إجراء من مجموعة من العناصر items. يكون المطلوب إيجاد جميع الترابطات correlations بين ظهور مجموعة جزئية من العناصر مع مجموعة جزئية أخرى. يُبين الشكل التالي مثالًا توضيحيًا: نستخدم فيما يلي المثال التالي التعليمي والذي يحوي 5 إجراءات: table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } الإجراء Transaction خبز، حليب Bread,Milk خبز، فوط، عصير، بيض Bread, Diaper, Juice, Eggs حليب، فوط، عصير، كولا Milk, Diaper, Juice, Coke خبز، حليب، فوط، عصير Bread, Milk, Diaper, Juice خبز، حليب، فوط، كولا Bread, Milk, Diaper, Coke نُعطي أولًا أهم التعاريف الأساسية: مجموعة عناصر itemset وهي مجموعة من العناصر مثلًا: { Milk , Bread , Diaper} (فوط أطفال، خبز، حليب) كما ندون k-itemset للدلالة على مجموعة عناصر تحوي k عنصر. عدد الدعم support count لمجموعة من العناصر وهو عدد مرات تواتر (ظهور) مجموعة من العناصر في الإجراءات مثلًا يكون عدد الدعم في مثالنا التعليمي لمجموعة العناصر السابقة: sc({Milk, Bread, Diaper}) = 2 الدعم support لمجموعة من العناصر وهو النسبة المئوية لظهور مجموعة من العناصر في الإجراءات، مثلًا يكون عدد الدعم في مثالنا التعليمي لمجموعة العناصر سابقة الذكر: s({Milk, Bread, Diaper}) = (2/5)*100 = 40% الحد الأدنى للدعم minimum support وهو حد أدنى تجريبي للدعم (يُمكن أن يكون رقم أو نسبة مئوية) نُحدّده لخوارزميات التنقيب عن القواعد. دورة الذكاء الاصطناعي احترف برمجة الذكاء الاصطناعي AI وتحليل البيانات وتعلم كافة المعلومات التي تحتاجها لبناء نماذج ذكاء اصطناعي متخصصة. اشترك الآن مجموعة عناصر متواترة frequent itemset نقول عن مجموعة عناصر أنها متواترة إذا كان دعم المجموعة أكبر أو يساوي الحد الأدنى للدعم. قاعدة ترابط association rule وهي اقتضاء من الشكل: {X} => {Y} وحيث X و Y هي مجموعات من العناصر (لا تحوي، بالطبع، عناصر مشتركة) مثلاً: {Milk, Diaper} => {Bread} الدعم لقاعدة ترابط association rule support يكون الدعم لقاعدة ترابط X=>Y هو الدعم لاجتماع العناصر X و Y معًا. أي نسبة الإجراءات التي تحوي X و Y معًا من عدد الإجراءات الكلي: الثقة في قاعدة ترابط association rule confidence وهو الاحتمال الشرطي لظهور مجموعة العناصر Y في إجراء يحوي X، أي عمليًا احتمال (الثقة) أن تظهر مجموعة العناصر Y في عربة تسوق تحوي العناصر X. مثلًا يكون الدعم لمجموعة العناصر {Milk, Diaper, Bread} في المثال السابق مساويًا 40% لأن هذه العناصر ظهرت مع بعضها البعض مرتين في الإجراءات الخمسة الكلية. يُمكن من هذه العناصر الثلاثة {Milk, Diaper, Bread} توليد مجموعة من القواعد المختلفة (يكفي أن نوزع هذه العناصر على الطرف اليساري واليمني بكل الطرق الممكنة لنحصل على جميع القواعد). يُمكن أن يكون لكل قاعدة معامل ثقة مختلف كما تُبين الأمثلة التالية (المحسوبة من مثالنا التعليمي): {Milk, Diaper} => {Bread} (s=0.4, c=0.67) {Milk, Bread} => {Diaper} (s=0.4, c= 0.67) {Diaper, Bread} => {Milk} (s=0.4, c=0.67) {Bread} => {Milk, Diaper} (s=0.4, c=0.50) {Diaper} => {Milk, Bread} (s=0.4, c=0.5) {Milk} => {Diaper, Bread} (s=0.4, c=0.5) نعرض في هذه المقالة كيفية استخراج قواعد الترابط التي تحقق دعم وثقة معينين. إعداد المشروع يحتاج تنفذ شيفرات هذه المقالة بيئةً برمجيةً للغة بايثون الإصدار 3.8. ويجب أن تتضمن هذه البيئة البرمجية مدير الحِزم pip لتثبيت الحِزم، ومُنشئ البيئات الافتراضية venv لإنشاء بيئاتٍ افتراضيةٍ. نستخدم محرر الشيفرات البرمجية Jupyter Notebooks، وهو مفيد جدًا لتجربة وتشغيل الأمثلة الخاصة بتَعَلّم الآلة بطريقةٍ تفاعليةٍ، حيث نستطيع من خلاله تشغيل كتلًا صغيرةً من الشيفرات البرمجية ورؤية النتائج بسرعة، مما يُسهّل علينا اختبار الشيفرات البرمجية وتصحيحها. نحتاج أولًا لتثبيت بعض التبعيات، وذلك لإنشاء مساحة عملٍ للاحتفاظ بملفاتنا قبل أن نتمكن من تطوير برنامجنا. نُنشئ مجلدًا جديدًا خاصًا بمشروعنا وندخل إليه هكذا: mkdir asoc cd asoc نُنفذّ الأمر التالي لإنشاء البيئة الافتراضية: python -m venv asoc ومن ثم الأمر التالي في Linux لتنشيط البيئة الافتراضية: source asoc/bin/activate أما في Windows، فيكون أمر التنشيط: "asoc/Scripts/activate.bat" نستخدم إصداراتٍ مُحددةٍ من المكتبات اللازمة، من خلال إنشاء ملف requirements.txt في مجلد المشروع، وسيُحدِّد هذا الملف المتطلبات والإصدارات التي سنحتاج إليها. نفتح الملف requirements.txt في محرر النصوص، ونُضيف الأسطر التالية، وذلك لتحديد المكتبات التي نريدها وإصداراتها: asttokens==2.0.5 backcall==0.2.0 colorama==0.4.4 cycler==0.11.0 debugpy==1.6.0 decorator==5.1.1 entrypoints==0.4 executing==0.8.3 fonttools==4.33.3 ipykernel==6.13.0 ipython==8.4.0 jedi==0.18.1 joblib==1.1.0 jupyter-client==7.3.1 jupyter-core==4.10.0 kiwisolver==1.4.2 matplotlib==3.5.2 matplotlib-inline==0.1.3 mlxtend==0.20.0 nest-asyncio==1.5.5 numpy==1.22.4 packaging==21.3 pandas==1.4.2 parso==0.8.3 pickleshare==0.7.5 Pillow==9.1.1 prompt-toolkit==3.0.29 psutil==5.9.1 pure-eval==0.2.2 Pygments==2.12.0 pyparsing==3.0.9 python-dateutil==2.8.2 pytz==2022.1 pywin32==304 pyzmq==23.0.0 scikit-learn==1.1.1 scipy==1.8.1 seaborn==0.11.2 six==1.16.0 stack-data==0.2.0 threadpoolctl==3.1.0 tornado==6.1 traitlets==5.2.2.post1 wcwidth==0.2.5 نحفظ التغييرات التي طرأت على الملف ونخرج من محرر النصوص، ثم نُثَبت هذه المكتبات بالأمر التالي: (asoc) $ pip install -r requirements.txt بعد تثبيتنا لهذه التبعيات، نُصبح جاهزين لبدء العمل على مشروعنا. كتابة الشيفرة البرمجية نُشغّل محرر الشيفرات البرمجية Jupyter Notebook بمجرد اكتمال عملية التثبيت هكذا: (asoc) $ jupyter notebook ثم نُنشئ ملفًا جديدًا في داخل المحرر ونُسمّه باسم asc مثلًا. توليد قواعد الترابط نعرض في الشيفرة التالية توليد قواعد الترابط للمثال السابق بهدف التعرف على المكتبات اللازمة وآلية استخدامها. نضع إجراءات المثال السابق أولًا في مصفوفة ثنائية وبحيث يكون كل عنصر منها هو مصفوفة من عناصر إجراء واحد. نحتاج أولًا إلى توليد إطار بيانات dataframe وبحيث تكون رؤوس الأعمدة هي العناصر وقيم الخلايا هي إما True في حال وجود العنصر في صف row الإجراء الموافق أو False في حال عدم وجوده. نستخدم الصنف TransactionEncoder من المكتبة mlxtend.preprocessing للوصول إلى ذلك. # الإجراءات transactions = [['Bread', 'Milk'], ['Bread', 'Diaper', 'Juice', 'Eggs'], ['Milk', 'Diaper', 'Juice', 'Coke' ], ['Bread', 'Milk', 'Diaper', 'Juice'], ['Bread', 'Milk', 'Diaper', 'Coke']] # مكتبة ترميز الإجراءات from mlxtend.preprocessing import TransactionEncoder # إنشاء غرض من الصف te = TransactionEncoder() # ملائمة المرمز مع البيانات te_model = te.fit(transactions) # تحويل الإجراءات rows=te_model.transform(transactions) # استيراد مكتبة إطار البيانات import pandas as pd # بناء إطار بيانات الإجراءات df = pd.DataFrame(rows, columns=te_model.columns_) print(df) وبالنتيجة يكون لدينا إطار بيانات الإجراءات التالي: لاحظ مثلًا أن الصف الأول من إطار البيانات يوافق الإجراء الأول: {Bread, Milk}. نستدعي في الشيفرة التالية الدالة apriori من المكتبة mlxtend.frequent_patterns والتي تحسب العناصر المتواترة في إطار البيانات السابق (df) وفق حد أدنى معين للدعم min_support (يساوي 40% في مثالنا). يكون ناتج تطبيق هذه الدالة إطار بيانات frequent_itemsets ذي عمودين: مجموعة العناصر المتواترة itemsets والدعم support. نُضيف عمود محسوب جديد لإطار البيانات الناتج يحسب طول كل مجموعة عناصر length. # مكتبة خوارزمية إيجاد العناصر المتواترة from mlxtend.frequent_patterns import apriori # توليد المجموعات المتواترة مع تحديد الحد الأدنى للدعم frequent_itemsets = apriori(df, min_support=0.4, use_colnames=True) # حساب أطوال مجموعات العناصر frequent_itemsets['length'] = frequent_itemsets['itemsets'].apply(lambda x: len(x)) print(frequent_itemsets) تُظهر الطباعة دعم وطول كل مجموعة من مجموعات العناصر المتواترة: يُمكن الآن توليد قواعد الترابط باستخدام إطار بيانات العناصر المتواترة frequent_itemsets السابق، كما تُبين الشيفرة التالية. نستخدم الدالة association_rules من المكتبة mlxtend.frequent_patterns مع تحديد الحد الأدنى للثقة min_threshold (لنأخذ القيمة 60% في مثالنا). # مكتبة خوارزمية إيجاد قواعد الترابط from mlxtend.frequent_patterns import association_rules # توليد القواعد مع تحديد الحد الأدنى للثقة rules = association_rules(frequent_itemsets,metric="confidence",min_threshold=0.6) # الترتيب التنازلي وفق معامل الثقة rules = rules.sort_values(['confidence'], ascending =[False]) print(rules) يُبين الشكل التالي قواعد الترابط الناتجة: يُمكن استخدام رسم الإحداثيات المتوازية parallel_coordinates من المكتبة pandas.plotting لرسم مشاهدة توضيحية للقواعد السابقة. from matplotlib import pyplot as plt from pandas.plotting import parallel_coordinates # دالة تحويل القواعد إلى إحداثيات def rules_to_coordinates(rules): rules['antecedent'] = rules['antecedents'].apply(lambda antecedent: list(antecedent)[0]) rules['consequent'] = rules['consequents'].apply(lambda consequent: list(consequent)[0]) rules['rule'] = rules.index return rules[['antecedent','consequent','rule']] # توليد الإحداثيات المتوازية coords = rules_to_coordinates(rules) # توليد رسم الإحداثيات المتوازية plt.figure(figsize=(4,8)) parallel_coordinates(coords, 'rule') plt.grid(True) plt.show() يكون الرسم البياني الناتج: يُبين الرسم ارتباطات العناصر، وذلك برسم خط بين العنصر من الجهة اليسرى وبين نهاية الخط الأفقي للعنصر الآخر المرتبط معه من الجهة اليمنى، مثلًا يرتبط الحليب Milk مع كل من الخبز Bread و الفوط Diaper. تحميل بيانات المتجر نبدأ أولًا بتحميل بيانات المتجر من الملف Groceries.csv ضمن إطار من البيانات DataFrame من مكتبة Pandas ومن ثم عرض بعضها: # تحميل بيانات المتجر df = pd.read_csv('Groceries.csv',header=None) df.head() يظهر لنا أوائل صفوف الملف: نلاحظ وجود قيم كثيرة فارغة NaN وذلك لأن عدد العناصر في كل صف غير متساوي. نحذف في الشفرة التالية القيم الفارغة، ثم نُنشئ مصفوفة الإجراءات والتي هي مصفوفة يكون كل عنصر منها مصفوفة من عناصر صف واحد من إطار البيانات: # حذف القيم الفارغة # وإنشاء مصفوفة transactions = df.T.apply(lambda x: x.dropna().tolist()).tolist() print(transactions[1:10])) يُبين الشكل التالي مثلًا العناصر العشرة الأولى من مصفوفة الإجراءات الناتجة: نستخدم في الشيفرة التالية مُرمز الإجراءات للحصول على إطار بيانات الإجراءات: # إنشاء غرض من الصف te = TransactionEncoder() # ملائمة المرمز مع البيانات te_model = te.fit(transactions) # تحويل الإجراءات rows=te_model.transform(transactions) # بناء إطار بيانات الإجراءات df = pd.DataFrame(rows, columns=te_model.columns_) print(df.shape) مما يُعطي: (9835, 169) لاحظ أن عدد أعمدة إطار البيانات الناتج هو 169 عمودًا مما يعني وجود 169 عنصرًا مختلفًا فقط في الإجراءات البالغ عددها 9835 إجراء. نستدعي في الشيفرة التالية الدالة apriori والتي تحسب العناصر المتواترة في إطار البيانات df وفق حد أدنى معين للدعم min_support يساوي 0.5% (هو رقم تجريبي حصلنا عليه بتكرار توليد العناصر المتواترة وقواعد الترابط حتى الوصول لقواعد ترابط عددها محدود نسبيًا). يكون ناتج تطبيق هذه الدالة إطار بيانات frequent_itemsets ذي عمودين: مجموعة العناصر المتواترة itemsets والدعم support. نُضيف عمود محسوب جديد لإطار البيانات الناتج يحسب طول length كل مجموعة عناصر. # توليد المجموعات المتواترة مع تحديد الحد الأدنى للدعم frequent_itemsets = apriori(df, min_support=0.005, use_colnames=True) # حساب أطوال مجموعات العناصر frequent_itemsets['length'] = frequent_itemsets['itemsets'].apply(lambda x: len(x)) print(frequent_itemsets) تُبين النتائج أن لدينا 1001 مجموعة من العناصر المتواترة المُحققة للحد الأدنى للدعم ويتراوح طولها بين 1 و 4: يُمكن الآن توليد قواعد الترابط باستخدام إطار بيانات العناصر المتواترة السابق كما تُبين الشيفرة التالية. نستخدم الدالة association_rules مع تحديد الحد الأدنى للثقة 55% (رقم تجريبي حصلنا عليه بعد عدة محاولات لتوليد قواعد الترابط حتى وصلنا لمجموعة معقولة من القواعد). # توليد القواعد مع تحديد الحد الأدنى للثقة rules = association_rules(frequent_itemsets,metric="confidence",min_threshold=0.55) # الترتيب التنازلي وفق معامل الثقة rules = rules.sort_values(['confidence'], ascending =[False]) print(rules) يُبين الشكل التالي قواعد الترابط الناتجة (حوالي 50 قاعدة): يُمكن استخدام رسم الإحداثيات المتوازية لرسم مشاهدة توضيحية للقواعد السابقة: from pandas.plotting import parallel_coordinates # دالة تحويل القواعد إلى إحداثيات def rules_to_coordinates(rules): rules['antecedent'] = rules['antecedents'].apply(lambda antecedent: list(antecedent)[0]) rules['consequent'] = rules['consequents'].apply(lambda consequent: list(consequent)[0]) rules['rule'] = rules.index return rules[['antecedent','consequent','rule']] # توليد الإحداثيات المتوازية coords = rules_to_coordinates(rules) # توليد رسم الإحداثيات المتوازية plt.figure(figsize=(4,8)) parallel_coordinates(coords, 'rule') plt.legend([]) plt.grid(True) plt.show() يكون الرسم البياني الناتج: الخلاصة عرضنا في هذه المقالة خطوات بناء إيجاد قواعد الترابط بين مبيعات العناصر في المتاجر. يُمكن تجربة المثال كاملًا من موقع Google Colab من الرابط أو تنزيله من الملف المرفق. الملف المرفق: data (1).zip اقرأ أيضًا المفاهيم الأساسية لتعلم الآلة تعلم الآلة: التحديات الرئيسية وكيفية التوسع في المجال خطوات تنفيذ مشروع عن تعلم الآلة في بايثون: الجزء الأول النسخة الكاملة لكتاب مدخل إلى الذكاء الاصطناعي وتعلم الآلة
  4. تُعدّ مسألة تصنيف الشخصيات بالاعتماد على تغريداتهم على وسائل التواصل الاجتماعي من المسائل المهمة مثلًا يُمكن أن يكون من المفيد تحديد الأشخاص الذين يكتبون تحليلات مهمة في مجالات الأعمال أو الاقتصاد أو الرياضة وغيرها مما يتيح للآخرين معرفة تقييمات أو آراء الأشخاص المغردين واتخاذ الإجراء المناسب. نعرض في هذه المقالة استخدام تقنيات التعلم العميق في تصنيف الشخصيات المغردة بنصوص مكتوبة باللغة العربية وباللهجة السعودية بمعنى أن اللغة المستخدمة ليست بالضرورة اللغة العربية الفصحى بل يُمكن أن تدخل فيها ألفاظ عامية يستخدمها المغردون عادةً. لتصنيف شخص ما، سنلجأ أولًا إلى تصنيف تغريداته (أي إسناد كل تغريده إلى صف معين)، ومن ثم تصنيفه بناًء على نتائج تصنيف تغريداته (الصفوف ذات التواتر الكبر). بيانات التدريب تحوي مجموعة البيانات المتوفرة حوالي 26500 تغريدة لمجموعة متنوعة من المغردين المشهورين في المملكة العربية السعودية. جُمّعت هذه التغريدات عن طريق مجموعة من الطلاب الجامعيين وذلك من موقع تويتر Twitter. بالطبع، لا يوجد تصنيف متوفر لهذه التغريدات على تويتر. تجدها موجودة هي وبقية ملفات هذا الفصل في الملف المضغوط المرفق. تصنيف بيانات التدريب يتطلب استخدام خوارزميات تعلم الآلة (خوارزميات تصنيف التغريدات في حالتنا) توفر بيانات للتدريب أي مجموعة من التغريدات مُصنفّة مُسبقًا إلى مجموعة من الصفوف، ويُمكن، كما في حالتنا، اللجوء إلى الطرق اليدوية أي الطلب من مجموعة من الأشخاص قراءة النصوص وتصنيفها وهو حل يصلح في حال كان عدد النصوص صغيرًا نسبيًا، ويتميز هذا الحل بالدقة العالية لأن الأشخاص تُدرك، بشكل عام، معاني النصوص من خلال خبرتها اللغوية المُكتسبة وتُصنّف النصوص بشكل صحيح غالبًا. طلبنا من الطلاب المشاركين في مشروعنا تصنيف كل تغريدة إلى واحدة من المواضيع (الصفوف) التالية: table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } الصف بالعربي English الرياضة Sports الأعمال Business التكنولوجيا Technology المجتمع Social السياسة Politics الأخبار News الاقتصاد Economy نُعطي فيما يلي أمثلة عن هذه التغريدات (بعد تصنيفها): "الحمد لله مباراة الدوري وهدف غالي يشابه هدف القناص مباراة الفتح الرائد الهلال" (الرياضة). "قريبا جدا… تتابع السوق السعودي وشركاته والأمريكي وشركاته والعملات والكربتو النفط والذهب بمنصة واحدة مباشرة وتقدر ت…" (الأعمال). "فايروس خطير جدا يستهدف مستخدمي نظام الاندرويد قادر يسرق بيانات حساسه الصور وتسجيل صوت المستخدم والوصول لمعلوماتهم وسرقة…" (التكنولوجيا) "أالسلام عليكم ورحمة الله وبركاتة اللهم فرج يفرج همه ويبارك ماله ويفتح أبواب الخيروال…" (المجتمع) "مبادرون لأجل فلسطين.. تكريم كويتي لرافضي التطبيع في الفعاليات الرياضية والأدبية" (السياسة) "الخط العربي ومخاوف التقنية في الزمن الرقمي.. تجربة عالمية أم خروج عن تقاليد الفن العريق؟" (الأخبار) "معلومة فنية (٢)للشراء المضاربي ١- اقفال السوق ٥ دقايق اذا كانت شمعة ايجابية للحصول ربح مضاربي يوم ٢-عند…" (الاقتصاد). نعرض في هذه المقالة كيفية بناء مُصنّف حاسوبي آلي يُصنّف أي تغريدة عربية إلى أحد الصفوف السبعة السابقة ومن ثم تصنيف الشخص المغرد لواحد أو أكثر من هذه الصفوف (الأكثر تواترًا). المعالجة الأولية للنصوص تتميز التغريدات، بشكل عام، باحتوائها على مجموعة من الأمور غير المهمة في مسألة التصنيف مثل الروابط Links والوسوم Hashtags والرموز التعبيرية Emojis وغيرها. يُبين الشكل التالي مثالًا عن التغريدات المُجمّعة: تهدف المعالجة الأولية إلى الحصول على الكلمات المهمة فقط من النصوص وذلك عن طريق تنفيذ بعض العمليات اللغوية عليها. لتكن لدينا مثلًا الجملة التالية: "أنا أحب الذهاب إلى الحديقة ?، كل يوم 9 صباحاً، مع رفاقي هؤلاء! @toto "، سنقوم بتنفيذ العمليات التالية: حذف الروابط والوسوم والرموز التعبيرية: يكون ناتج الجملة السابقة: "أنا أحب الذهاب إلى الحديقة، كل يوم 9 صباحاً، مع رفاقي هؤلاء!" حذف إشارات الترقيم المختلفة كالفواصل وإشارات الاستفهام وغيرها: يكون ناتج الجملة السابقة: "أنا أحب الذهاب إلى الحديقة كل يوم 9 صباحاً مع رفاقي هؤلاء" حذف الأرقام الواردة في النص: يكون ناتج الجملة السابقة: "أنا أحب الذهاب إلى الحديقة كل يوم صباحاً مع رفاقي هؤلاء" حذف كلمات التوقف stop words وهي الكلمات التي تتكرر كثيرًا في النصوص ولا تؤثر في معانيها كأحرف الجر (من، إلى، …) والضمائر (أنا، هو، …) وغيرها فيكون ناتج الجملة السابقة: " أحب الذهاب الحديقة يوم صباحاً رفاقي" تجذيع الكلمات stemming أي إرجاع الكلمات المتشابهة إلى كلمة واحدة (جذع) مما يُساهم في إنقاص عدد الكلمات الكلية المختلفة في النصوص، ومطابقة الكلمات المتشابهة مع بعضها البعض. مثلًا: يكون للكلمات الأربع: (رائع، رايع، رائعون، رائعين) نفس الجذع المشترك: (رايع) فيكون ناتج الجملة السابقة: " احب ذهاب حديق يوم صباح رفاق" إعداد المشروع يحتاج تنفذ شيفرات هذه المقالة بيئةً برمجيةً للغة بايثون الإصدار 3.8. ويجب أن تتضمن هذه البيئة البرمجية مدير الحِزم pip لتثبيت الحِزم، ومُنشئ البيئات الافتراضية venv لإنشاء بيئاتٍ افتراضيةٍ. نستخدم محرر الشيفرات البرمجية Jupyter Notebooks، وهو مفيد جدًا لتجربة وتشغيل الأمثلة الخاصة بتَعَلّم الآلة بطريقةٍ تفاعليةٍ، حيث نستطيع من خلاله تشغيل كتلًا صغيرةً من الشيفرات البرمجية ورؤية النتائج بسرعة، مما يُسهّل علينا اختبار الشيفرات البرمجية وتصحيحها. نحتاج أولًا لتثبيت بعض التبعيات، وذلك لإنشاء مساحة عمل للاحتفاظ بملفاتنا قبل أن نتمكن من تطوير برنامجنا. نُنشئ مجلدًا جديدًا خاصًا بمشروعنا وندخل إليه هكذا: mkdir arc cd arc نُنفذّ الأمر التالي لإنشاء البيئة الافتراضية: python -m venv arc ومن ثم الأمر التالي في Linux لتنشيط البيئة الافتراضية: source arc/bin/activate أما في Windows، فيكون أمر التنشيط: "arc/Scripts/activate.bat" نستخدم إصداراتٍ محددةٍ من المكتبات اللازمة، من خلال إنشاء ملف requirements.txt في مجلد المشروع، وسيُحدِّد هذا الملف المتطلبات والإصدارات التي سنحتاج إليها. نفتح الملف requirements.txt في محرر النصوص، ونُضيف الأسطر التالية، وذلك لتحديد المكتبات التي نريدها وإصداراتها: absl-py==1.0.0 asttokens==2.0.5 astunparse==1.6.3 backcall==0.2.0 cachetools==5.1.0 certifi==2021.10.8 charset-normalizer==2.0.12 click==8.1.3 colorama==0.4.4 cycler==0.11.0 debugpy==1.6.0 decorator==5.1.1 entrypoints==0.4 executing==0.8.3 flatbuffers==1.12 fonttools==4.33.3 gast==0.4.0 google-auth==2.6.6 google-auth-oauthlib==0.4.6 google-pasta==0.2.0 grpcio==1.46.1 h5py==3.6.0 idna==3.3 imbalanced-learn==0.9.1 imblearn==0.0 importlib-metadata==4.11.3 ipykernel==6.13.0 ipython==8.3.0 jedi==0.18.1 joblib==1.1.0 jupyter-client==7.3.1 jupyter-core==4.10.0 keras==2.6.0 Keras-Applications==1.0.8 Keras-Preprocessing==1.1.2 kiwisolver==1.4.2 libclang==14.0.1 Markdown==3.3.7 matplotlib==3.5.2 matplotlib-inline==0.1.3 nest-asyncio==1.5.5 nltk==3.7 numpy==1.22.3 oauthlib==3.2.0 opt-einsum==3.3.0 packaging==21.3 pandas==1.4.2 parso==0.8.3 pickleshare==0.7.5 Pillow==9.1.1 prompt-toolkit==3.0.29 protobuf==3.20.1 psutil==5.9.0 pure-eval==0.2.2 PyArabic==0.6.14 pyasn1==0.4.8 pyasn1-modules==0.2.8 Pygments==2.12.0 pyparsing==3.0.9 python-dateutil==2.8.2 pytz==2022.1 #pywin32==304 pyzmq==22.3.0 regex==2022.4.24 requests==2.27.1 requests-oauthlib==1.3.1 rsa==4.8 scikit-learn==1.1.0 scipy==1.8.0 seaborn==0.11.2 six==1.16.0 sklearn==0.0 snowballstemmer==2.2.0 stack-data==0.2.0 tensorboard==2.9.0 tensorboard-data-server==0.6.1 tensorboard-plugin-wit==1.8.1 tensorflow==2.9.0 tensorflow-estimator==2.9.0 tensorflow-io-gcs-filesystem==0.26.0 termcolor==1.1.0 threadpoolctl==3.1.0 tornado==6.1 tqdm==4.64.0 traitlets==5.2.1.post0 typing-extensions==4.2.0 urllib3==1.26.9 wcwidth==0.2.5 Werkzeug==2.1.2 wrapt==1.14.1 zipp==3.8.0 نحفظ التغييرات التي طرأت على الملف ونخرج من محرر النصوص، ثم نُثَبت هذه المكتبات بالأمر التالي: (arc) $ pip install -r requirements.txt بعد تثبيتنا لهذه التبعيات، نُصبح جاهزين لبدء العمل على مشروعنا. كتابة الشيفرة البرمجية نُشغّل محرر الشيفرات البرمجية Jupyter Notebook بمجرد اكتمال عملية التثبيت هكذا: (arc) $ jupyter notebook ثم نُنشئ ملفًا جديدًا في داخل المحرر ونُسمّه باسم ac مثلًا. تحميل البيانات نبدأ أولًا بتحميل التغريدات من الملف tweets.csv ضمن إطار من البيانات DataFrame من مكتبة Pandas ومن ثم عرض بعضها: import pandas as pd # قراءة التغريدات وتحميلها ضمن إطار من البيانات tweets = pd.read_csv('tweets.csv',encoding = "utf-8") # إظهار الجزء الأعلى من إطار البيانات tweets.head() يظهر لنا أوائل التغريدات: يُمكن استخدام خاصية الشكل shape لمعرفة عدد الصفوف والأعمدة للبيانات المُحمّلة: print('Data size:', tweets.shape) يكون الناتج: Data size: (26748, 2) المعالجة الأولية للنصوص نستخدم فيما يلي بعض الخدمات التي توفرها المكتبة nltk لمعالجة اللغات الطبيعية كتوفير قائمة كلمات التوقف باللغة العربية (حوالي 700 كلمة) واستخراج الوحدات tokens من النصوص. كما نستخدم مجذع الكلمات العربية من مكتبة snowballstemmer. كما نستخدم التعابير النمطية regular expressions للتعرف على الرموز التعبيرية والوسوم والروابط وحذفها. # مكتبة السلاسل النصية import string # مكتبة التعابير النظامية import re # مكتبة معالجة اللغات الطبيعية import nltk #nltk.download('punkt') #nltk.download('stopwords') # مكتبة كلمات التوقف from nltk.corpus import stopwords # مكتبة استخراج الوحدات from nltk.tokenize import word_tokenize # مكتبة المجذع العربي from snowballstemmer import stemmer ar_stemmer = stemmer("arabic") # دالة حذف المحارف غير اللازمة def remove_chars(text, del_chars): translator = str.maketrans('', '', del_chars) return text.translate(translator) # دالة حذف المحارف المكررة def remove_repeating_char(text): return re.sub(r'(.)\1{2,}', r'\1', text) # دالة تنظيف التغريدات def clean_tweet(tweet): stop_words = stopwords.words('arabic') # محارف الرموز التعبيرية emoj = re.compile("[" u"\U0001F600-\U0001F64F" u"\U0001F300-\U0001F5FF" u"\U0001F680-\U0001F6FF" u"\U0001F1E0-\U0001F1FF" u"\U00002500-\U00002BEF" u"\U00002702-\U000027B0" u"\U00002702-\U000027B0" u"\U000024C2-\U0001F251" u"\U0001f926-\U0001f937" u"\U00010000-\U0010ffff" u"\u2640-\u2642" u"\u2600-\u2B55" u"\u200d" u"\u23cf" u"\u23e9" u"\u231a" u"\ufe0f" u"\u3030" "]+", re.UNICODE) tweet = str(tweet) # حذف @ وما يتبعها tweet = re.sub("@[^\s]+","",tweet) tweet = re.sub("RT","",tweet) # حذف الروابط tweet = re.sub(r"(?:\@|http?\://|https?\://|www)\S+", "", tweet) # حذف الرموز التعبيرية tweet = re.sub(emoj, '', tweet) # حذف كلمات التوقف tweet = ' '.join(word for word in tweet.split() if word not in stop_words) # حذف الإشارات # tweet = tweet.replace("#", "").replace("_", " ") # حذف الأرقام tweet = re.sub(r'[0-9]+', '', tweet) # حذف المحارف غير اللازمة # علامات الترقيم العربية arabic_punctuations = '''`÷×؛<>_()*&^%][ـ،/:"؟.,'{}~¦+|!”…“–ـ''' # علامات الترقيم الإنجليزية english_punctuations = string.punctuation # دمج علامات الترقيم العربية والانكليزية punctuations_list = arabic_punctuations + english_punctuations tweet = remove_chars(tweet, punctuations_list) # حذف المحارف المكررة tweet = remove_repeating_char(tweet) # استبدال الأسطر الجديدة بفراغات tweet = tweet.replace('\n', ' ') # حذف الفراغات الزائدة من اليمين واليسار tweet = tweet.strip(' ') return tweet # دالة تقسيم النص إلى مجموعة من الوحدات def tokenizingText(text): tokens_list = word_tokenize(text) return tokens_list # دالة حذف كلمات التوقف def filteringText(tokens_list): # قائمة كلمات التوقف العربية listStopwords = set(stopwords.words('arabic')) filtered = [] for txt in tokens_list: if txt not in listStopwords: filtered.append(txt) tokens_list = filtered return tokens_list # دالة التجذيع def stemmingText(tokens_list): tokens_list = [ar_stemmer.stemWord(word) for word in tokens_list] return tokens_list # دالة دمج قائمة من الكلمات في جملة def toSentence(words_list): sentence = ' '.join(word for word in words_list) return sentence شرح الدوال السابقة: الدالة clean_tweet تحذف الرموز التعبيرية والروابط والوسوم والأرقام وعلامات الترقيم العربية والإنكليزية من النص وذلك باستخدام التعابير النظامية الموافقة. الدالة remove_repeating_char تحذف المحارف المكررة والتي قد يستخدمها كاتب التغريدة. الدالة tokenizingText تعمل على تجزئة النص إلى قائمة من الوحدات tokens. الدالة filteringText تحذف كلمات التوقف من قائمة الوحدات. الدالة stemmingText تعمل على تجذيع كلمات قائمة الوحدات المتبقية. يُبين المثال التالي نتيجة استدعاء كل دالة من الدوال السابقة: # مثال text= "أنا أحب الذهاب إلى الحديقة ?، كل يوم 9 صباحاً، مع رفاقي هؤلاء! @toto " print(text) text=clean_tweet(text) print(text) tokens_list=tokenizingText(text) print(tokens_list) tokens_list=filteringText(tokens_list) print(tokens_list) tokens_list=stemmingText(tokens_list) print(tokens_list) يكون ناتج التنفيذ: تعرض الشيفرة التالية التصريح عن الدالة process_tweet والتي تقوم أولًا بتنظيف التغريدات وذلك باستدعاء الدالة clean_tweet، ومن ثم تحويل التغريدات إلى وحدات وذلك باستدعاء الدالة tokenizingText، وأخيرًا تجذيع الوحدات عن طريق الدالة stemmingText. ومن ثم تنفيذ دالة المعالجة الأولية على جميع التغريدات: # دالة معالجة التغريدات def process_tweet(tweet): # تنظيف التغريدة tweet=clean_tweet(tweet) # التحويل إلى وحدات tweet=tokenizingText(tweet) # التجذيع tweet=stemmingText(tweet) return tweet # المعالجة الأولية للتغريدات tweets['tweet'] = tweets['tweet'].apply(process_tweet) موازنة الصفوف تتطلب معظم خوارزميات التصنيف توفر بيانات للتدريب وبصفوف متوازنة، بمعنى أن يكون عدد أسطر البيانات من كل صف متساوية تقريبًا تجنبًا لانحياز المُصنف إلى الصف ذي العدد الأكبر من الأسطر في بيانات التدريب. من المفيد إذًا أولًا معاينة توزع أعداد الصفوف. نستخدم في الشيفرة البرمجية التالية مكتبات الرسم اللازمة لرسم أشرطة تُمثّل أعداد الصفوف: # مكتبات الرسم import matplotlib.pyplot as plt import seaborn as sns # حجم الرسم plt.figure(figsize=(12, 6)) # رسم عدد كل صف sns.countplot(data=tweets, y='topic'); plt.title('Topics Distribution', fontsize=18) plt.show() يُبين الشكل الناتج عدم توازن الصفوف على الإطلاق: نستخدم في الشيفرة التالية الصنف RandomOverSampler من المكتبة imblearn.over_sampling والذي يقوم باختيار أسطر عشوائية من الصفوف القليلة العدد ويُكررها في مجموعة البيانات. # استيراد مكتبة الموازنة from imblearn.over_sampling import RandomOverSampler # إنشاء كائن من الصنف oversample = RandomOverSampler() # توليد سطر عشوائي tweets = tweets.sample(frac=1) # توليد الأسطر الجديدة tweets, Y = oversample.fit_resample(tweets, tweets.topic) نعيد رسم أعداد الصفوف بعد الموازنة: # إعادة رسم أعداد الصفوف # بعد الموازنة plt.figure(figsize=(12, 6)) sns.countplot(data=tweets, y='topic'); plt.title('Topics Distribution After OverSampling', fontsize=18) plt.show() يُبين الشكل الناتج توازن الصفوف بشكل كامل: ترميز الصفوف لا تقبل بنى تعلم الآلة النصوص كمدخلات لها، تقوم الشيفرة التالية باستخدام الصنف LabelEncoder من المكتبة sklearn.preprocessing لترميز الصفوف باستخدام الأرقام. نطبع في النهاية أسماء الصفوف والترميز المقابل لها: from sklearn.preprocessing import LabelEncoder # ترميز الصفوف le_topics = LabelEncoder() tweets['topic'] = tweets[['topic']].apply(le_topics.fit_transform) classes = le_topics.classes_ # الصفوف n_classes = len(classes) # عدد الصفوف print("No. of classes:", n_classes) print("Classes:", classes) print("Coding: ", le_topics.transform(classes)) يكون الإظهار: No. of classes: 7 Classes: ['Business' 'Economy' 'News' 'Politics' 'Social' 'Sports' 'Technology'] Coding: [0 1 2 3 4 5 6] تحويل النصوص إلى أشعة رقمية لا تقبل بنى تعلم الآلة النصوص كمدخلات لها، بل تحتاج إلى أشعة رقمية كمدخلات. نستخدم الشيفرة التالية لتحويل الشعاع النصي لكل تغريدة tweet_preprocessed إلى شعاع رقمي: from keras.preprocessing.text import Tokenizer from keras.preprocessing.sequence import pad_sequences # نركيب جمل التغريدات من المفردات المعالجة sentences = tweets['tweet'].apply(toSentence) print(sentences[6]) # عدد الكلمات الأعظمي ذات التواتر الأكبر # التي ستُستخدم max_words = 5000 # الطول الأعظمي لشعاع الأرقام max_len = 50 # التصريح عن المجزئ # مع تحديد عدد الكلمات التي ستبقى # بالاعتماد على تواترها tokenizer = Tokenizer(num_words=max_words ) # ملائمة المجزئ لنصوص التغريدات tokenizer.fit_on_texts(sentences) # تحويل النص إلى قائمة من الأرقام S = tokenizer.texts_to_sequences(sentences) print(S[0]) # توحيد أطوال الأشعة X = pad_sequences(S, maxlen=max_len) print(X[0]) X.shape نجد من الشيفرة أن المتغير max_words يُحدّد عدد الكلمات الأعظمي التي سيتم الاحتفاظ بها حيث يُحسب تواتر كل كلمة في كل النصوص ومن ثم تُرتب حسب تواترها (المرتبة الأولى للكلمة ذات التواتر الأكبر). ستُهمل الكلمات ذات المرتبة أكبر من max_words، و يُحدّد المتغير max_len طول الشعاع الرقمي النهائي فإذا كان موافقًا لنص أقل من max_len تُضاف أصفار للشعاع حتى يُصبح طوله مساويًا إلى max_len. أما إذا كان طوله أكبر يُقتطع جزءًا منه ليُصبح طوله مساويًا إلى max_len. بينما تقوم الدالة fit_on_texts بملائمة المُجزء tokenizer لنصوص جمل التغريدات sentences.values أي حساب تواتر الكلمات والاحتفاظ بالكلمات ذات التواتر أكبر أو يساوي max_words. نطبع في الشيفرة السابقة، بهدف التوضيح، ناتج كل مرحلة. اخترنا مثلًا شعاع التغريدة 6 بعد المعالجة: تكون نتيجة تحويل الشعاع السابق النصي إلى شعاع من الأرقام: [1839, 1375, 2751, 315, 975, 1420, 1839, 3945, 436, 794, 919, 445, 1290, 312, 258] وبعد عملية توحيد الطول يكون الشعاع الرقمي النهائي الناتج: [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1839 1375 2751 315 975 1420 1839 3945 436 794 919 445 1290 312 258] تجهيز دخل وخرج الشبكة العصبية تعرض الشيفرة التالية حساب شعاع الخرج أولًا وذلك بإسناد العمود topic من إطار البيانات، والذي يحوي الترميز الرقمي للصفوف إلى المتغير y. نستخدم الدالة train_test_split لتقسيم البيانات المتاحة إلى 80% منها لعملية التدريب و20% لعملية الاختبار وحساب مقاييس الأداء: # توليد شعاع الخرج y = tweets['topic'] # مكنبة تقسيم البيانات إلى تدريب واختبار from sklearn.model_selection import train_test_split # تقسيم البيانات إلى تدريب واختبار X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0) print(X_train.shape, y_train.shape) print(X_test.shape, y_test.shape) نطبع في الشيفرة السابقة حجوم أشعة الدخل والخرج للتدريب وللاختبار: (30520, 50) (30520,) (7630, 50) (7630,) نموذج الشبكة العصبية المتعلم تُعدّ المكتبة Keras من أهم مكتبات بايثون التي توفر بناء شبكات عصبية لمسائل التعلم الآلي. تعرض الشيفرة التالية التصريح عن دالة بناء نموذج التعلّم create_model مع إعطاء جميع المعاملات المترفعة قيمًا ابتدائية: # تضمين النموذج التسلسلي from keras.models import Sequential # تضمين الطبقات اللازمة from keras.layers import Embedding, Dense, LSTM # دوال التحسين from tensorflow.keras.optimizers import Adam, RMSprop # التصريح عن دالة إنشاء نموذج التعلم # مع إعطاء قيم أولية للمعاملات المترفعة def create_model(embed_dim = 32, hidden_unit = 16, dropout_rate = 0.2, optimizers = RMSprop, learning_rate = 0.001): # التصريح عن نموذج تسلسلي model = Sequential() # طبقة التضمين model.add(Embedding(input_dim = max_words, output_dim = embed_dim, input_length = MAX_LENGTH)) # LSTM model.add(LSTM(units = hidden_unit ,dropout=dropout_rate)) # الطبقة الأخيرة model.add(Dense(units = len(classes), activation = 'softmax')) # يناء النموذج model.compile(loss = 'sparse_categorical_crossentropy', optimizer = optimizers(learning_rate = learning_rate), metrics = ['accuracy']) # طباعة ملخص النموذج print(model.summary()) return model نستخدم من أجل مسألتنا نموذج شبكة عصبية تسلسلي يتألف من ثلاث طبقات هي: طبقة التضمين Embedding وطبقة LSTM (شبكة ذات ذاكرة طويلة المدى) والطبقة الكثيفة Dense. الطبقة الأولى: طبقة التضمين Embedding نستخدم هذه الطبقة لتوليد ترميز مكثف للكلمات dense word encoding مما يُساهم في تحسين عملية التعلم. نطلب تحويل الشعاع الذي طوله input_length (في حالتنا 50) والذي يحوي قيم ضمن المجال input_dim (من 1 إلى 5000 في مثالنا) إلى شعاع من القيم ضمن المجال output_dim (مثلًا 32 قيمة). الطبقة الثانية: شبكة ذات ذاكرة طويلة المدى Long Short-Term Memory يُحدّد المعامل المترفع units عدد الوحدات المخفية لهذه الطبقة. يُساهم المعامل dropout في معايرة الشبكة خلال التدريب حيث يقوم بإيقاف تشغيل الوحدات المخفية بشكل عشوائي أثناء التدريب، وبهذه الطريقة لا تعتمد الشبكة بنسبة 100٪ على جميع الخلايا العصبية الخاصة بها. وبدلاً من ذلك، تُجبر نفسها على العثور على أنماط أكثر أهمية في البيانات من أجل زيادة المقياس الذي تحاول تحسينه (الدقة مثلًا). الطبقة الثالثة: الكثيفة Dense يُحدّد المعامل units حجم الخرج لهذه الطبقة (7 في حالتنا: عدد الصفوف) ويُبين الشكل التالي ملخص النموذج: معايرة المعاملات الفائقة للوصول لنموذج أمثلي يمكن الوصول لنموذج تعلم أمثلي بمعايرة معاملاته الفائقة وفق معطيات المشروع. لنُبين أولًا الفرق بين المعاملات الفائقة لنموذج والمعاملات الأخرى له: المعاملات الفائقة hyperparameters: هي إعدادات خوارزمية التعلّم قبل التدريب (والتي وضعها مصممو الخوارزمية). المعاملات parameters: هي المعاملات التي يتعلّمها النموذج أثناء التدريب مثل أوزان الشبكة العصبية. تؤثر عملية معايرة المعاملات الفائقة على أداء النموذج لاسيما لجهة التوزان المطلوب بين مشكلة قلة التخصيص underfitting ومشكلة فرط التخصيص overfitting واللتان تؤديان إلى نموذج غير قادر على تعميم أمثلة التدريب وبالتالي لن يتمكن من التصنيف مع معطيات جديدة (يُمكن العودة لمقال تعلم الآلة: التحديات الرئيسية وكيفية التوسع في المجال من أكاديمية حسوب للمزيد من التفصيل حول هاتين المشكلتين). تظهر مشكلة قلة التخصيص عندما لا يكون للنموذج درجات حرية كافية ليتعلّم الربط بين الميزات والهدف، وبالتالي يكون له انحياز كبير Bias–variance tradeoff نحو قيم معينة للهدف. يُمكن تصحيح قلة التخصيص بجعل النموذج أكثر تعقيدًا. أما مشكلة فرط التخصيص فتظهر عندما يقوم النموذج بتخزين بيانات التدريب فيكون له بالتالي تباين كبير والذي يُمكن تصحيحه بالحد من تعقيد النموذج باستخدام التسوية regularization. تكمن المشكلة في معايرة المعاملات الفائقة بأن قيمها المثلى تختلف من مسألة لأخرى! وبالتالي، فإن الطريقة الوحيدة للوصول لهذه القيم المثلى هي تجريب قيم مختلفة مع كل مجموعة بيانات تدريب جديدة. يوفر Scikit-Learn العديد من الطرق لتقويم المعاملات الفائقة وبالتالي سنعتمد في مشروعنا عليها دون أن نُعقّد الأمور أكثر. يُمكن العودة إلى مقال تحليل المشاعر في اللغة العربية باستخدام التعلم العميق فقرة "البحث الشبكي مع التقييم المتقاطع" لشرح طريقة حسابنا لأفضل القيم للمعاملات المترفعة. بناء نموذج التعلم النهائي نستخدم الدالة KerasClassifier من scikit لبناء المُصنف مع الدالة السابقة create_model: # مكتبة التصنيف from keras.wrappers.scikit_learn import KerasClassifier # إنشاء النموذج مع قيم المعاملات المترفعة الأمثلية model = KerasClassifier(build_fn = create_model, # معاملات النموذج dropout_rate = 0.2, embed_dim = 32, hidden_unit = 64, optimizers = Adam, learning_rate = 0.001, # معاملات التدريب epochs=10, batch_size=256, # نسبة بيانات التقييم validation_split = 0.1) # ملائمة النموذج مع بيانات التدريب model_prediction = model.fit(X_train, y_train) يُمكن الآن رسم منحني الدقة accuracy لكل من بيانات التدريب والتقييم (لاحظ أننا في الشيفرة السابقة احتفاظنا بـ 10% من بيانات التدريب للتقييم): # معاينة دقة النموذج # التدريب والتقييم fig, ax = plt.subplots(figsize = (10, 4)) ax.plot(model_prediction.history['accuracy'], label = 'train accuracy') ax.plot(model_prediction.history['val_accuracy'], label = 'val accuracy') ax.set_title('Model Accuracy') ax.set_xlabel('Epoch') ax.set_ylabel('Accuracy') ax.legend(loc = 'upper left') plt.show() يكون للمنحي الشكل التالي: حساب مقاييس الأداء يُمكن الآن حساب مقاييس الأداء المعروفة في مسائل التصنيف (الصحة Accuracy، الدقة Precision، الاستذكار Recall، المقياس F1) للنموذج المتعلم باستخدام الشيفرة التالية: # مقاييس الأداء # مقياس الصحة from sklearn.metrics import accuracy_score # مقياس الدقة from sklearn.metrics import precision_score # مقياس الاستذكار from sklearn.metrics import recall_score # f1 from sklearn.metrics import f1_score # مصفوفة الارتباك from sklearn.metrics import confusion_matrix # تصنيف بيانات الاختبار y_pred = model.predict(X_test) # حساب مقاييس الأداء accuracy = accuracy_score(y_test, y_pred) precision=precision_score(y_test, y_pred , average='weighted') recall= recall_score(y_test, y_pred, zero_division=1, average='weighted') f1= f1_score(y_test, y_pred, zero_division=1, average='weighted') print('Model Accuracy on Test Data:', accuracy*100) print('Model Precision on Test Data:', precision*100) print('Model Recall on Test Data:', recall*100) print('Model F1 on Test Data:', f1*100) confusion_matrix(y_test, y_pred) تكون النتائج: Model Accuracy on Test Data: 90.90 Model Precision on Test Data: 90.88 Model Recall on Test Data: 90.90 Model F1 on Test Data: 90.86 array([[ 964, 22, 24, 57, 16, 12, 19], [ 18, 1029, 26, 20, 15, 9, 8], [ 13, 18, 1033, 19, 5, 8, 3], [ 45, 19, 52, 871, 59, 12, 10], [ 11, 25, 18, 38, 990, 11, 3], [ 3, 10, 13, 3, 15, 986, 3], [ 4, 10, 8, 2, 0, 8, 1063]], dtype=int64) لاحظ ارتفاع قيم جميع المقاييس مما يعني جودة المُصنف. يُمكن رسم مصفوفة الارتباك confusion matrix بشكل أوضح باستخدام المكتبة seaborn: # رسم مصفوفة الارتباك import seaborn as sns sns.set(style = 'whitegrid') fig, ax = plt.subplots(figsize = (8,6)) sns.heatmap(confusion_matrix(y_true = y_test, y_pred = y_pred), fmt = 'g', annot = True) ax.xaxis.set_label_position('top') ax.xaxis.set_ticks_position('top') ax.set_xlabel('Prediction', fontsize = 14) ax.set_ylabel('Actual', fontsize = 14) plt.show() مما يُظهر المخطط التالي: يُمكن حساب بعض مقاييس الأداء الأخرى المُستخدمة في حالة وجود أكثر من صف في المسألة (Micro, Macro, Weighted): # مقاييس الأداء في حالة أكثر من صفين print('\nAccuracy: {:.2f}\n'.format(accuracy_score(y_test, y_pred))) print('Micro Precision: {:.2f}'.format(precision_score(y_test, y_pred, average='micro'))) print('Micro Recall: {:.2f}'.format(recall_score(y_test, y_pred, average='micro'))) print('Micro F1-score: {:.2f}\n'.format(f1_score(y_test, y_pred, average='micro'))) print('Macro Precision: {:.2f}'.format(precision_score(y_test, y_pred, average='macro'))) print('Macro Recall: {:.2f}'.format(recall_score(y_test, y_pred, average='macro'))) print('Macro F1-score: {:.2f}\n'.format(f1_score(y_test, y_pred, average='macro'))) print('Weighted Precision: {:.2f}'.format(precision_score(y_test, y_pred, average='weighted'))) print('Weighted Recall: {:.2f}'.format(recall_score(y_test, y_pred, average='weighted'))) print('Weighted F1-score: {:.2f}'.format(f1_score(y_test, y_pred, average='weighted'))) # تقرير التصنيف from sklearn.metrics import classification_report print('\nClassification Report\n') print(classification_report(y_test, y_pred, target_names=classes)) مما يُعطي الناتج التالي: لاحظ ارتفاع جميع المقاييس مما يعني جودة المُصنف. تصنيف الأشخاص يُمكن الآن تصنيف الأشخاص وذلك وفق تصنيفات تغريداتهم. تقوم الشيفرة التالية بتصنيف تغريدة واحدة، فيكون دخل الدالة classify_tweet سلسلة نصية نضعها أولًا في متجهة تحوي النص. نستدعي دالة تحويل النص إلى أرقام tokenizer.texts_to_sequences ومن ثم توحيد طول المتجهة الرقمية الناتجة وذلك باستدعاء الدالة pad_sequences. # دالة تصنيف تغريدة def classify_tweet(tweet): # تحويل شعاع الكلمات إلى جملة tweet = toSentence(tweet) # وضع الجملة في شعاع ar=[] ar.append(tweet) # تحويل النص إلى قائمة من الأرقام seq = tokenizer.texts_to_sequences(ar) # توحيد طول المتجهة الرقمية pseq = pad_sequences(seq, maxlen=max_len) # استدعاء دالة التنبؤ للنموذج pred = model.predict(pseq) return pred تقوم الدالة classify_person بتصنيف شخص، ويكون معامل الدالة اسم الشخص (بفرض أن ملف تغريداته يحمل نفس الاسم مع اللاحقة csv)، إذ تعمل الدالة أولًا على تحميل تغريدات الشخص في إطار بيانات df. وأخيرًا تكون دالة تصنيف الشخص classify_person هي: # دالة تصنيف الشخص def classify_person(person_name): # تحميل تغريدات الشخص # في إطار بيانات path = person_name + '.csv' df = pd.read_csv(path) # إنشاء قاموس لعد # التغريدات من كل صف classes_count=dict() # إعطاء قيم ابتدائيه 0 for i in range(len(classes)): key=classes[i] classes_count[key]=0 # الحد الأدنى لطول التغريدة min_tweet_len=5 total=0 for _, row in df.iterrows(): tweet=row['tweet'] # تنظيف التغريدة processed_tweet=process_tweet(tweet) if len(processed_tweet)>min_tweet_len: # تصنيف التغريدة c= classify_tweet(processed_tweet) # إيجاد اسم الصف من رمزه topic=le_topics.inverse_transform(c)[0] # إضافة 1 للصف الموافق classes_count[topic]=classes_count[topic]+1 total=total+1 # ترتيب الصفوف وفق العدد # تنازلياً sorted_classes = sorted(classes_count, key=classes_count.get,reverse=True) # القاموس النهائي sorted_classes_cleaned = {} min_display=total/25 # إهمال الصفوف ذات العدد الصغير for w in sorted_classes: if classes_count[w]>min_display: sorted_classes_cleaned[w] = classes_count[w] # طباعة النتائج print(sorted_classes_cleaned) n=0 for key, value in sorted_classes_cleaned.items(): n=n+value print(person_name, "is classified as :") for key, value in sorted_classes_cleaned.items(): print(key, "(", "{:.2f}".format((value/n)*100) , "%)") # رسم فطيرة أعداد الصفوف x = sorted_classes_cleaned.keys() y = sorted_classes_cleaned.values() import matplotlib.pyplot as plt # pie plt.figure(figsize=(9,9)); plt.title(person_name, fontdict = {'fontsize':20}) plt.pie(y, labels = x,autopct='%1.1f%%') plt.show() # مثال classify_person("salem") نجد من الشيفرة السابقة، تُنشئ الدالة القاموس classes_count والذي يكون مفتاحه اسم الصف وقيمته ستكون عدد التغريدات من هذا الصف (تُعطي أولًا قيمة ابتدائية 0 لكل قيم القاموس). يُحدّد المتغير min_tweet_len الطول الأدنى للتغريدة لتؤخذ بعين الاعتبار (لا تحمل التغريدات الصغيرة جدًا معاني بل تكون على الأغلب عبارات مجاملة وترحيب). تدور الدالة على تغريدات الشخص وتستدعي من أجل كل تغريدة دالة المعالجة الأولية للتغريدة process_tweet ثم دالة التصنيف السابقة classify_tweet. يكون ناتج التصنيف رقم (ترميز الصف) ولذا تستدعي الدالة inverse_transform للحصول على اسم الصف ثم نزيد عدد الصف الموافق في القاموس بـ 1. يحسب المتغير total العدد الكلي للتغريدات التي تم أخذها بعين الاعتبار، وتُستخدم الدالة المتغير sorted لترتيب القاموس تنازليا (المعامل reverse=True) وفق العدد. نضع في المتغير min_display مثلًا القيمة total/25 وذلك بهدف عدم إظهار صفوف الشخص قليلة التواتر في تغريداته، ونضع أخيرًا في القاموس sorted_classes_cleaned الصفوف الأكثر تواترًا ونطبع النتائج ونرسم فطيرة تُمثل النسب المئوية لتغريدات الشخص. تكون النتائج مثلًا: الخلاصة عرضنا في هذه المقالة خطوات بناء نموذج تعلّم لتصنيف الأشخاص وفق تغريداتهم. يُمكن تجربة المثال كاملًا من موقع Google Colab من الرابط أو من الملف المرفق data.zip. اقرأ أيضًا تحليل المشاعر في النصوص العربية باستخدام التعلم العميق دليل المبتدئين لفهم أساسيات التعلم العميق خطوات تنفيذ مشروع عن تعلم الآلة في بايثون: الجزء الأول data.zip
  5. نعرض في هذه المقالة الإرشادات العامة الأساسية الواجب اتباعها لإظهار المحتوى، ولا سيما النصوص الطويلة نسبيًا بوضوح على مختلف أنواع ومقاسات شاشات العرض. القراءة على الويب يُلخص الدليل الإرشادي للكتابة الموضوع من قِبل الحكومة الأمريكية ما يريده الأشخاص من الكتابة على الويب بما يلي: تُظهر الأبحاث أن الأشخاص لا يقرؤون صفحات الويب بتمعُّن، وإنما كل ما يفعلونه هو مسحها سريعًا؛ حيث يقرأ الأشخاص حوالي 20-28% فقط من محتوى صفحة الويب وسطيًا. تكون القراءة من الشاشة أبطأ من قراءة الورق. سيهجر الأشخاص موقع الويب ويغادروه، إذا لم يكن من السهل الوصول إلى معلوماته وفهمها. الكتابة للجوال يُعدّ التركيز على الموضوع المطروح ووضع خلاصته أولًا من القواعد الأساسية للكتابة للجوال. يجب توضيح النقاط الرئيسية للموضوع في البداية؛ حيث تنص القاعدة العامة وعلى نحوٍ مثالي بوجوب وضع النقاط الأساسية في الفقرات الأربع الأولى وبما لا يزيد عن 70 كلمة لتُناسب الكتابة مختلف الأجهزة وإطارات العرض. يجب التأكد من أن المحتوى موجَّهٌ لمساعدة زوار الموقع في تحقيق أهدافهم، لذا يجب البدء أولًا بتحديد الشريحة المستهدفة وتحديد توقعات المستخدمين واحتياجاتهم. يجب الكتابة باستخدام أسلوب الخطاب المباشر وعرض الإجراءات والحلول العملية؛ كما يجب نشر ما يريده الزوار والابتعاد عن الحشو والتكرار. تُظهر أبحاث الحكومة البريطانية ما يلي أيضًا: والخلاصة هي أنه يجب استخدام لغةٍ بسيطة وكلمات أقصر وتركيبات جمل سهلة حتى مع الجمهور المتعلِّم والتقني؛ كما يجب الحفاظ على نبرةٍ خطابية ما لم يكن هناك سببٌ وجيهٌ لخلاف ذلك. تنص أحد القواعد القديمة للصحافة بأن نكتب كما لو كنا نتحدث إلى شخص ذكي يبلغ 11 عامًا. المستخدمون القادمون يُعدّ أسلوب الكتابة المُختزل ضروريًا للقراء على الأجهزة المحمولة خصوصًا، وهو أمرٌ بالغ الأهمية عند إنشاء محتوى الهواتف منخفضة التكلفة ذات إطارات العرض الصغيرة، والتي تتطلب مزيدًا من التمرير وقد تحتوي على شاشاتٍ ذات جودةٍ منخفضة واستجابة ضعيفة. يمتلك معظم مستخدمي الويب، والبالغ عددهم أكثر من مليار مستخدم، أجهزةً رخيصة، ولا يرغبون في إنفاق كلفة الاتصال بالويب على التنقل في محتوًى طويل، كما أنهم قد لا يقرؤون بلغتهم الأم؛ لذلك يجب دومًا اختصار النص، أي استخدام جملٍ قصيرة وعلامات ترقيم أقل وفقرات من خمسة أسطر أو أقل وعناوين على سطر واحد فقط؛ كما يجب استخدام النصوص المتجاوبة، مثل استخدام عناوين أقصر لإطارات العرض الصغيرة، مع الحذر من الجوانب السلبية. يؤدي اتباع أسلوب الحد الأدنى من النص إلى تسهيل توطين المحتوى وتدويله أيضًا، ويزيد من احتمالية اقتباس المحتوى في وسائل التواصل الاجتماعي. يجب الإلتزام بقواعد الحد الأدنى: الحفاظ على البساطة. تقليل الحشو والجمل السردية الطويلة. التوجُّه للمغزى المفيد مباشرةً. حذف المحتوى غير الضروري يتزايد حجم صفحات الويب يومًا بعد يوم؛ كما تتيح تقنيات التصميم المتجاوب -التي عرضناها سابقًا- تقديم محتوًى مختلف لإطارات العرض الأصغر، ولكن من الأجدر البدء بتبسيط النص والصور والمحتويات الأخرى دائمًا. يقول جاكوب نيلسون Jakob Nielsen: يجب التساؤل عن أهداف زوار الموقع دومًا وفيما إذا كان كل مكوّن في الصفحة يُساعد الزوار في الوصول لأهدافهم. حذف عناصر الصفحة المكررة يبلغ الحجم الوسطي لملفات HTML حوالي 70 كيلو بايت مع أكثر من تسعة طلبات لصفحة الويب الواحدة وسطيًا وفق أرشيف HTTP. تستخدم العديد من المواقع الشهيرة عدة آلافٍ من عناصر HTML في كل صفحة، وعدة آلافٍ من سطور التعليمات البرمجية، وذلك حتى على أجهزة الجوال. قد لا يجعل الحجم الزائد لملف HTML عملية التحميل أبطأ، إلا أنه يُعطي إشاراتٍ واضحة على تضخُّم المحتوى؛ حيث يُشير إلى عناصر أكثر ونصوصًا أكبر أو الأمرين معًا. يؤدي تخفيض تعقيد HTML إلى تخفيض حجم الصفحة والمساعدة في التخصيص المحلي والدولي وتسهيل تخطيط التصميم المتجاوب وتصحيحه. للحصول على معلوماتٍ حول كتابة HTML بكفاءة أكبر، يُمكن الرجوع إلى HTML عالي الأداء. من التغريدات الشهيرة لكاربور سيل Gabor Cselle على تويتر: ينطبق نفس الأمر على المحتوى؛ حيث يجب مساعدة المستخدمين في الوصول إلى المطلوب بأسرع ما يُمكن؛ كما لا يجب إخفاء المحتوى لمستخدمي الجوال فقط. يجب محاولة تحقيق مبدأ تكافؤ المحتوى، لأن تخمين الميزات التي لن يفقدها مستخدمو الجوال قد يكون خاطئًا مع بعض الأشخاص. يجب إنشاء إصداراتٍ مختلفة من نفس المحتوى في حال توفر الموارد لتُناسب الحجوم المختلفة لإطارات العرض، أو على الأقل لعناصر الصفحة ذات الأولوية العالية. يجب أخذ إدارة المحتوى وتسلسل خطوات العمل بالحسبان: هل تؤدي الأنظمة القديمة إلى محتوًى قديم؟ تبسيط النص يتزايد تصفح الويب على أجهزة الجوال مما يُلزم تغيير طريقة الكتابة للوصول إلى محتوًى أسهل يذهب مباشرًة للمغزى المقصود بعيدًا عن الحشو بلا فائدة. حذف الصور المكررة يُمكن أن تكون الصور جميلةً وممتعةً وغنيةً بالمعلومات، إلا أنها تستخدم موارد الصفحة وتُضيف إلى حجمها وتزيد من عدد طلبات الملفات. تؤدي رداءة الاتصال إلى زيادة زمن الاستجابة؛ مما يعني أن الزيادة في طلبات ملفات الصور ستُفاقم المشكلة عند فتح الموقع من الجوال. يُظهر موقع أرشفة بيانات HTTP أن صفحات الويب تطلب ملفات الصور 54 مرةً وسطيًا: كما تُشكّل الصور أكثر من 60% من حجم الصفحة: تستهلك الصور الطاقة أيضًا، حيث يُعدّ الاتصال ثاني أكبر سببٍ لاستنفاد بطارية الجوال بعد الشاشة؛ وهذا يعني أن زيادة طلبات الصور تستلزم مزيدًا من استخدام الاتصال وبالتالي تفريغ البطارية. يتناسب استهلاك الطاقة مع إظهار الصور طردًا مع حجمها وعددها. يُمكن العودة لتقرير من قتل بطاريتي من ستانفورد. يُحبَّذ التخلص من الصور إن أمكن ذلك. ومن الإرشادات المقترحة: يجب التفكير في تصميمات تتجنب الصور تمامًا، أو تستخدمها باعتدال. يُمكن أن يكون استخدام النص لوحده رائعًا (راجع الرابط). يجب البدء أولًا بدراسة سلوك زوار الموقع؛ وماذا يُريدون منه؛ وفيما إذا كانت الصور مُساعدةً لهم أم لا. شاع سابقًا حفظ العناوين والنصوص الهامة مثل صور؛ ولكن لا يتجاوب هذا الأسلوب مع تغييرات حجم إطارات العرض؛ كما أنه يزيد من حجم الصفحة ومن زمن الاستجابة. لن تصل محركات البحث ولا قارئات الشاشة ولا التقنيات المساعدة الأخرى إلى النصوص المحفوظة مثل صور. يجب استخدام النصوص "الحقيقية" ما أمكن ذلك، كما يمكن أن توفّر خطوط الويب وأنماط CSS مظهرًا جميلًا للنصوص. يُحبذ استخدام أنماط CSS بدلًا من الصور للتدرجات والظلال والزوايا الدائرية ونقشات الخلفية (وهي جميعًا مدعومة من قبل كل المتصفحات الحديثة). ومع ذلك، يجب الانتباه إلى أنه وعلى الرغم من أن استخدام CSS أفضل من استخدام الصور؛ إلا أن له كلفةٌ إضافيةٌ للمعالجة والإظهار لاسيما على الجوال. من النادر أن تعمل صور الخلفية جيدًا على الجوال. يُمكن استخدام استعلامات الوسائط لتجنُّب وضع صور الخلفية على إطارات العرض الصغيرة. يجب تجنب وضع الصور في شاشة البداية. يجب استخدام أنماط CSS للتحريك (راجع مقالة أساسيات التحريك). يجب معرفة الخطوط الرسومية اللازمة واستخدام الرموز unicode والأيقونات عوضًا عن الصور، واستخدام خطوط الويب Web Fonts إذا كان ذلك ضروريًا. يُفضَّل استخدام الأيقونات المتوفرة في الخطوط لأنها رسومات متجهة يُمكن تحجيمها بدون حدود، كما يُمكن تنزيل مجموعة من الأيقونات في نوع خطٍ واحد. يُمكن استخدام عنصر الحاوية <canvas> لإنشاء الصور في سكريبت جافا باستخدام الخطوط والمنحنيات والنصوص وصور أخرى. لا تقلّل الصور من النوع SVG أو من نوع روابط البيانات (يُمكن وضع كلا النوعين سطريًا inline في CSS) من حجم الصفحة، إلا أنها تُخفّض من زمن الاستجابة عن طريق تخفيض عدد طلبات الملف المصدر. يتوفر للصور SVG دعمٌ واسع على الجوالات وعلى متصفحات الحواسيب المكتبية؛ كما يُمكن لأدوات التحسين تخفيض حجم الرسومات SVG. وبالمثل، تُدعم بيانات الروابط جيدًا. يُفضّل استخدام العنصر <video> عوضًا عن الصور المتحركة GIFs. تصميم المحتوى ليعمل جيدا على مختلف حجوم إطارات العرض ينصح براين فلينج في تصميم وتطوير الجوال Mobile Design and Development بما يلي: لا يلجأ المصممون المتميزون إلى عمليات التحسين لملاءمة الجوال، بل يفكرون على نحوٍ متجاوب في إنشاء مواقعٍ تعمل على مختلف الأجهزة. تٌعدّ هيكلية النص ومحتويات الصفحة الأخرى أمرًا أساسيًا لتحقيق النجاح على مختلف الأجهزة. يستخدم الكثير من الأشخاص الذين يدخلون على الويب والذي يتجاوز عددهم المليار مستخدم جوالاتٍ منخفضة التكلفة مع إطارات عرض صغيرة، وبذلك يُمكن أن تكون القراءة على شاشة منخفضة الدقة مقاس 3.5 بوصة أو 4 بوصة عملًا شاقًا. يُبين الشكل التالي صورةً لهذين المقاسين معًا: يبدو النص على الشاشة الكبيرة صغيرًا إلا أنه مقروء؛ بينما يكون على الشاشة الصغيرة غير قابلًا للقراءة رغم ظهور تخطيط الصفحة صحيحًا، كما يبدو العرض ضبابيًا عند التكبير وتفقد الألوان من بريقها فلا يعود اللون الأبيض أبيضًا مثلًا، ويصبح المحتوى غير واضح. تصميم المحتوى للجوال يجب وضع المحتوى على أنه أولوية مع مراحل التخطيط والتصميم الفني، أي أنه يجب التصميم مع نصوص وصور حقيقية وليس مع محتوًى وهمي. يقول جيفري زيلدمان Jeffrey Zeldman: يجب وضع المحتوى الأكثر أهمية في الأعلى، حيث يميل المستخدمون إلى قراءة صفحات الويب على شكل الحرف F؛ أي يهتمون أولًا بالجزء الأعلى ثم يمسحون المنتصف. يزور المستخدمون الموقع لتحقيق هدفٍ ما؛ لذلك يجب دومًا دراسة ما يحتاجون إليه لتحقيق هذا الهدف والتخلص من كل شيءٍ آخر إضافي. يجب التدقيق في الزخارف المرئية والنصية والمحتوى القديم والروابط الزائدة وما لا داعٍ له. يجب توخي الحذر عند استخدام أيقونات المشاركة الاجتماعية، حيث يُمكن أن تُسبب فوضى في التخطيطات، كما يُمكن لشيفرتها أن تُبطئ تحميل الصفحة. يجب تصميم التخطيطات المتجاوبة مع المحتوى وغير المخصصة لحجوم أجهزةٍ ثابتة. اختبار المحتوى لنتذكر أنه لتحقيق النجاح: مهما فعلنا، فلا بُدّ من الاختبار. يجب التحقق من إمكانية القراءة على إطارات العرض الأصغر باستخدام أدوات المطور Chrome DevTools وأدوات المحاكاة الأخرى. يجب اختبار المحتوى في ظل ظروف حيز النطاق التراسلي المنخفض والتأخير العالي؛ لذلك يجب تجربة المحتوى في مجموعةٍ متنوعة من سيناريوهات الاتصال. يجب محاولة قراءة المحتوى والتفاعل معه على جوالٍ رخيص. يجب الطلب من الأصدقاء والزملاء تجربة التطبيق أو الموقع. يجب بناء مختبر لاختبار الجهاز. يوفّر GitHub repo الخاص بمختبر Mini Mobile Device من Google الإرشادات حول كيفية إنشاء مختبرٍ مُخصص. من المفيد استخدام OpenSTF، وهو تطبيق ويب بسيط لاختبار مواقع الويب على العديد من أجهزة Android. يُبين الشكل التالي استخدام OpenSTF: يتزايد استخدام الأجهزة المحمولة لتصفح المحتوى والحصول على المعلومات، وليس فقط أجهزةً للاتصال والألعاب والوسائط المتعددة، مما يجعل من الأهمية بمكان تصميم المحتوى ليعمل على طيفٍ واسعٍ من إطارات العرض، وإعطاء المحتوى الأولوية عند تصميم تخطيط الصفحة والواجهات والتفاعل مع المستخدم بحيث يظهر المحتوى صحيحًا على مختلف الأجهزة. فهم كلفة البيانات يتزايد حجم صفحات الويب على نحوٍ مُطّرد. فوفقًا لـ أرشيف HTTP يبلغ متوسط حجم الصفحة لـ أهم مليون موقع أكثر من 2 ميغا بايت. يتجنب المستخدمون المواقع أو التطبيقات التي يعتقدون أنها بطيئة أو باهظة الثمن، لذا من الضروري فهم تكلفة تحميل الصفحة ومكونات التطبيق. يُمكن أن يكون تخفيض حجم الصفحة مربحًا أيضًا. اكتشف كريس زاكرياس من YouTube أنه عند تخفيض حجم صفحة المشاهدة من 1.2 ميغا بايت إلى 250 كيلو بايت: وبعبارةٍ أخرى: يُمكن أن يؤدي تخفيض حجم الصفحة إلى فتح أسواقٍ جديدة بالكامل. حساب حجم الصفحة يتوفر العديد من الأدوات لحساب حجم الصفحة. تعرض لوحة المطور Chrome DevTools Network الحجم الإجمالي بالبايت لجميع الموارد، ويُمكن استخدامها للتأكد من حجم كل نوع من الموارد. يُمكن أيضًا التحقق من العناصر المُستعادة من ذاكرة التخزين المؤقت cache للمتصفح. يوفر المتصفح Firefox والمتصفحات الأخرى أدواتٍ مماثلةً أيضًا. يوفر WebPagetest إمكانية اختبار تحميل الصفحة للمرة الأولى والتحميلات اللاحقة لها. يُمكن أتمتة الاختبار باستخدام سكريبت (لتسجيل الدخول إلى موقعٍ ما مثلًا) أو باستخدام واجهات برمجة التطبيقات RESTful APIs الخاصة بهم. يوضح المثال التالي المُنزّل من developers.google.com/web بأن التخزين المؤقت كان ناجحًا وأن عمليات تحميل الصفحة اللاحقة لا تتطلب مواردًا إضافية. يعرض WebPagetest الحجم وتفصيلات الطلب حسب نوع MIME أيضًا. حساب كلفة الصفحة ينظر كثيرٌ من المستخدمين إلى الكلفة المالية لتصفح الموقع؛ وليس إلى عدد البايتات اللازمة؛ أو إلى أداء الموقع السريع. يسمح الموقع "ما هي كلفة موقعي" What Does My Site Cost? بتقدير التكلفة المالية الفعلية لتحميل موقعٍ ما. يُبين المخطط التكراري التالي كلفة تحميل الموقع amazon.com (باستخدام طريقة الدفع المُسبق للبيانات): يجب الانتباه إلى أن ذلك لا يأخذ بالحسبان قدرة الشخص على تحمُّل التكاليف موازنةً بدخله. يُمكن أيضًا الرجوع إلى الموقع blog.jana.com لمعاينة كلفة البيانات. table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } البلد كلفة 500MB الحد الأدنى للأجر الساعي عدد ساعات العمل لدفع كلفة 500MB الهند $3.38 $0.20 17 ساعة أندونيسيا $2.39 $0.43 6 ساعة البرازيل $13.77 $1.04 13 ساعة لا يُشكّل حجم الصفحة مشكلةً فقط للأسواق الناشئة؛ حيث يجب أيضًا ملاحظة اشتراك الكثير من الأشخاص في معظم البلدان بخطط الدفع محدودة البيانات وبأنهم يتجنبون بالطبع الصفحات الثقيلة والمُكلفة؛ كما أن خطط البيانات "غير المحدودة" للجوالات وشبكات wifi يكون لها في النهاية حدٌ معين للبيانات تتوقف بعده الخدمة أو يُحدّ منها. يُنصح بالتمتُّع بالشفافية والإعلام عن حجم البيانات التي يستهلكها الموقع. وبالنتيجة، يؤثر حجم الصفحة على كلٍ من الأداء والتكلفة المالية. ترجمة -وبتصرف- للمقالة Multi-Device Content للمؤلف: Sam Dutton. اقرأ أيضًا الصور في تصميم صفحات الويب المتجاوب نماذج تصميم الويب المتجاوب تحريك واجهات العرض أثناء التنقل في موقع الويب
  6. يُمكن في تصميم الويب المتجاوب تغيير المحتوى إضافًة إلى تغيير التخطيط وفقًا لمواصفات الجهاز. يمكن عرض الصور عالية الدقة على نحوٍ ممتاز على الشاشات عالية الدقة (2x)؛ كما يُمكن أن تظهر صورةٌ عرضها 50% جيدًا على متصفحٍ عرضه 800px، بينما ستستهلك كثيرًا من المساحة على هاتفٍ ضيق، كما أن تحجيمها لملاءمة الشاشات الصغيرة سيتطلب نفس تكلفة حيّز النطاق التراسلي bandwidth. الإدارة الفنية تتطلب مسائلٌ أخرى إجراء تغييرات جذرية على الصور، مثل تغيير نسب الصورة، أو القص، أو حتى استبدال كامل الصورة، وتُدعى هذه التغييرات بالإدارة الفنية ويُمكن العودة إلى responsiveimages.org لمزيدٍ من الأمثلة. الصور المتجاوبة ربما لا يعلم الأشخاص أن الصور تُمثّل أكثر من 60٪ وسطيًا من البايتات اللازمة لتحميل صفحة ويب. سنعرض فيما يلي كيفية التعامل مع الصور الموجودة على الويب الحديث بحيث تبدو الصور رائعةً وتُحمّل على أي جهازٍ بسرعة. كما نشرح مجموعةً من المهارات والتقنيات لمكاملة الصور المتجاوبة ضمن تسلسل عمليات تطوير صفحات الويب؛ بحيث تتكيف هذه الصور وتُلائم حجوم إطارات العرض المختلفة وسيناريوهات الاستخدام المتعددة. الصور في لغات الترميز markup يُعدّ العنصر img من العناصر الأساسية القوية فهو ينزِّل المحتوى ويفك ترميزه ويعرضه، كما تدعم المتصفحات الحديثة طيفًا واسعًا من تنسيقات الصور. لا يختلف تضمين الصور في الأجهزة المختلفة عن تضمينها في حاسوبٍ مكتبي مع ضرورة إجراء بعض التعديلات الطفيفة أحيانًا لتحقيق تجربة استخدامٍ جيدة. يجب عمومًا الانتباه لما يلي: استخدام الحجوم النسبية للصور لمنع امتدادها خارج حاويتها عن طريق الخطأ. استخدام العنصر picture لتحديد صورٍ مختلفة تظهر واحدةٌ منها وفق مواصفات جهاز العرض (الإدارة الفنية). استخدام السمة "مجموعة المصادر" srcset والسمة x في العنصر img لإرشاد المتصفح لاختيار الصورة الأنسب من بين كثافاتٍ مختلفة. استخدام الصور السطرية inline في حال احتواء الصفحة على صورةٍ أو صورتين لتخفيض عدد طلبات تحميل ملف الصورة. استخدام الحجم النسبي للصور لا بُدّ من استخدام الوحدات النسبية عند تحديد عرض الصورة كي لا تمتد خارج إطار العرض عن طريق الخطأ؛ فعند تحديد العرض إلى width: 50% مثلًا، سيكون عرض الصورة دومًا 50% من عرض حاويتها وليس 50% من عرض إطار العرض أو من عرض الصورة نفسها. يُمكن أيضًا أن نحتاج لاستخدام max-width: 100% وذلك لسماح أنماط CSS للمحتوى بالامتداد خارج حاويته. img, embed, object, video { max-width: 100%; } يجب توفير وصفٍ مفيدٍ للصورة باستخدام السمة alt في عناصر img؛ مما يُساعد قارئات الشاشة والتقنيات المساعدة الأخرى من الوصول للموقع بسهولةٍ أكبر. تحسين عنصر الصور img باستخدام السمة srcset للأجهزة عالية الكثافة تُحسّن السمة srcset من أداء العنصر img، حيث توفّر مجموعة ملفات صور متعددة للاختيار منها وفقًا لمواصفات الجهاز. على غرار الدالة image-set الأساسية في أنماط CSS، تسمح السمة srcset للمتصفح باختيار الصورة الأنسب وفقًا لمواصفات الجهاز، مثل استخدام صورة 2x على شاشة عرض 2x، أو ربما لاحقًا، صورة 1x على شاشة 2x عند محدودية النطاق الترددي للشبكة المستخدمة. <img src="photo.png" srcset="photo@2x.png 2x" ...> تستخدم المتصفحات التي لا تدعم srcset ملف الصورة الافتراضي المُحدّد بالسمة src، لذا فمن المهم دومًا تضمين صورة 1x يُمكن عرضها على أي جهازٍ بغض النظر عن إمكاناته؛ أما في حال دعم السمة srcset، فتُحلّل قائمة الصور/الشروط المفصولة بفواصل قبل أي طلب، ومن ثم تُنزّل وتُعرض الصورة الأكثر ملاءمة. يُمكن للشروط الموضوعة على الصور أن تحوي أي شيءٍ، مثل كثافة البكسلات والعرض والطول، إلا أن الكثافة فقط هي المدعومة حاليًا. يجب دومًا توفير صورة 2x لتحقيق التوازن بين السلوك الحالي والميزات المستقبلية لاحقًا. الإدارة الفنية للصور المتجاوبة باستخدام العنصر picture يُمكن تغيير الصور وفقًا لمواصفات الجهاز والمعروفة أيضًا باسم الإدارة الفنية، باستخدام العنصر picture؛ الذي يوفر إمكانية التصريح لمجموعةٍ من الصور المختلفة للاختيار منها وفقًا لمواصفات الجهاز، مثل الحجم والدقة والاتجاه وغيرها. يتزايد دعم العنصر picture في المتصفحات، بالرغم من عدم توفره في جميعها بعد؛ ولكن يُنصح باستخدام هذا العنصر لتوافقه الكبير مع الإصدارات السابقة واحتمال استخدام المزايا التي توفّرها تقنيات الصور المتجاوبة المتوفرة في المشروع من النمط "نقص الدعم" Picturefill polyfill. يُستخدم العنصر picture عند توفُّر الصورة بكثافاتٍ مختلفة؛ أو عندما يتطلب التصميم المتجاوب عرض صورٍ مختلفة على بعض أنواع الشاشات. وعلى غرار عنصر الفيديو video، يُمكن تضمين عدة عناصر "مصدر" source لتحديد ملفات صورٍ مختلفة اعتمادًا على استعلامات الوسائط أو تنسيق الصورة. <picture> <source media="(min-width: 800px)" srcset="head.jpg, head-2x.jpg 2x"> <source media="(min-width: 450px)" srcset="head-small.jpg, head-small-2x.jpg 2x"> <img src="head-fb.jpg" srcset="head-fb-2x.jpg 2x" alt="a head carved out of wood"> </picture> يُمكن معاينة مثال github.io. يستخدم المتصفح في المثال السابق الصورة head.jpg، أو الصورة head-2x.jpg (حسب دقة الجهاز) إذا كان عرضه 800px على الأقل؛ أما إذا كان عرض المتصفح بين 450px و 800px، فيستخدم head-small.jpg، أو head-small- 2x.jpg (حسب دقة الجهاز)؛ بينما تُعرض الصورة المُحدّدة في العنصر img (والواجب تضمينه دائمًا) على الشاشات ذات العرض الأصغر من 450px، أو في حال عدم دعم العنصر picture. الصور ذات الحجم النسبي يُمكن أن يكون صعبًا تحديد كثافة الصور في حال عدم معرفة الحجم النهائي للصورة، خصوصًا مع الصور المُنسابة والتي يُمكن أن تمتد لتتناسب مع عرض المتصفح. يُمكن عوضًا عن تقديم حجوم وكثافات ثابتة، تحديد حجم كل صورة بضبط سمة العرض إضافًة لحجم عنصر الصورة؛ مما يسمح للمتصفح حساب كثافة البكسلات تلقائيًا واختيار الصورة الأنسب للتنزيل. <img src="lighthouse-200.jpg" sizes="50vw" srcset="lighthouse-100.jpg 100w, lighthouse-200.jpg 200w, lighthouse-400.jpg 400w, lighthouse-800.jpg 800w, lighthouse-1000.jpg 1000w, lighthouse-1400.jpg 1400w, lighthouse-1800.jpg 1800w" alt="a lighthouse"> يُمكن معاينة المثال يعرض المثال السابق صورةً لها نصف عرض إطار العرض sizes="50vw"‎، ويختار المتصفح الصورة المناسبة اعتمادًا على عرض المتصفح وعلى نسبة البكسلات في الجهاز وذلك بغض النظر عن حجم نافذة المتصفح. يُبين الجدول التالي بعض الأمثلة عن الصور التي سيختارها المتصفح: table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } عرض المتصفح نسبة البكسلات للجهاز الصورة المستخدمة الدقة الفعلية 1x 200.jpg 1 400px 2x 400.jpg 2 400px 2.5x 400.jpg 2 320px 2.67x 800.jpg 2 600px 3.125x 1000.jpg 3 640px 1.45x 800.png 1 1100px الصور المتجاوبة والنقاط الحدية يُمكن تغيير حجم الصورة اعتمادًا على النقاط الحدّية المُحدّدة في تخطيط الموقع. مثلًا: يُمكن تفضيل امتداد صورة على كامل عرض إطار العرض في شاشة صغيرة، مع وضعها في جزء صغير من شاشة كبيرة. <img src="400.png" sizes="(min-width: 600px) 25vw, (min-width: 500px) 50vw, 100vw" srcset="100.png 100w, 200.png 200w, 400.png 400w, 800.png 800w, 1600.png 1600w, 2000.png 2000w" alt="an example image"> يُمكن معاينة المثال تستخدم سمة الحجوم sizes في المثال السابق عدة استعلامات وسائط لتحديد حجم الصورة. يُصبح حجم الصورة 25% من عرض إطار العرض عندما يتجاوز عرض المتصفح 600px؛ بينما يُصبح 50% من عرض إطار العرض عندما يكون عرض المتصفح بين 500px و 600px؛ أما عندما يكون عرض المتصفح أقل من 500px، فتمتد الصورة على كامل عرض المتصفح. توسيع صور المنتجات يحتاج مستخدمو مواقع التجارة الإلكترونية لمعاينة مشاهد مُقرّبة من المنتجات بدقة عالية بهدف تفحص تفاصيل المنتج، كما تؤكد الدراسات الإحباط الكبير لهؤلاء المستخدمين إذا لم يتمكنوا من ذلك. يوفر موقع J. Crew مثالًا جيدًا للصور القابلة للنقر والتوسيع حيث يظهر على كل صورة شريط صغير (يختفي عند النقر) يُعلّم المستخدم بإمكانية النقر على الصورة لتكبيرها ومعاينة تفاصيلها. تقنيات أخرى مع الصور الصور المضغوطة توفر تقنيات الصور المضغوطة compressive image technique صورًا مضغوطة 2x تُناسب جميع الأجهزة مهما كانت إمكاناتها؛ حيث ينخفض حجم الصور كثيرًا (حسب نوع الصورة ودرجة الضغط) مع عدم ملاحظة أي تغيير في جودة الصورة. ويُمكن معاينة مثال compressive.html يجب توخي الحذر عند استخدام التقانات الضاغطة، حيث تتطلب ذاكرةً أكبر ومعالجةً أكثر لفك الضغط. يُعدّ تغيير حجم الصور الكبيرة لملاءمة الشاشات الصغيرة أمرًا مُكلفًا ويُمكن أن يكون مرهقًا خصوصًا للأجهزة قليلة الإمكانات ذات الذاكرة الصغيرة والمعالجة المحدودة. استبدال الصور باستخدام JavaScript يُمكن استخدام سكريبت جافا لفحص قدرات الجهاز ومن ثم إجراء الأنسب؛ حيث يُمكن مثًلا معرفة نسبة بكسلات الجهاز باستخدام window.devicePixelRatio؛ كما يُمكن معرفة طول الشاشة وعرضها؛ إضافًة لإمكانية فحص ميزات الاتصال الشبكي باستخدام navigator.connection أو إجراء طلبٍ مزيف. وعند الحصول على جميع هذه المعلومات، ستُحدّد الصورة المناسبة للتحميل. يُعدّ تأخير تحميل الصورة حتى انتهاء عمليات الفحص والتحقق أحد سلبيات استخدام JavaScript؛ مما يعني أن تحميل الصور لن يبدأ إلا بعد تشغيل حدث تحميل الصفحة pageload. علاوًة على ذلك، يُمكن أن يُنزِّل المتصفح كلًا من الصور 1x و 2x مما يؤدي لزيادة حجم الصفحة. الصور السطرية- الصور النقطية والصور المتجهة تُنشأ الصور وتُخزّن باستخدام طريقتين مختلفتين تمامًا مما ينعكس على طريقة نشر الصور على نحوٍ متجاوب. الصور النقطية: مثل الصور الفوتوغرافية وغيرها، والتي تُمثّل بشبكةٍ من نقاط الألوان (البكسلات). تُنتِج الكاميرات والماسحات الضوئية الصور النقطية عادًة، كما يُمكن إنتاجها باستخدام عناصر الحاويات canavas في HTML. تُستخدم التنسيقات، مثل PNG و JPEG و WebP لتخزين هذا النوع من الصور. الصور المتجهة: تُعرّف هذه الصور باستخدام مجموعة من المنحنيات والخطوط والأشكال وألوان التعبئة والتدرجات اللونية، مثل الشعارات logo والرسومات الخطية. يُمكن إنشاء الصور المتجهة باستخدام برامجٍ متخصصة، مثل Adobe Illustrator أو Inkscape، أو استخدام لغة ترميزٍ معينة، مثل لغة الرسومات المتجهة القابلة للتحجيم Scalable Vector Graphics. الرسومات المتجهة SVG القابلة للتحجيم .side-by-side { display: inline-block; margin: 0 20px 0 0; width: 45%; } span#data_uri { background: url(data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%0D%0A%3C%21--%20Generator%3A%20Adobe%20Illustrator%2016.0.0%2C%20SVG%20Export%20Plug-In%20.%20SVG%20Version%3A%206.00%20Build%200%29%20%20--%3E%0D%0A%3C%21DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%0D%0A%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%0D%0A%09%20width%3D%22396.74px%22%20height%3D%22560px%22%20viewBox%3D%22281.63%200%20396.74%20560%22%20enable-background%3D%22new%20281.63%200%20396.74%20560%22%20xml%3Aspace%3D%22preserve%22%0D%0A%09%3E%0D%0A%3Cg%3E%0D%0A%09%3Cg%3E%0D%0A%09%09%3Cg%3E%0D%0A%09%09%09%3Cpolygon%20fill%3D%22%23E44D26%22%20points%3D%22409.737%2C242.502%20414.276%2C293.362%20479.828%2C293.362%20480%2C293.362%20480%2C242.502%20479.828%2C242.502%20%09%09%09%0D%0A%09%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpath%20fill%3D%22%23E44D26%22%20d%3D%22M281.63%2C110.053l36.106%2C404.968L479.757%2C560l162.47-45.042l36.144-404.905H281.63z%20M611.283%2C489.176%0D%0A%09%09%09%09L480%2C525.572V474.03l-0.229%2C0.063L378.031%2C445.85l-6.958-77.985h22.98h26.879l3.536%2C39.612l55.315%2C14.937l0.046-0.013v-0.004%0D%0A%09%09%09%09L480%2C422.35v-79.32h-0.172H368.853l-12.207-136.871l-1.189-13.325h124.371H480v-49.668h162.17L611.283%2C489.176z%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20fill%3D%22%23F16529%22%20points%3D%22480%2C192.833%20604.247%2C192.833%20603.059%2C206.159%20600.796%2C231.338%20599.8%2C242.502%20599.64%2C242.502%20%0D%0A%09%09%09%09480%2C242.502%20480%2C293.362%20581.896%2C293.362%20595.28%2C293.362%20594.068%2C306.699%20582.396%2C437.458%20581.649%2C445.85%20480%2C474.021%20%0D%0A%09%09%09%09480%2C474.03%20480%2C525.572%20611.283%2C489.176%20642.17%2C143.166%20480%2C143.166%20%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20fill%3D%22%23F16529%22%20points%3D%22540.988%2C343.029%20480%2C343.029%20480%2C422.35%20535.224%2C407.445%20%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20fill%3D%22%23EBEBEB%22%20points%3D%22414.276%2C293.362%20409.737%2C242.502%20479.828%2C242.502%20479.828%2C242.38%20479.828%2C223.682%20%0D%0A%09%09%09%09479.828%2C192.833%20355.457%2C192.833%20356.646%2C206.159%20368.853%2C343.029%20479.828%2C343.029%20479.828%2C293.362%20%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20fill%3D%22%23EBEBEB%22%20points%3D%22479.828%2C474.069%20479.828%2C422.4%20479.782%2C422.413%20424.467%2C407.477%20420.931%2C367.864%20%0D%0A%09%09%09%09394.052%2C367.864%20371.072%2C367.864%20378.031%2C445.85%20479.771%2C474.094%20480%2C474.03%20480%2C474.021%20%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20points%3D%22343.784%2C50.229%20366.874%2C50.229%20366.874%2C75.517%20392.114%2C75.517%20392.114%2C0%20366.873%2C0%20366.873%2C24.938%20%0D%0A%09%09%09%09343.783%2C24.938%20343.783%2C0%20318.544%2C0%20318.544%2C75.517%20343.784%2C75.517%20%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20points%3D%22425.307%2C25.042%20425.307%2C75.517%20450.549%2C75.517%20450.549%2C25.042%20472.779%2C25.042%20472.779%2C0%20403.085%2C0%20%0D%0A%09%09%09%09403.085%2C25.042%20425.306%2C25.042%20%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20points%3D%22508.537%2C38.086%20525.914%2C64.937%20526.349%2C64.937%20543.714%2C38.086%20543.714%2C75.517%20568.851%2C75.517%20568.851%2C0%20%0D%0A%09%09%09%09542.522%2C0%20526.349%2C26.534%20510.159%2C0%20483.84%2C0%20483.84%2C75.517%20508.537%2C75.517%20%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20points%3D%22642.156%2C50.555%20606.66%2C50.555%20606.66%2C0%20581.412%2C0%20581.412%2C75.517%20642.156%2C75.517%20%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20fill%3D%22%23FFFFFF%22%20points%3D%22480%2C474.021%20581.649%2C445.85%20582.396%2C437.458%20594.068%2C306.699%20595.28%2C293.362%20581.896%2C293.362%20%0D%0A%09%09%09%09480%2C293.362%20479.828%2C293.362%20479.828%2C343.029%20480%2C343.029%20540.988%2C343.029%20535.224%2C407.445%20480%2C422.35%20479.828%2C422.396%20%0D%0A%09%09%09%09479.828%2C422.4%20479.828%2C474.069%20%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20fill%3D%22%23FFFFFF%22%20points%3D%22479.828%2C242.38%20479.828%2C242.502%20480%2C242.502%20599.64%2C242.502%20599.8%2C242.502%20600.796%2C231.338%20%0D%0A%09%09%09%09603.059%2C206.159%20604.247%2C192.833%20480%2C192.833%20479.828%2C192.833%20479.828%2C223.682%20%09%09%09%22%2F%3E%0D%0A%09%09%3C%2Fg%3E%0D%0A%09%3C%2Fg%3E%0D%0A%3C%2Fg%3E%0D%0A%3C%2Fsvg%3E%0D%0A) no-repeat; background-size: cover; height: 484px; } span#svg { background: url(data:image/svg+xml;utf8,) no-repeat; background-size: cover; height: 484px; } تُمكّن الرسومات SVG من تضمين رسوماتٍ متجهةٍ متجاوبة في صفحة ويب. تُعدّ إمكانية المستعرض عرض صورةٍ متجهة بأي حجم من أهم ميزات تنسيقات الملفات المتجهة موازنةً مع تنسيقات الملفات النقطية. كما تصف تنسيقات متجهات SVG هندسة الصورة (أي كيفية بنائها من الخطوط والمنحنيات والألوان وما إلى ذلك). على النقيض من ذلك، لا تحتوي التنسيقات النقطية إلا على معلوماتٍ حول نقاط الألوان، مما يتوجب على المتصفح تخمين كيفية ملء الفراغات (البكسلات الناقصة) عند عملية تحجيم الصورة. يُظهر الشكل التالي نسختين من نفس الصورة: صورة PNG على اليسار و SVG على اليمين. تبدو الصورة SVG رائعًة بأي حجم، بينما تزداد ضبابية الصورة PNG مع ازدياد عرض الشاشة. See the Pen Images SVG vs. PNG by Hsoub (@Hsoub) on CodePen. روابط البيانات توفّر روابط البيانات Data URIs طريقةً لتضمين ملف (ملف صورة مثلًا) سطريًا inline عن طريق ضبط سمة المصدر src للعنصر img باستخدام سلسلة نصية مُرمزة "Base64" ومع التنسيق التالي: <img src="data:image/svg+xml;base64,[data]"> مثلًا: تكون بداية الشيفرة للشعار HTML5 السابق على النحو التالي (طول الشيفرة الكلي أكثر من 5000 محرف): <img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiB BZG9iZSBJbGx1c3RyYXRvciAxNi4wLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW ..."> توفِّر مثل الأداة المتاحة jpillora.com/base64-encoder إمكانية تحويل أي ملفٍ ثنائي، مثل الصور إلى روابط بيانات؛ حيث يكفي سحب ملف الصورة وإفلاته على الأداة. وعلى غرار الرسومات SVG، تُدعم روابط البيانات جيدًا من قِبل متصفحات الأجهزة المحمولة والحواسيب المكتبية. النمط السطري في CSS يُمكن وضع روابط البيانات والرسومات SVG بنمطٍ سطري inline في CSS، حيث تَدعم متصفحات الأجهزة المحمولة والحواسيب المكتبية هذا النمط. يُبين الشكل التالي صورتين (تبدوان متطابقتين) موضوعتين مثل صور خلفية في CSS الأولى باستخدام روابط بيانات والثانية باستخدام SVG. <span class="side-by-side" id="data_uri"></span> <span class="side-by-side" id="svg"></span> <style> .side-by-side { display: inline-block; margin: 0 20px 0 0; width: 45%; } span#data_uri { background: url(data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%0D%0A%3C%21--%20Generator%3A%20Adobe%20Illustrator%2016.0.0%2C%20SVG%20Export%20Plug-In%20.%20SVG%20Version%3A%206.00%20Build%200%29%20%20--%3E%0D%0A%3C%21DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%0D%0A%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%0D%0A%09%20width%3D%22396.74px%22%20height%3D%22560px%22%20viewBox%3D%22281.63%200%20396.74%20560%22%20enable-background%3D%22new%20281.63%200%20396.74%20560%22%20xml%3Aspace%3D%22preserve%22%0D%0A%09%3E%0D%0A%3Cg%3E%0D%0A%09%3Cg%3E%0D%0A%09%09%3Cg%3E%0D%0A%09%09%09%3Cpolygon%20fill%3D%22%23E44D26%22%20points%3D%22409.737%2C242.502%20414.276%2C293.362%20479.828%2C293.362%20480%2C293.362%20480%2C242.502%20479.828%2C242.502%20%09%09%09%0D%0A%09%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpath%20fill%3D%22%23E44D26%22%20d%3D%22M281.63%2C110.053l36.106%2C404.968L479.757%2C560l162.47-45.042l36.144-404.905H281.63z%20M611.283%2C489.176%0D%0A%09%09%09%09L480%2C525.572V474.03l-0.229%2C0.063L378.031%2C445.85l-6.958-77.985h22.98h26.879l3.536%2C39.612l55.315%2C14.937l0.046-0.013v-0.004%0D%0A%09%09%09%09L480%2C422.35v-79.32h-0.172H368.853l-12.207-136.871l-1.189-13.325h124.371H480v-49.668h162.17L611.283%2C489.176z%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20fill%3D%22%23F16529%22%20points%3D%22480%2C192.833%20604.247%2C192.833%20603.059%2C206.159%20600.796%2C231.338%20599.8%2C242.502%20599.64%2C242.502%20%0D%0A%09%09%09%09480%2C242.502%20480%2C293.362%20581.896%2C293.362%20595.28%2C293.362%20594.068%2C306.699%20582.396%2C437.458%20581.649%2C445.85%20480%2C474.021%20%0D%0A%09%09%09%09480%2C474.03%20480%2C525.572%20611.283%2C489.176%20642.17%2C143.166%20480%2C143.166%20%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20fill%3D%22%23F16529%22%20points%3D%22540.988%2C343.029%20480%2C343.029%20480%2C422.35%20535.224%2C407.445%20%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20fill%3D%22%23EBEBEB%22%20points%3D%22414.276%2C293.362%20409.737%2C242.502%20479.828%2C242.502%20479.828%2C242.38%20479.828%2C223.682%20%0D%0A%09%09%09%09479.828%2C192.833%20355.457%2C192.833%20356.646%2C206.159%20368.853%2C343.029%20479.828%2C343.029%20479.828%2C293.362%20%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20fill%3D%22%23EBEBEB%22%20points%3D%22479.828%2C474.069%20479.828%2C422.4%20479.782%2C422.413%20424.467%2C407.477%20420.931%2C367.864%20%0D%0A%09%09%09%09394.052%2C367.864%20371.072%2C367.864%20378.031%2C445.85%20479.771%2C474.094%20480%2C474.03%20480%2C474.021%20%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20points%3D%22343.784%2C50.229%20366.874%2C50.229%20366.874%2C75.517%20392.114%2C75.517%20392.114%2C0%20366.873%2C0%20366.873%2C24.938%20%0D%0A%09%09%09%09343.783%2C24.938%20343.783%2C0%20318.544%2C0%20318.544%2C75.517%20343.784%2C75.517%20%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20points%3D%22425.307%2C25.042%20425.307%2C75.517%20450.549%2C75.517%20450.549%2C25.042%20472.779%2C25.042%20472.779%2C0%20403.085%2C0%20%0D%0A%09%09%09%09403.085%2C25.042%20425.306%2C25.042%20%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20points%3D%22508.537%2C38.086%20525.914%2C64.937%20526.349%2C64.937%20543.714%2C38.086%20543.714%2C75.517%20568.851%2C75.517%20568.851%2C0%20%0D%0A%09%09%09%09542.522%2C0%20526.349%2C26.534%20510.159%2C0%20483.84%2C0%20483.84%2C75.517%20508.537%2C75.517%20%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20points%3D%22642.156%2C50.555%20606.66%2C50.555%20606.66%2C0%20581.412%2C0%20581.412%2C75.517%20642.156%2C75.517%20%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20fill%3D%22%23FFFFFF%22%20points%3D%22480%2C474.021%20581.649%2C445.85%20582.396%2C437.458%20594.068%2C306.699%20595.28%2C293.362%20581.896%2C293.362%20%0D%0A%09%09%09%09480%2C293.362%20479.828%2C293.362%20479.828%2C343.029%20480%2C343.029%20540.988%2C343.029%20535.224%2C407.445%20480%2C422.35%20479.828%2C422.396%20%0D%0A%09%09%09%09479.828%2C422.4%20479.828%2C474.069%20%09%09%09%22%2F%3E%0D%0A%09%09%09%3Cpolygon%20fill%3D%22%23FFFFFF%22%20points%3D%22479.828%2C242.38%20479.828%2C242.502%20480%2C242.502%20599.64%2C242.502%20599.8%2C242.502%20600.796%2C231.338%20%0D%0A%09%09%09%09603.059%2C206.159%20604.247%2C192.833%20480%2C192.833%20479.828%2C192.833%20479.828%2C223.682%20%09%09%09%22%2F%3E%0D%0A%09%09%3C%2Fg%3E%0D%0A%09%3C%2Fg%3E%0D%0A%3C%2Fg%3E%0D%0A%3C%2Fsvg%3E%0D%0A) no-repeat; background-size: cover; height: 484px; } span#svg { background: url(data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' x='0px' y='0px' width='50%' height='560px' viewBox='281.63 0 396.74 560' enable-background='new 281.63 0 396.74 560' xml:space='preserve'><g><g><g><polygon fill='#E44D26' points='409.7,242.5 414.3,293.4 479.8,293.4 480,293.4 480,242.5 479.8,242.5'/><path fill='#E44D26' d='M281.63 110.053l36.106 404.968L479.757 560l162.47-45.042l36.144-404.905H281.63z M611.283 489.2 L480 525.572V474.03l-0.229 0.063L378.031 445.85l-6.958-77.985h22.98h26.879l3.536 39.612l55.315 14.937l0.046-0.013v-0.004 L480 422.35v-79.32h-0.172H368.853l-12.207-136.871l-1.189-13.325h124.371H480v-49.668h162.17L611.283 489.176z'/><polygon fill='#F16529' points='480,192.8 604.2,192.8 603.1,206.2 600.8,231.3 599.8,242.5 599.6,242.5 480,242.5 480,293.4 581.9,293.4 595.3,293.4 594.1,306.7 582.4,437.5 581.6,445.9 480,474 480,474 480,525.6 611.3,489.2 642.2,143.2 480,143.2'/><polygon fill='#F16529' points='541,343 480,343 480,422.4 535.2,407.4'/><polygon fill='#EBEBEB' points='414.3,293.4 409.7,242.5 479.8,242.5 479.8,242.4 479.8,223.7 479.8,192.8 355.5,192.8 356.6,206.2 368.9,343 479.8,343 479.8,293.4'/><polygon fill='#EBEBEB' points='479.8,474.1 479.8,422.4 479.8,422.4 424.5,407.5 420.9,367.9 394.1,367.9 371.1,367.9 378,445.9 479.8,474.1 480,474 480,474'/><polygon points='343.8,50.2 366.9,50.2 366.9,75.5 392.1,75.5 392.1,0 366.9,0 366.9,24.9 343.8,24.9 343.8,0 318.5,0 318.5,75.5 343.8,75.5'/><polygon points='425.3,25 425.3,75.5 450.5,75.5 450.5,25 472.8,25 472.8,0 403.1,0 403.1,25 425.3,25'/><polygon points='508.5,38.1 525.9,64.9 526.3,64.9 543.7,38.1 543.7,75.5 568.9,75.5 568.9,0 542.5,0 526.3,26.5 510.2,0 483.8,0 483.8,75.5 508.5,75.5'/><polygon points='642.2,50.6 606.7,50.6 606.7,0 581.4,0 581.4,75.5 642.2,75.5'/><polygon fill='#FFFFFF' points='480,474 581.6,445.9 582.4,437.5 594.1,306.7 595.3,293.4 581.9,293.4 480,293.4 479.8,293.4 479.8,343 480,343 541,343 535.2,407.4 480,422.4 479.8,422.4 479.8,422.4 479.8,474.1'/><polygon fill='#FFFFFF' points='479.8,242.4 479.8,242.5 480,242.5 599.6,242.5 599.8,242.5 600.8,231.3 603.1,206.2 604.2,192.8 480,192.8 479.8,192.8 479.8,223.7'/></g></g></g></svg>) no-repeat; background-size: cover; height: 484px; } </style> الناتج: الإيجابيات والسلبيات رغم طول الشيفرة للصور، لاسيما عند استخدام روابط البيانات، فإنها تؤدي للتقليل من طلبات HTTP؛ حيث يُمكن تحميل صفحةٍ تحتوي صورًا وأنماط CSS وسكريبت جافا مرةً واحدةً فقط. من أهم سلبيات هذه الطريقة: يُمكن أن يستغرق إظهار الصور مع روابط بيانات وقتًا أطول بكثير من الصور مع مصدر src خارجي على الهواتف المحمولة. يُمكن أن تزيد روابط البيانات من حجم صفحة HTML كثيرًا. يُمكن أن تزيد من تعقيد الشيفرة وتسلسل خطوات العمل في إنشاء الصفحة. زيادة حجم روابط البيانات بحوالي 30% عن حجم الملف الثنائي، وبالتالي لن تُخفف هذه الطريقة من حجم التنزيل الكلي. غير مدعومة أبدًا في IE6 و IE7، مع توفُّر دعمٍ جزئي في IE8. لا تعود مسألة تخفيض عدد الطلبات ملحة عند استخدام HTTP/2. نحتاج دومًا لاختبار ما يعمل على نحوٍ أفضل لتحقيق التجاوب الجيد. يُمكن استخدام أدوات المطور لقياس حجم الملف المُنزّل وعدد الطلبات ووقت الاستجابة الكلي. قد تكون روابط البيانات اختيارًا موفقًا للصور النقطية لصفحةٍ رئيسة تحتوي صورةً واحدةً أو اثنتين غير مستخدمتين في أماكن أخرى في الموقع؛ أما عند الحاجة لصورٍ سطرية متجهة، تكون رسومات SVG هي الخيار الأفضل. الصور في أنماط CSS تُعدّ خاصية الخلفية background في CSS أداةً مهمةً لإضافة صورٍ معقدة إلى العناصر؛ حيث أنها تُسهّل إضافة صورٍ متعددة وتكرارها وغير ذلك من الأمور؛ كما تزداد قوة هذه الخاصية عند دمجها مع استعلامات الوسائط، مما يتيح تحميل الصوره شرطيًا وفقًا لدقة الشاشة وحجم إطار العرض وغير ذلك من مواصفات الجهاز. يجب تغيير خاصية صورة الخلفية background-image في CSS لأجهزة العرض عالية الدقة، وذلك باستخدام استعلامات الوسائط مع الدقة الأدنى min-resolution و نسبة البكسلات الأدنى webkit-min-device-pixel-ratio-. يجب استخدام مجموعة المصادر srcset لتوفير صورٍ عالية الدقة إضافًة إلى الصورة 1x في الشيفرة. يجب التدقيق في التأثير على الأداء عند استخدام تقنيات استبدال الصور في سكريبت جافا، وعند توفير صورٍ مضغوطةٍ عالية الدقة لأجهزةٍ ذات دقة منخفضة. استخدام استعلامات الوسائط للتحميل الشرطي للصور أو للإدارة الفنية يُمكن استخدام استعلامات الوسائط لتغيير تخطيط الصفحة، كما يُمكن استخدامها أيضًا لتحميل الصور شرطيًا، أو لتوفير الإدارة الفنية وفقًا لعرض إطار العرض. يُظهر المثال التالي طلب تنزيل الملف small.png فقط ووضعه في محتوى الحاوية div على الشاشات الصغيرة؛ أما على الشاشات الأكبر، فيكون لخلفية جسم الصفحة صورة (background-image: url(body.png، وللحاوية صورةٌ أخرى (background-image: url(large.png. .example { height: 400px; background-image: url(small.png); background-repeat: no-repeat; background-size: contain; background-position-x: center; } @media (min-width: 500px) { body { background-image: url(body.png); } .example { background-image: url(large.png); } } يُمكن معاينة المثال السابق. استخدام image-set لتوفير صور عالية الدقة تُحسّن الدالة ()image-set من أداء خاصية الخلفية background عن طريق توفير مجموعةٍ متعدّدة من الصور وفقًا لمواصفات الجهاز المختلفة؛ مما يسمح للمتصفح باختيار أفضل صورة اعتمادًا على خصائص الجهاز، حيث يمكن مثلًا استخدام صورة 2x على جهاز 2x وصورة 1x على جهاز 2x عند محدودية حيز النطاق التراسلي للشبكة. background-image: image-set( url(icon1x.jpg) 1x, url(icon2x.jpg) 2x ); يقيس المتصفح الصورة المناسبة إضافًة إلى تنزيلها، حيث يفترض المتصفح أن حجم الصور 2x أكبر مرتين من الصور 1x، وبالتالي يُخفَّض حجم الصورة 2x بنسبة 2، بحيث تظهر الصورة بنفس الحجم على الصفحة. يجب توفير صورةٍ احتياطية لاستخدامها في حالة عدم توفر الدعم للدالة ()image-set، حيث ما زال دعم هذه الدالة جديدًا ومتوفرًا على كلٍ من Chrome و Safari فقط مع بادئة محرك المتصفح webkit-. ألقِ نظرةً على ما يلي على سبيل المثال: .sample { width: 128px; height: 128px; background-image: url(icon1x.png); background-image: -webkit-image-set( url(icon1x.png) 1x, url(icon2x.png) 2x ); background-image: image-set( url(icon1x.png) 1x, url(icon2x.png) 2x ); } يمكن معاينة المثال السابق. تطلب الشيفرة السابقة تحميل الصورة المناسبة على المتصفحات التي تدعم الدالة ()image-set؛ وإلا فتُستخدم الصورة 1x. وبهذا ستحصل المتصفحات التي لا تدعم الدالة على الصور 1x. استخدام استعلامات الوسائط لتوفير صور عالية الدقة أو الإدارة الفنية يُمكن لاستعلامات الوسائط إنشاء قواعدٍ بناءً على نسبة بكسلات الجهاز device pixel ratio، مما يُمكّن من توفير صورٍ مختلفة لشاشات 1x وشاشات 2x. @media (min-resolution: 2dppx), (-webkit-min-device-pixel-ratio: 2) { /* الأنماط عالية الكثافة والمصادر هنا */ } تدعم المتصفحات Chrome و Firefox و Opera معيار الدقة الأدنى (min-resolution: 2dppx)؛ بينما يتطلب كلٌ من متصفحي Safari و Android كتابة القيمة بدون الوحدة dppx. يجب الانتباه إلى حدوث تحميل هذه الأنماط فقط عند مطابقة الجهاز لاستعلام الوسائط، وبالتالي يجب تحديد هذه الأنماط من أجل الحالة الأساسية، وهذا يضمن عرض شيءٍ ما إذا كان المتصفح لا يدعم استعلامات الوسائط الخاصة بالدقة. .sample { width: 128px; height: 128px; background-image: url(icon1x.png); } @media (min-resolution: 2dppx), /* Standard syntax */ (-webkit-min-device-pixel-ratio: 2) /* Safari & Android Browser */ { .sample { background-size: contain; background-image: url(icon2x.png); } } يمكن معاينة المثال السابق. ويُمكن أيضًا استخدام خاصية العرض الأدنى min-width لإظهار صورٍ بديلة اعتمادًا على حجم إطار العرض؛ حيث تتمتع هذه التقنية بميزة عدم تنزيل الصورة في حال عدم تحقق استعلام الوسائط. على سبيل المثال: تُنزّل الصورة bg.png وتوضع في الجسم body، إذا كان عرض المتصفح أكبر أو يساوي 500px فقط: @media (min-width: 500px) { body { background-image: url(bg.png); } } استخدام رسومات SVG للأيقونات تُستخدم الرسومات المتجهة SVG لإضافة الأيقونات للصفحة عندما يكون ذلك مُمكنًا، أو المحارف unicode في بعض الحالات. استبدال الأيقونات البسيطة بـالمحارف unicode يدعم الكثير من الخطوط المحارف الرسومية unicode، والتي يُمكن استخدامها عوضًا عن الصور لا سيما وأنها على خلاف الصور تظهر جيدًا مهما كان حجمها. تتضمن المحارف الرسومية إضافًة إلى المحارف العادية، رموز الأسهم (←) والمعاملات الرياضية (√) والأشكال الهندسية (★) وصور التحكم (▶) والعلامات الموسيقية (♬) والأحرف اليونانية (Ω) وحتى قطع الشطرنج ( ♞). تُضمّن هذه المحارف بنفس طريقة تدوين الكائنات على النحو التالي: XXXX&#؛ حيث يُمثّل XXXX رقم محرف unicode. ألقِ نظرةً على المثال التالي: You're a super &#9733; والذي يُظهِر: You're a super ★ استبدال الأيقونات المعقدة برسومات SVG يُمكن استخدام رسومات SVG للأيقونات الأكثر تعقيدًا؛ نظرًا لأن هذه الرسومات خفيفة وسهلة الاستخدام عمومًا، كما يُمكن تصميمها باستخدام أنماط CSS. وتتمتع بالمزايا التالية موزانةً مع الصور النقطية: يُمكن تحجيم الرسومات المتجهة بلا حدود. يُمكن استخدام تأثيرات CSS مثل اللون والتظليل والشفافية والتحريك مباشرةً. يُمكن تضمين هذه الرسومات سطريًا inline. توفر دلالة واضحة. توفر إمكانية وصول أفضل مع استخدام السمات المناسبة. With SVG icons, you can either add icons using inline SVG, like this checkmark: <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32"> <path d="M27 4l-15 15-7-7-5 5 12 12 20-20z" fill="#000000"></path> </svg> or by using an image tag, like this credit card icon: <img src="credit.svg">. يُمكن معاينة المثال السابق. إرشادات استخدام الخطوط للأيقونات يشيع استخدام الخطوط للأيقونات لسهولة استخدامها، إلا أن لها بعض العيوب موزانةً مع أيقونات رسومات SVG: تُنشَأ باستخدام رسوميات مُتجهة، مما يُمكّن من تحجيمها بلا حدود؛ ولكن يُمكن أن تكون غير مصقولة، مما يُعطي أحيانًا أيقونات غير دقيقة كما هو متوقع منها أن تكون. لا توفِّر دعمًا كاملًا لأنماط CSS. يُمكن أن يكون تحقيق التوضع المثالي للبيكسل أمرًا صعبًا اعتمادًا على ارتفاع الخط وتباعد المحارف وغير ذلك. لا توفر الدلالة semantic، مما يجعل من الصعب استخدامها مع قارئات الشاشة أو التقنيات المساعدة الأخرى. يُمكن أن ينتج عن استخدام مجموعةٍ فرعيةٍ صغيرةٍ فقط منها حجم ملفٍ كبير ما لم يُحدّد نطاقها صحيحًا. يُبين الشكل التالي مثالًا لصفحة تستخدم الخطوط FontAwesome: With Font Awesome, you can either add icons by using a unicode entity, like this HTML5 logo (<span class="awesome"></span>) or by adding special classes to an <i> element like the CSS3 logo (<i class="fa fa-css3"></i>). يُمكن معاينة المثال السابق. تتوفر المئات من خطوط الأيقونات المجانية والمدفوعة بما في ذلك Font Awesome و Pictos و Glyphicons. يجب التأكد من التوازن بين طلبات HTTP الإضافية وحجم الملف حين الحاجة للأيقونات؛ حيث يُفضل استخدام صورةٍ، أو مجموعة صور مُضمّنة في صورةٍ واحدة image sprite في حال الحاجة لعددٍ قليل من الأيقونات. تحسين الصور لتحقيق الأداء الأمثل تُشكّل الصور غالبًا العدد الأكبر من البايتات المُنزّلة كما أنها تشغل قسمًا كبيرًا من المساحة المرئية على الصفحة. وبالنتيجة، يؤدي تحسين الصور إلى تخفيض عدد البايتات اللازم وبالتالي تحسين أداء الموقع؛ فكلما انخفض عدد البايتات الواجب تنزيلها، انخفض التنافس على حجز حيّز النطاق التراسلي، وزادت سرعة التحميل والعرض. يجب عدم اختيار تنسيق الصورة عشوائيًا، بل يجب فهم التنسيقات المختلفة المتاحة واستخدام التنسيق الأنسب. يجب تضمين أدوات تحسين الصور وضغطها في سير العمل على الموقع لتخفيض حجم الملفات. يُمكن تقليل عدد طلبات http عن طريق وضع الصور المُستخدمة على نحوٍ متكرر في حاوية صور image sprites. يُمكن تحسين زمن تحميل الصفحة الأولى والتخفيف من وزنها بتحميل الصور فقط عند الوصول إليها. اختيار التنسيق الصحيح يجب الانتباه لنوعين من الصور، وهما: الصور المتجهة و الصور النقطية. ونحتاج اختيار تنسيق الضغط المناسب بالنسبة للصور النقطية، مثل GIF و PNG و JPG. الصور النقطية: مثل الصور الفوتوغرافية وغيرها، والتي تُمثّل بشبكةٍ من نقاط الألوان (البكسلات). تُنتج الكاميرات والماسحات الضوئية الصور النقطية عادًة، كما يُمكن إنتاجها باستخدام عناصر الحاويات canavas في HTML؛ وكلما زاد حجم الصورة، زاد حجم الملف أيضًا. عندما يتغير حجم الصورة إلى حجمٍ أكبر من حجمها الأصلي، تُصبح الصور النقطية ضبابية، لأن المتصفح يحتاج إلى تخمين كيفية ملء البكسلات الناقصة. الصور المُتجهة: تُعرّف هذه الصور باستخدام مجموعةٍ من المنحنيات والخطوط والأشكال وألوان التعبئة والتدرجات اللونية، مثل الشعارات logo والرسومات الخطية، ويُمكن إنشاؤها باستخدام برامجٍ متخصصة، مثل Adobe Illustrator أو Inkscape؛ وتُحفَظ بتنسيقٍ متجه، مثل SVG. نظرًا لأن الصور المتجهة مبنية على عناصر أولية بسيطة، يُمكن تحجيمها دون أي خسارةٍ في الجودة، أو تغييرٍ في حجم الملف. من المهم الانتباه لمنشأ الصورة (نقطية أو متجهة) والمحتوى (الألوان، التحريك، النص،..) عند اختيار التنسيق المناسب. لا يوجد تنسيقٌ واحدٌ يُناسب جميع أنواع الصور؛ إذ لكل تنسيق نقاط قوة وضعف. من الإرشادات الأساسية لاختيار التنسيق المناسب: استخدام JPG للصور الفوتوغرافية. استخدام الرسوميات SVG للرسومات المتجهة والرسومات ذات الألوان الصلبة مثل الأيقونات والخطوط الفنية؛ وفي حال كان الرسم المتجه غير متاح، يُمكن تجربة التنسيقات WebP، أوPNG. استخدام PNG عوضًا عن GIF، لأنها تتيح المزيد من الألوان وتوفر نسب ضغط أفضل. استخدام عنصر الفيديو <video> للحصول على زمن تحريك أطول، والذي يوفر أيضًا نوعية صور أفضل، إضافًة لتحكُّم المستخدم في تشغيل العرض. تخفيض حجم الملف يُمكن تخفيض حجم ملف الصورة إلى حدٍ كبير عن طريق "المعالجة اللاحقة" للصور بعد حفظها. يتوفر العديد من الأدوات المتاحة لضغط الصور مع ضياع بعض البيانات أو بدون ضياع؛ ومنها متاحٌ على الويب؛ ومنها على هيئة برامج ذات واجهات رسومية أو سطور أوامر. من الأفضل تضمين عمليات تحسين الصور على نحوٍ مؤتمت ضمن سير العمل في بناء الموقع. تتوفر العديد من الأدوات ذات الأداء العالي والتي تضغط الصور دون ضياعٍ لبيانات الملفات JPG و PNG، وبدون أي تأثير على جودة الصورة. يُمكن استخدام الأدوات jpegtran أو jpegoptim (متوفر على لينكس Linux فقط؛ ويجب تشغيله مع خيار إزالة الكل strip-all--) للصور JPG؛ بينما يُمكن استخدام OptiPNG أو PNGOUT للصور PNG. استخدام تتابع الصور تسمح تقنية التتابع CSS spriting بدمج مجموعةٍ من الصور في "صورةٍ واحدة sprite sheet". يُمكن بعد ذلك انتقاء صورةٍ منها للعرض عن طريق تحديد الصورة الخلفية لعنصر sprite sheet مع تحديد الإزاحة المناسبة لعرض الجزء المطلوب. .sprite-sheet { background-image: url(sprite-sheet.png); width: 40px; height: 25px; } .google-logo { width: 125px; height: 45px; background-position: -190px -170px; } .gmail { background-position: -150px -210px; } .maps { height: 40px; background-position: -120px -165px; } يُمكن معاينة المثال السابق. يُخفّض التتابع من عدد التنزيلات المطلوبة للحصول على صور متعدّدة مع السماح بالتخزين المؤقت لها. استخدام التحميل الكسول يُمكن أن يؤدي استخدام التحميل الكسول إلى تسريعٍ كبير لتحميل الصفحات الطويلة، التي تتضمن العديد من الصور الموجودة أسفل الجزء المرئي من الصفحة، عن طريق تحميلها؛ إما عند الحاجة لعرضها؛ أو عند انتهاء تحميل المحتوى الأساسي وعرضه. يُمكن أن يؤدي استخدام التحميل الكسول إلى إنشاء تجارب تمرير لا نهائية إضافًة لتحسين الأداء. يجب توخي الحذر عند إنشاء صفحات تمرير لا نهائية، لأن المحتوى يُحمّل عندما يُصبح مرئيًا فقط مما يجعل محركات البحث غير قادرةٍ على رؤية هذا المحتوى إطلاقًا. علاوًة على ذلك، فإن المستخدمين الذين يبحثون عن المعلومات التي يتوقعون رؤيتها في التذييل لا يرونه (أي التذييل) أبدًا نظرًا تحميل المحتوى الجديد دائمًا. تجنب الصور نهائيا يُمكن في بعض الحالات أن تكون الصورة الأفضل ليست صورةً على الإطلاق. يجب استخدام الإمكانات الأصلية للمتصفح لتوفير الوظائف نفسها أو وظائف مشابهة. تنشئ المستعرضات اليوم عناصرًا مرئية كانت تتطلب صورًا سابقًا؛ مما يعني أن المتصفحات لم تعد بحاجةٍ إلى تنزيل ملفات صور منفصلة، وبالتالي تتجنب حجم الصور غير الملائم. يُمكن استخدام خطوط يونيكود unicode أو خطوط الأيقونات الخاصة لعرض الأيقونات. وضع النص في الشيفرة عوضا عن تضمينه في الصور يجب أن يكون النص نصًا وليس مُضمّنًا في الصور كلما كان ذلك مُمكنًا؛ حيث يؤدي استخدام الصور للعناوين الرئيسية أو وضع معلومات الاتصال، مثل أرقام الهواتف أو العناوين في الصور إلى منع المستخدمين من نسخ المعلومات ولصقها؛ كما أن ذلك يجعل المعلومات غير متاحة لبرامج قراءة الشاشة وغير متجاوبة. عوضًا عن ذلك، يُمكن وضع النص في الشيفرة واستخدام خطوط الويب المتاحة لتحقيق النمط المطلوب. استخدام أنماط CSS لاستبدال الصور يُمكن للمتصفحات الحديثة استخدام خصائص CSS لإنشاء أنماط كانت تتطلب صورًا سابقًا. يُمكن مثلًا إنشاء التدرجات اللونية المعقدة باستخدام خاصية الخلفية background؛ ويُمكن إنشاء الظلال باستخدام صندوق الظلال box-shadow؛ كما يُمكن إضافة الزوايا المستديرة باستخدام خاصية نصف قطر الحدود border-radius. <style> div#noImage { color: white; border-radius: 5px; box-shadow: 5px 5px 4px 0 rgba(9,130,154,0.2); background: linear-gradient(rgba(9, 130, 154, 1), rgba(9, 130, 154, 0.5)); } </style> يجب الانتباه إلى أن استخدام هذه التقنيات يتطلب عدة دورات للإظهار؛ مما يُعدّ أمرًا مرهقًا على الهواتف المحمولة. سيُفقِد الإفراط في الاستخدام أي فائدةٍ مكتسبة، إضافًة إلى إعاقة الأداء. ترجمة -وبتصرف- للمقالة Images للمؤلف: Pete LePage. اقرأ أيضًا أساسيات تصميم الويب المتجاوب ما هو الفرق بين التصميم المتجاوب (Responsive Web Design) والتصميم المتلائم (Adaptive Web Design)
  7. تتطور نماذج تصميم الويب المتجاوب بصورةٍ متسارعة، ولكن يعمل عددٌ قليلٌ منها فقط جيدًا على الحواسيب المكتبية وعلى الأجهزة المحمولة معًا. يُمكن تصنيف معظم التخطيطات المُستخدمة في صفحات الويب المتجاوب إلى خمس فئات: المُنساب عمومًا mostly fluid؛ وإفلات العمود column drop؛ والتخطيط المُزاح layout shifter؛ والتعديلات الطفيفة tiny tweaks؛ وخارج اللوحة off canvas. مع الإشارة إلى أنه يُمكن للصفحة استخدام أكثر من نموذج معًا، مثل استخدام "إفلات العمود" مع "خارج اللوحة". تُشكّل هذه الفئات، والتي عرّفها أولًا لوك روبلسكي Luke Wroblewski)، نقطة انطلاقٍ أساسية لأي صفحةٍ متجاوبة. كُتبت جميع الأمثلة التالية بلغةٍ ترميزية باستخدام الصندوق المرن flexbox بهدف التبسيط وسهولة الفهم، وذلك مع حاويةٍ رئيسة div تضم ثلاث أو خمس حاويات div ثانوية، وبدءًا من العرض الأصغر، ومن ثم أُضيفت نقاطٌ حدّية عند الضرورة. تدعم المتصفحات الحديثة نمط تخطيط الصندوق المرن إلا أنه ما زال يتطلب بعض التعديلات من قبل المصنعين وصولًا للدعم الأمثل له. النموذج المنساب عموما Mostly Fluid يتكون النموذج المُنساب عمومًا من شبكةٍ انسيابية بصورةٍ أساسية؛ حيث تُحافظ هذه الشبكة على حجمها على الشاشات المتوسطة والكبيرة مع ضبط الهوامش على الشاشات الأوسع؛ بينما تتسبب بإعادة تدفق المحتوى الرئيسي مع تكديس الأعمدة عموديًا على الشاشات الصغيرة. من الميزات الأساسية لهذا النموذج عدم الحاجة إلا لنقطةٍ حدّيةٍ واحدة بين الشاشات الصغيرة والشاشات الكبيرة كما يُبين المثال التالي: تُكدَّس كل حاوية div عموديًا في العرض الأصغر؛ وعندما يتجاوز عرض الشاشة 600px، تُحافظ الحاوية div الأولى على العرض width: 100%؛ بينما تظهر الحاويات الأربع div الثانوية مثل عمودين أسفل الحاوية الأولى. عندما يتجاوز عرض الشاشة 800px، يُصبح عرض الحاوية الأساسية div ثابتًا مع توسيطها على الشاشة. من المواقع التي تستخدم هذا النموذج: A List Apart. Media Queries. SimpleBits. .container { display: -webkit-flex; display: flex; -webkit-flex-flow: row wrap; flex-flow: row wrap; } .c1, .c2, .c3, .c4, .c5 { width: 100%; } @media (min-width: 600px) { .c2, .c3, .c4, .c5 { width: 50%; } } @media (min-width: 800px) { .c1 { width: 60%; } .c2 { width: 40%; } /*لا يعمل استخدام 33.33 دومًا بسبب التقريب*/ .c3, .c4 { width: 33%; } .c5 { width: 34%; } } @media (min-width: 800px) { .container { width: 800px; margin-left: auto; margin-right: auto; } } نموذج إفلات العمود Column drop يكدِّس هذا النموذج الأعمدة عموديًا، عندما يُصبح عرض النافذة ضيقًا في التخطيطات متعدّدة الأعمدة والمُمتدة عرضًا على كامل الشاشة. ويُمكن أن يؤدي هذا إلى تكديس جميع الأعمدة عموديًا؛ لذلك يعتمد اختيار النقاط الحدّية لهذا النموذج على المحتوى وعلى تفاصيل التصميم. يُبين المثال التالي استخدام هذا النموذج: وكما الحال في النموذج المُنساب عمومًا، يُكدّس المحتوى في العرض الأصغر؛ إلا أنه عندما يتجاوز عرض الشاشة 600px، تأخذ الحاوية الأولى والثانية العرض الكامل للشاشة؛ أما عند تجاوز 800px، تأخذ جميع الحاويات الثلاث كامل عرض الشاشة. تُحدّد خاصية الترتيب order في أنماط CSS ترتيب الحاويات. من المواقع التي تستخدم هذا النموذج: Modernizr. .container { display: -webkit-flex; display: flex; -webkit-flex-flow: row wrap; flex-flow: row wrap; } .c1, .c2, .c3 { width: 100%; } @media (min-width: 600px) { .c1 { width: 60%; -webkit-order: 2; order: 2; } .c2 { width: 40%; -webkit-order: 1; order: 1; } .c3 { width: 100%; -webkit-order: 3; order: 3; } } @media (min-width: 800px) { .c2 { width: 20%; } .c3 { width: 20%; } } نموذج التخطيط المزاح Layout shifter يُعدّ هذا النموذج أكثر النماذج استجابةً مع عدّة نقاطٍ حدّية تُحدّد حسب عرض الشاشة؛ حيث يكمن الفرق الجوهري في هذا النموذج بطريقة تحريك المحتوى عوضًا عن إعادة تدفق المحتوى وإفلات الأعمدة أسفل بعضها بعضًا. يتطلب هذا النموذج تحديد مجموعةٍ من النقاط الحدّية، مما يُصعّب عمليات التعديل اللاحقة؛ إذ قد تتطلب كل نقطةٍ حدّية إجراء تغييرات على العناصر وليس على تخطيط المحتوى العام فقط. يُبيّن المثال التالي استخدام هذا النموذج: حيث يُكدَّس المحتوى عموديًا في الشاشات الأصغر، إلا أنه يتغير جذريًا على الشاشات الأكبر؛ إذ تُوضع حاوية div على اليسار وتُكدَّس حاويتان على يمينها. من المواقع التي تستخدم هذا النموذج: Andersson-Wise Architects. .container { display: -webkit-flex; display: flex; -webkit-flex-flow: row wrap; flex-flow: row wrap; } .c1, .c2, .c3, .c4 { width: 100%; } @media (min-width: 600px) { .c1 { width: 25%; } .c4 { width: 75%; } } @media (min-width: 800px) { .container { width: 800px; margin-left: auto; margin-right: auto; } } نموذج التعديلات الطفيفة Tiny tweaks يُجري هذا النموذج بعض التعديلات الطفيفة على التخطيط، مثل تعديل حجم الخط، أو تغيير حجوم الصور، أو تحريك المحتوى بطرقٍ بسيطةٍ جدًا. يُناسب هذا النموذج تخطيطات العمود الواحد، مثل مواقع الصفحة الخطية الواحدة والمقالات ذات النص الكبير. يُبين المثال التالي استخدام هذا النموذج: عمليًا، وكما يوحي اسم هذا النموذج، لا يتغير الكثير مع تغير حجم الشاشة؛ فكلما زاد عرض الشاشة، كبُر حجم الخط وزادت مساحة الحشوة padding. من المواقع التي تستخدم هذا النموذج: Ginger Whale. Future Friendly. .c1 { padding: 10px; width: 100%; } @media (min-width: 500px) { .c1 { padding: 20px; font-size: 1.5em; } } @media (min-width: 800px) { .c1 { padding: 40px; font-size: 2em; } } نموذج خارج اللوحة Off canvas عوضًا عن تكديس المحتوى عموديًا، يضع هذا النموذج المحتوى الأقل استخدامًا، مثل قوائم التنقل أو قوائم التطبيق خارج الشاشة، ويظهر هذا المحتوى عندما يصبح حجم الشاشة كبيرًا بدرجةٍ كافية فقط. أما على الشاشات الأصغر، فيجب النقر لإظهار هذا المحتوى المخفي. يُبين المثال التالي استخدام هذا النموذج: عوضًا عن تكديس المحتوى عموديًا، يَستخدم هذا المثال سمة التحويل لإخفاء حاويتين بوضعهما خارج الشاشة: 'transform: translate(-250px, 0)' تُستخدم JavaScript لإظهار الحاويات عن طريق إضافة الصف class المُسمى open إلى العنصر لجعله مرئيًا. ومع اتساع عرض الشاشة، تُزال مواضع العناصر خارج الشاشة فتعود هذه العناصر لتظهر ضمن إطار العرض المرئي. بما أن Safari for iOS 6 و Android Browser لا يدعمان flex-flow: row nowrap من flexbox، استُخدم التوضُّع المُطلق في هذا المثال. من المواقع التي تستخدم هذا النموذج: HTML5Rocks Articles. Google Nexus. Facebook's Mobile Site. body { overflow-x: hidden; } .container { display: block; } .c1, .c3 { position: absolute; width: 250px; height: 100%; /* حيلة لتحسين الأداء على المتصفح كروم See: http://aerotwist.com/blog/on-translate3d-and-layer-creation-hacks/ #perfmatters */ -webkit-backface-visibility: hidden; backface-visibility: hidden; -webkit-transition: -webkit-transform 0.4s ease-out; transition: transform 0.4s ease-out; z-index: 1; } .c1 { /* حيلة لتحسين الأداء على المتصفحات القديمة من كروم Using translate3d as a trick to improve performance on older versions of Chrome See: http://aerotwist.com/blog/on-translate3d-and-layer-creation-hacks/ #perfmatters */ -webkit-transform: translate(-250px,0); transform: translate(-250px,0); } .c2 { width: 100%; position: absolute; } .c3 { left: 100%; } .c1.open { -webkit-transform: translate(0,0); transform: translate(0,0); } .c3.open { -webkit-transform: translate(-250px,0); transform: translate(-250px,0); } @media (min-width: 500px) { /* استخدام الصندوق المرن إذا كان عرض الشاشة أكبر من 500 بكسل */ .container { display: -webkit-flex; display: flex; -webkit-flex-flow: row nowrap; flex-flow: row nowrap; } .c1 { position: relative; -webkit-transition: none 0s ease-out; transition: none 0s ease-out; -webkit-transform: translate(0,0); transform: translate(0,0); } .c2 { position: static; } } @media (min-width: 800px) { body { overflow-x: auto; } .c3 { position: relative; left: auto; -webkit-transition: none 0s ease-out; transition: none 0s ease-out; -webkit-transform: translate(0,0); transform: translate(0,0); } } ترجمة -وبتصرف- للمقالة Responsive Web Design Patterns للمؤلف: Pete LePage. اقرأ أيضًا أساسيات تصميم الويب المتجاوب ما هو الفرق بين التصميم المتجاوب (Responsive Web Design) والتصميم المتلائم (Adaptive Web Design) الدليل الشامل لشرح النقاط الحدية لصفحات الويب المتجاوبة
  8. تعرض هذه المقالة أساسيات إنشاء صفحات ويب متجاوبة مع احتياجات المستخدمين وقدرات الجهاز الذي تُعرض عليه. يتزايد استخدام الأجهزة المحمولة لتصفُّح الويب كثيرًا يومًا بعد يوم، مما يتطلب استخدام طرق عرضٍ مناسبة لصفحات الويب على شاشات هذه الأجهزة المتميزة بصغر حجمها نسبيًا. يُلبّي تصميم الويب المتجاوب احتياجات المستخدمين ويتكيف مع قدرات أجهزتهم؛ وقد وضع إيثان ماركوت Ethan Marcotte أساسياته في مقالته في موقع alistapart؛ وهو موقعٌ يُعنى بقضايا تصميم الويب. يتغير تخطيط صفحة الويب في تصميم الويب المتجاوب وفق حجم الجهاز وقدراته؛ حيث يمكن مثلًا عرض محتوًى ما ضمن عمودٍ واحدٍ فقط على جهازٍ محمول؛ بينما يُعرض نفس المحتوى ضمن عمودين على جهاز لوحي أكبر. من المهم جدًا أن تتكيف صفحات الويب مع مختلف حجوم الشاشات، والتي تتغير بصورةٍ مستمرة وفق أنواع الأجهزة المختلفة، مثل الهواتف والأجهزة اللوحية والحواسيب ووحدات التحكم في الألعاب وأجهزة التلفاز والأجهزة القابلة للارتداء. علاوًة على ذلك، يُمكن أن تختلف طرق التفاعل مع الأجهزة، كأن تكون عن طريق اللمس في البعض منها مثلًا. وبالنتيجة، يجب أن يأخذ التصميم الحديث المتجاوب كل هذه الأمور في الحسبان لتحسين تجربة الاستخدام للجميع. إعداد إطار العرض يجب أن تتضمن الصفحات المُعدّة على نحوٍ مثالي لطيفٍ متنوعٍٍ من الأجهزة وسمًا وصفيًا meta لإطار العرض viewport؛ حيث يُحدّد هذا الوسم للمتصفح كيفية تحجيم الصفحة واختيار أبعادها. تعرض متصفحات الجوال الصفحة بعرض شاشة حاسوب مكتبي (حوالي 980 بكسل عادًة، كما يُمكن أن تختلف حسب الجهاز)، وذلك بهدف تقديم أفضل تجربة استخدام، ثم تحاول تحسين مظهر المحتوى عن طريق زيادة حجم الخطوط وتحجيم المحتوى ليُناسب أبعاد شاشة العرض، مما يجعل الخطوط تبدو للمستخدمين غير متناسبة مع حجم الشاشة. وبالتالي، سيُضطر المستخدمون للنقر المزدوج أو القرص للتكبير pinch-to-zoom، للتمكُّن من معاينة المحتوى والتفاعل معه براحة. <!DOCTYPE html> <html lang="en"> <head> … <meta name="viewport" content="width=device-width, initial-scale=1"> … </head> … يؤدي إسناد القيمة width=device-width في وسم إطار العرض viewport إلى توجيه الصفحة لإظهار المحتوى على كامل عرض الشاشة وذلك باستخدام وحدة البكسلات المُستقلة عن الجهاز device-independent pixels؛ وهي وحدة قياس طول تُحوّل إلى عددٍ من البكسلات الفيزيائية حسب كثافة البكسلات على الجهاز، فكلما ارتفعت الكثافة زادت البكسلات الفيزيائية الموافقة لبكسل مستقل، وهذا يسمح للصفحة بإظهار المحتوى بما يتناسب مع مختلف حجوم الشاشات، بدءًا من الهواتف الصغيرة المحمولة، وانتهاءً بشاشات الحواسيب المكتبية الكبيرة. يعرض المثال التالي إظهار صفحةٍ في جهاز دون استخدام الوسم الوصفي لإطار العرض. أما مع استخدام الوسم الوصفي لإطار العرض، فسيكون الإظهار: تُحافظ بعض المتصفحات على عرض الصفحة عند التدوير إلى الوضع الأفقي وعند تصغير أو تكبير الصفحة عوضًا عن إعادة التدفق لملء كامل الشاشة. يؤدي ضبط سمة الحجم الابتدائي initial-scale = 1 إلى توجيه المستعرضات لإنشاء علاقة 1:1 بين وحدات بكسل أنماط CSS ووحدات البكسل المستقلة عن الجهاز وذلك بغض النظر عن اتجاه الجهاز؛ مما يسمح للصفحة بالاستفادة من العرض الأفقي كاملًا. التأكد من إمكانية الوصول لإطار العرض تتحقق أداة التدقيق Lighthouse من وجود الوسم الوصفي لإطار العرض viewport؛ وفي حال عدم وجوده تُظهر التنبيه الموافق "لا تتوفر السمة الوصفية لإطار العرض مع تحديد العرض أو الحجم الابتدائي" Does not have a <meta name="viewport"> tag with width or initial-scale، وهذا يُساعد في التحقق من استخدام مستندات HTML لهذا الوسم على نحوٍ صحيح. يُمكن ضبط السمات التالية لإطار العرض، إضافًة إلى ضبط سمة الحجم الابتدائي initial-scale: الحجم الأدنى minimum-scale. الحجم الأقصى maximum-scale. الحجم القابل للتخصيص من قبل المستخدم user-scalable. لا نوصي بضبط هذه السمات، إذ قد يؤدي ذلك إلى تعطيل إمكانية تكبير أو تصغير إطار العرض مما يحدّ من إمكانيات الوصول. تحجيم المحتوى وفق إطار العرض اعتاد المستخدمون على التنقل عموديًا في صفحات الويب، ويؤدي إرغام المستخدم على التمرير أفقيًا أو التصغير لمعاينة الصفحة بأكملها إلى تجربة استخدام سيئة. يُمكن أحيانًا، عن طريق الخطأ، إنشاء محتوى صفحة على الجوال لا يُناسب إطار العرض المُحدّد وذلك على الرغم من استخدام وسم إطار العرض؛ حيث يُمكن مثلًا أن تتسبب صورةٌ بضرورة التمرير الأفقي إذ كان عرضها أكبر من عرض إطار العرض، وبالتالي يجب ضبط المحتوى ليُناسب عرض إطار العرض وبحيث لا يُضطر المستخدم إلى التمرير الأفقي. تتحقق أداة التدقيق Lighthouse من عدم تمدُّد المحتوى خارج إطار العرض؛ وفي حال حدوث ذلك، تُظهر التنبيه الموافق "لم يُضبط حجم المحتوى صحيحًا بما يُناسب إطار العرض" Content is not sized correctly for the viewport. الصور تتسبب الصور ذات الأبعاد الثابتة والتي تكون أكبر من إطار العرض بظهور أشرطة التمرير. ومن الطرق الشائعة لتجاوز هذه المشكلة، هي إعطاء جميع الصور عرضًا أقصى max-width بنسبة 100%؛ مما يؤدي إلى تقليص حجم الصورة لتُناسب المساحة إذا كان حجم إطار العرض أصغر من حجم الصورة. وفي جميع الأحوال، لن يزداد حجم الصورة أكبر من حجمها الطبيعي مع استخدام max-width وليس width بنسبة 100%. من المستحسن عمومًا إضافة ما يلي إلى ملف الأنماط CSS منعًا من ظهور أشرطة التمرير مع الصور العريضة: img { max-width: 100%; display: block; } إضافة أبعاد الصورة إلى العنصر img يؤدي استخدام max-width: 100% إلى تعديل override أبعاد الصورة الأصلية. ومع ذلك، يجب الاستمرار في استخدام سمة العرض width والإرتفاع height لوسم الصورة <img>؛ نظرًا لاستخدام المتصفحات الحديثة هذه الأبعاد لحجز مساحة الصورة قبل تحميلها؛ مما يُساعد على تجنُّب الإزاحات في التخطيط layout shifts عند تحميل المحتوى. التخطيط نظرًا لاختلاف أبعاد الشاشة وعرضها المُحدّد بالبكسل في أنماط CSS كثيرًا بين الأجهزة (مثلًا، بين الهواتف والأجهزة اللوحية، وحتى بين الهواتف المختلفة)، يجب ألّا يعتمد المحتوى على عرض إطار عرضٍ معيّن لإظهار المحتوى جيدًا. تطلّب ذلك سابقًا ضبط العناصر المُستخدمة لإنشاء التخطيط باستخدام النسب المئوية. يُبين المثال التالي تخطيط عمودين مع عناصرٍ عائمة باستخدام البكسل لتحديد الحجوم. يتعيّن على المستخدم استخدام شريط التمرير الأفقي لرؤية المحتوى عندما يُصبح عرض إطار العرض أصغر من مجموع عرضي العمودين: بينما تبقى الأعمدة دائمًا نسبًا مئوية معينة من الحاوية عند استخدام النسب المئوية للعرض؛ مما يعني أن الأعمدة ستُصبح أضيق عوضًا عن ظهور أشرطة التمرير، كما يُبين المثال التالي: يسمح استخدام بعض تقنيات التخطيط الحديثة إنشاء هذه الشبكات المرنة بسهولةٍ كبيرة، مثل تقنية الصندوق المرن Flexbox والتخطيط الشبكي Grid Layout والتخطيط متعدد الأعمدة Multicol. التخطيط باستخدام الصندوق المرن Flexbox تُعدّ هذه الطريقة طريقة التخطيط المثالية عند وجود مجموعةٍ من العناصر ذات الحجوم المختلفة والمطلوب وضعها في صفٍ واحد أو عدة صفوف، مع احتلال العناصر الأصغر مساحةً أقل والأخرى الأكبر مساحةً أكثر. .items { display: flex; justify-content: space-between; } يُمكن استخدام طريقة التخطيط Flexbox لعرض العناصر في صفٍ واحد أو في صفوفٍ متعددة مع تقليص المساحة المتاحة، كما يُبين المثال التالي: التخطيط الشبكي باستخدام أنماط CSS يسمح استخدام التخطيط الشبكي في أنماط CSS بإنشاء الشبكات المرنة مباشرةً؛ حيث يُمكن مثلًا إعادة إنشاء المثال السابق مع العناصر العائمة باستخدام التخطيط الشبكي والوحدة fr، التي تُمثّل جزءًا من المساحة المتاحة في الحاوية، عوضًا عن النسب المئوية كما يلي: .container { display: grid; grid-template-columns: 1fr 3fr; } يُمكن أيضًا استخدام التخطيط الشبكي لإنشاء تخطيط شبكةٍ منتظمةٍ مع أي عددٍ من العناصر التي تُناسبها؛ حيث ينخفض عدد المسارات (الأعمدة) مع تقليص حجم الشاشة. يُبين المثال التالي توضُّع العدد المناسب من البطاقات في كل سطر مع حجم ٍأدنى 200px: التخطيط متعدد الأعمدة Multicol يُمكن استخدام التخطيط متعدد الأعمدة Multicol مع بعض أنواع التخطيطات لإنشاء عددٍ من الأعمدة المتجاوبة باستخدام خاصية عرض العمود column-width. يُمكن في المثال التالي معاينة إمكانية إضافة أعمدةٍ أخرى بعرض 200px إذا وجدت المساحة الكافية لها. استخدام استعلامات الوسائط في أنماط CSS لتحقيق التجاوب نحتاج أحيانًا إلى إجراء تغييراتٍ جذرية على التخطيط لدعم حجم شاشةٍ معينة وعلى نحوٍ أكبر مما تسمح به التقنيات السابقة. يأتي هنا دور استعلامات الوسائط media queries؛ وهي عوامل تصفية يُمكن تطبيقها على أنماط CSS بهدف تعديل الأنماط وفق أنواع الأجهزة التي تُظهر المحتوى أو ميزات هذه الأجهزة، مثل العرض والارتفاع والاتجاه وقابلية الحومان hover، وفيما إذا كانت الشاشة تعمل باللمس أم لا. نحتاج لاستهداف نوعٍ من الإظهار لتوفير أنماطٍ مختلفة للطباعة. يُمكن تضمين ورقة أنماط stylesheet تحوي أنماط الطباعة المختلفة كما يلي: <!DOCTYPE html> <html lang="en"> <head> … <link rel="stylesheet" href="print.css" media="print"> … </head> … كما يُمكن عوضًا عن الطريقة السابقة، تضمين أنماط الطباعة في ورقة الأنماط الرئيسية باستخدام استعلام الوسائط على النحو التالي: @media print { /* توضع أنماط الطباعة هنا */ } يُمكن تضمين أوراق أنماطٍ منفصلة في ملف أنماط CSS الرئيسي الخاص بك باستخدام صيغة import@، مثلًا: `@import url(print.css) print; إلا أنه لا يُوصى بهذا الاستخدام لأسبابٍ تتعلق بالأداء. يُمكن الرجوع إلى تجنُّب عمليات استيراد CSS لمزيدٍ من التفاصيل. يُستعلم في تصميم الويب المتجاوب عن ميزات الجهاز بهدف توفير تخطيطٍ مختلف للشاشات الأصغر؛ أو عند اكتشاف استخدام الزائر لشاشةٍ تعمل باللمس. استعلامات الوسائط المعتمدة على حجم إطار العرض تسمح استعلامات الوسائط بإنشاء تجربة استخدامٍ متجاوبة، حيث تُطبّق أنماطٌ معينة وفق حجوم الشاشات المختلفة؛ أي أن الميزة التي نستعلم عنها هي حجم الشاشة، كما يُمكن الاستعلام أيضًا عمّا يلي: العرض width (أدنى عرض min-width، أقصى عرض max-width). الارتفاع height (أدنى ارتفاع min-height، أقصى ارتفاع max-height). الاتجاه orientation. نسبة العرض إلى الارتفاع aspect-ratio. تتمتع كل هذه السمات بدعمٍ كامل من جميع المتصفحات. يجب عدم استخدام سمة عرض الجهاز device-width وسمة ارتفاع الجهاز device-height رغم وردهما في المواصفات القياسية؛ حيث أُلغي الاعتماد عليهما لأنهما تختبران الحجم الحقيقي لنافذة الجهاز وهو أمرٌ غير مفيد عمليًا، إذ يُمكن أن يكون هذا الحجم مختلفًا عن حجم إطار العرض الذي يُعاينه المستخدم، لاسيما فيما لو غيَّر حجم نافذة المتصفح مثلًا. استعلامات الوسائط المعتمدة على قدرات الجهاز لا يُمكن الجزم بأن كل جهازٍ كبير هو حاسوبٌ مكتبي، أو أن الأشخاص يستخدمون شاشات اللمس فقط على الأجهزة الصغيرة وذلك نظرًا لتنوع الأجهزة المُتاحة كثيرًا. يُمكن استخدام الإضافات الحديثة لمواصفات استعلامات الوسائط لاختبار نوع المؤشر المُستخدم للتفاعل مع الجهاز وفيما إذا كان المستخدم يستطيع الحومان hover على العناصر. الحومان hover. المؤشر pointer. "أي حومان" any-hover. "أي مؤشر" any-pointer. يُمكن للقارئ معاينة هذا العرض على أجهزةٍ مختلفة، مثل حاسوبٍ مكتبي، أو هاتف، أو جهاز لوحي. تتمتع هذه السمات الجديدة بدعمٍ كاملٍ من جميع المتصفحات الحديثة. استخدام سمة أي حومان any-hover وسمة أي مؤشر any-pointer تختبر سمة أي حومان any-hover فيما إذا كان المستخدم يتمتع بإمكانية الحومان؛ كما تختبر سمة أي مؤشر any-pointer استخدام نوعٍ ما من المؤشرات، وذلك حتى لو لم تكن الطريقة الأساسية لتفاعل المستخدم مع الجهاز. يجب توخي الحذر عند استخدام هذه السمات إذ لن يكون الطلب من المستخدم استخدام الفأرة عوضًا عن شاشة اللمس أمرًا مُحبذًا. يُمكن أن تكون هاتان السمتان مفيدتين، إذا كان من المهم معرفة نوع الجهاز الذي يمتلكه المستخدم. على سبيل المثال، ينبغي أن يُتابع الحاسوب المحمول المزود بشاشة لمس ولوحة تتبُّع المؤشرات العريضة والدقيقة إضافًة إلى إمكانية الحومان. كيفية اختيار النقاط الحدية يجب عدم اختيار النقاط الحدّية وفق فئات الأجهزة، حيث أن تعريف هذه النقاط اعتمادًا على أجهزةٍ، أو منتجات، أو أسماء علاماتٍ تجارية، أو نظم تشغيلٍ مُحدّدة قيد الاستخدام حاليًا يُمكن أن يؤدي إلى صعوبة الصيانة لاحقًا. عوضًا عن ذلك، ينبغي أن يُحدّد المحتوى كيفية ملائمة التخطيط لحاويته. اختيار النقاط الحدية بدءا من الحجم الأصغر ومن ثم الأكبر يجب تصميم المحتوى ليلائم حجم الشاشات الصغيرة أولًا، ومن ثم يُمكن توسيع الشاشة حتى يُصبح إدراج نقطة حدّية ضروريًا؛ حيث يُتيح ذلك الحصول على نقاط حدّية أمثلية بالاعتماد على المحتوى وبأقل عددٍ ممكن من هذه النقاط. بالعودة إلى مثال توقعات الطقس، الذي عرضناه في البداية، تكمن الخطوة الأولى في إظهار التوقعات على شاشةٍ صغيرة جيدًا كما يُبين الشكل التالي: ومن ثم تعديل حجم المتصفح حتى الحصول على فراغاتٍ بيضاء واسعة بين العناصر، وبحيث لا يبدو منظر توقعات الطقس جيدًا. يُمكن بالطبع أن يكون الحكم على جودة المنظر قرارًا شخصيًا، إلا أن الزيادة عن 600px ستُعطي فراغاتٍ عريضةً بالتأكيد. يُبين الشكل التالي مظهر التطبيق في وضعٍ يُظهر وجوب تعديل التصميم: لإدراج نقطةٍ حدّية عند 600px، نُنشئ استعلامي وسائط في نهاية أنماط CSS للمكوّن؛ حيث يُستخدم الأول عندما يكون عرض المتصفح أقل أو يساوي 600px؛ بينما يُستخدم الآخر عندما يكون عرض المتصفح أكبر من 600px. @media (max-width: 600px) { } @media (min-width: 601px) { } أخيرًا، نُعيد تشكيل أنماط CSS كما يلي: نُضيف أنماط CSS للشاشات الصغيرة ضمن استعلام الوسائط الأول وأنماط CSS للشاشات الأكبر ضمن استعلام الوسائط الثاني. اختيار نقاط حدية ثانوية عند الضرورة من المفيد إجراء بعض عمليات الضبط الطفيفة إضافًة إلى النقاط الحدّية الرئيسية المستخدمة لتغييرات التخطيط الكبيرة؛ حيث من المفيد مثلًا ضبط هوامش أو بطانة padding عنصر أو زيادة حجم الخط بين النقاط الحدّية الرئيسية مما يُساهم في جعل التخطيط مريحًا أكثر. يُمكن مثلًا البدء بتحسين تخطيط الشاشات الصغيرة عن طريق تكبير حجم الخط عند تجاوز عرض إطار العرض 360px، كما يُمكن الفصل بين درجات الحرارة العليا والدنيا بحيث تكون على نفس السطر عوضًا عن وضعها فوق بعضها بعضًا، إضافًة لتكبير أيقونة الطقس قليلًا وذلك عند توفر المساحة الكافية لذلك. @media (min-width: 360px) { body { font-size: 1.0em; } } @media (min-width: 500px) { .seven-day-fc .temp-low, .seven-day-fc .temp-high { display: inline-block; width: 45%; } .seven-day-fc .seven-day-temp { margin-left: 5%; } .seven-day-fc .icon { width: 64px; height: 64px; } } وبالمثل، يكون من الأفضل تحديد أقصى عرضٍ للوحة توقعات الطقس، بحيث لا تمتد على كامل عرض الشاشة. إعدادات النص للقراءة الأمثلية تنص قواعد إتاحة القراءة السهلة على وجوب عدم احتواء السطر الواحد على أكثر من 70 إلى 80 حرفًا (حوالي 8 إلى 10 كلمات في اللغة الإنجليزية)؛ مما يتطلب إدراج نقطة حدّية في حال تجاوز عدد الكلمات في كتلةٍ نصية 10 كلمات. يُبين الشكل التالي مظهر النص على هاتف جوال: بينما يظهر نفس النص على حاسوبٍ مكتبي بعد إضافة النقاط الحدّية لتحديد طول السطر: يُبين المثال السابق ملاءمة الخط Roboto من الحجم 1em على نحوٍ أمثلي للشاشات الصغيرة، حيث يوفر حوالي 10 كلمات في السطر الواحد؛ أما بالنسبة للشاشات الكبيرة فيجب إضافة نقطة حدّية. يُبين المثال التالي تحديد عرض المحتوى إلى 550px إذا تجاوز عرض المتصفح 575px. @media (min-width: 575px) { article { width: 550px; margin-left: auto; margin-right: auto; } } تجنب إخفاء المحتوى يجب توخي الحذر عند اختيار المحتوى المطلوب إخفاءه أو إظهاره وفق حجم الشاشة؛ إذ لا يجب إخفاء محتوًى ما لمجرد عدم ملاءمته لحجم الشاشة، فقد يكون هذا المحتوى مهمًا جدًا للمستخدم. يُشكّل مثلًا إخفاء نسبة غبار الطلع في الهواء من توقعات الطقس مشكلةً كبيرة للذين يعانون من الحساسية في فصل الربيع والذين يحتاجون لهذه المعلومة لمعرفة فيما إذا كان بإمكانهم الخروج من المنزل أم لا. معاينة النقاط الحدية لاستعلامات الوسائط في أدوات التطوير Chrome DevTools يُمكن تغيير حجم المتصفح لمعاينة مظهر صفحات الموقع بعد الانتهاء من إعدادات النقاط الحدّية، كما يُمكن أيضًا استخدام أدوات التطوير Chrome DevTools، والتي تسمح بمعاينة الصفحة مع مختلف النقاط الحدّية. يُبين الشكل التالي تطبيق حالة الطقس مع إطار عرضٍ عريض باستخدام DevTools: كما يُبين الشكل التالي تطبيق حالة الطقس مع إطار عرضٍ ضيق باستخدام DevTools: لمعاينة الصفحة مع نقاط حدّية مختلفة، يُمكن فتح أدوات المطور DevTools ثم تشغيل وضع الجهاز Device Mode مما يؤدي لفتح الصفحة بالوضع المتجاوب responsive mode. كما يُمكن لمعاينة استعلامات الوسائط وإظهار النقاط الحدّية على هيئة أشرطةٍ ملونة، اختيار Show media queries من القائمة Device Mode. يؤدي النقر على شريطٍ من هذه الأشرطة إلى معاينة الصفحة مع تنشيط استعلام الوسائط الموافق، كما يؤدي النقر بزر الفأرة الأيمن على شريطٍ ما للانتقال إلى تعريف استعلام الوسائط الموافق. ترجمة -وبتصرف- للمقالة Responsive web design basics للمؤلفين: Pete LePage و Rachel Andrew. اقرأ أيضًا ما هو الفرق بين التصميم المتجاوب (Responsive Web Design) والتصميم المتلائم (Adaptive Web Design) الدليل الشامل لشرح النقاط الحدية لصفحات الويب المتجاوبة
  9. يتنقل المستخدمون بين واجهات العرض المختلفة طوال الوقت، مثل الانتقال من واجهةٍ تحوي قائمةً من العناصر إلى واجهةٍ تعرض تفاصيل عنصرٍ ما من هذه العناصر، أو إظهار شريط تنقُّلٍ جانبي عن طريق النقر على جزءٍ منه. يُساهم التحريك بين الواجهات إلى زيادة ارتباط المستخدم بالتطبيق وإضفاء الحياة عليه. يجب استخدام الانتقالات translations للتنقُل بين الواجهات، مع تجنُّب استخدام خصائصٍ، مثل اليسار left أو الأعلى top والتي تُنشّط التخطيط. يجب التأكد من سرعة التحريك وقصر مدته. يجب الانتباه لتغييرات التحريك والتخطيط عند زيادة حجم الشاشة، إذ أن ما يصلح على شاشةٍ صغيرة قد يبدو غريبًا على شاشة حاسوب مكتبي. يعتمد مظهر وسلوك الانتقالات بين الواجهات على أنواع واجهات العرض المختلفة؛ حيث يختلف مثلًا تحريك شريطٍ منبثق شرطي أعلى واجهةٍ عن الانتقال بين قائمة عناصر وواجهة عرض تفاصيل عنصرٍ منها. من قواعد النجاح الأساسية المحافظة على 60 إطارًا في الثانية عند التحريك. وبهذا، نتجنب ظهور التحريك المتقطع المتداخل مع تفاعل المستخدمين؛ كما يجب التأكد من ضبط الخاصية "سوف يُعدّل" will-change لأي عنصرٍ يُخطط لتحريكه لاحقًا. أما بالنسبة للانتقالات بين واجهات العرض، يُستحسن استخدام will-change: transform. استخدام الانتقالات للتنقل بين واجهات العرض لتسهيل عرض الأفكار في هذه المقالة، سنفترض في مثالنا وجود واجهتين، الأولى هي واجهة عرض قائمةٍ من العناصر، والثانية هي واجهة عرض تفاصيل عنصرٍ منها؛ فعند نقر المستخدم على عنصرٍ في قائمة العرض الأولى، تنزلق واجهة عرض التفاصيل لتظهر داخلًة على الشاشة، وتنزلق قائمة العرض الأولى لتختفي خارجةً من الشاشة. لتنفيذ التأثير السابق، نحتاج إلى حاويةٍ لكلتا واجهتي العرض مع ضبط خاصية الفيضان overflow إلى مخفي overflow: hidden. وبهذه الطريقة، توضع كلتا الواجهتين داخل الحاوية جنبًا إلى جنب دون إظهار أي أشرطة تمريرٍ أفقية، كما يُمكن أن تنزلق كل واجهة جنبًا إلى جنب داخل الحاوية حسب الحاجة. تكون أنماط CSS للحاوية: .container { width: 100%; height: 100%; overflow: hidden; position: relative; } يمكن ضبط خاصية موقع الحاوية إلى نسبي relative؛ مما يعني توضُّع كل واجهة عرض ضمن هذه الحاوية تمامًا في الزاوية اليسرى العلوية ومن ثم تُحرّك باستخدام التحويلات. تُعدّ هذه الطريقة أفضل وأسهل من حيث الأداء، من استخدام خاصية اليسار left، التي يؤدي إلى تشغيل التخطيط والطلاء، ويكون من السهل عادًة تخفيف تكلفة هذه الطريقة. .view { width: 100%; height: 100%; position: absolute; left: 0; top: 0; /* أعلم المتصفح بخطة تحريك كل واجهة عرض دخولًا وخروجًا*/ will-change: transform; } تؤدي إضافة الانتقال transition في خاصية التحويل transform إلى إضفاء تأثير انتقالٍ لطيف. يُستخدم منحني بيزيه cubic-bezier مخصّص للوصول إلى شعور استخدام مُحبَّب. .view { transition: transform 0.3s cubic-bezier(0.465, 0.183, 0.153, 0.946); } يجب تحريك واجهة العرض الموجودة خارج الشاشة إلى اليمين، لذا يجب في هذه الحالة نقل واجهة عرض التفاصيل: .details-view { transform: translateX(100%); } يجب الآن كتابة بعض تعليمات JavaScript للتعامل مع الصفوف. تبدِّل الشيفرة التالية الصفوف المناسبة لواجهات العرض: var container = document.querySelector('.container'); var backButton = document.querySelector('.back-button'); var listItems = document.querySelectorAll('.list-item'); /* تعديل الصفوف في الحاوية واختيار واجهة العرض */ function onViewChange(evt) { container.classList.toggle('view-change'); } //عند النقر على عنصر في القائمة يحب عرض واجهة تفاصيله for (var i = 0; i < listItems.length; i++) { listItems[i].addEventListener('click', onViewChange, false); } //العودة للواجهة الأولى عند النقر على زر العودة للخلف backButton.addEventListener('click', onViewChange); وأخيرًا، تُضاف تصريحات CSS إلى هذه الصفوف: .view-change .list-view { transform: translateX(-100%); } .view-change .details-view { transform: translateX(0); } يُمكن تجربة المثال. يُمكن توسيع المثال لإضافة واجهات عرض متعددة مع نفس منهجية العمل: تكون كل واجهة غير مرئية خارج الشاشة مع إحضارها وإظهارها حين الحاجة وإزالة واجهة العرض الحالية. إضافًة إلى الانتقال بين واجهات العرض، يُمكن تطبيق هذه التقنية أيضًا على العناصر المنزلقة، مثل عناصر التنقل في الشريط الجانبي. يكمن الاختلاف الحقيقي الوحيد في أنه لا يجب تحريك واجهات العرض الأخرى. التأكد من تنفيذ التحريك على الشاشات الأكبر يجب الاحتفاظ بقائمة العرض طوال الوقت بالنسبة للشاشات الأكبر عوضًا عن إزالتها، والانتقال لواجهة عرض التفاصيل من الجانب الأيمن. يؤدي هذا إلى سلوكٍ مشابهٍ للتعامل مع واجهة عرض تنقل. تحريك واجهات العرض المنبثقة الشرطية تُستخدم واجهات العرض المنبثقة الشرطية لعرض الرسائل الهامة وذلك في حال توفر الأسباب الموجبة لتعطيل التفاعل مع واجهة المستخدم. يجب عمومًا عدم الإفراط في استخدام هذا النوع من الواجهات لأنها تقاطع تجربة الاستخدام وقد تؤدي لإنهائها؛ إلا أنها يُمكن أن تكون ضرورية في بعض الحالات؛ كما يُسهم إضافة التحريك لها في إضفاء الحيوية عليها. يجب استخدام واجهات العرض المنبثقة الشرطية باعتدال؛ حيث يشعر المستخدمون بالإحباط إذا قاطعت تجربتهم دون داعٍ. تُساهم نسبة التحجيم المناسبة في إضفاء التأثير اللطيف "إسقاط على drop on". يجب إخفاء واجهات العرض المنبثقة الشرطية بسرعة عندما يرفضها المستخدم؛ كما يجب إظهار هذه الواجهات ببطء حتى لا تُفاجئ المستخدم. يجب تطابق حجم غطاء الواجهة المنبثقة مع إطار العرض وذلك عن طريق ضبط خاصية الموضع position إلى ثابت fixed: .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; opacity: 0; will-change: transform, opacity; } تكون قيمة الشفافية opacity للواجهة 0 في البداية وتكون بذلك مخفية، إلا أنها تحتاج أيضًا إلى ضبط أحداث المؤشر pointer-events إلى لا شيء none حتى لا تتجاوب مع أحداث المستخدم مثل النقر واللمس؛ وبدون ذلك، تُعطّل جميع التفاعلات وتغدو الصفحة غير مستجيبة أبدًا. أخيرًا، يجب استخدام will-change مع كلٍ من الخصائص opacity و transform التي يُطبّق التحريك عليها. يُمكن الرجوع إلى استخدام الخاصية will-change. يجب أن تستجيب الواجهة المنبثقة عندما تكون مرئيةً لتفاعلات المستخدم مع شفافيةٍ opacity قيمتها 1: .modal.visible { pointer-events: auto; opacity: 1; } يُمكن استخدام سكريبت جافا لتبديل الصف إلى مرئي "visible" عند الحاجة لعرض الواجهة المنبثقة. modal.classList.add('visible'); يُمكنك الآن، إضافة التحريك إلى الواجهة المنبثقة. .modal { transform: scale(1.15); transition: transform 0.1s cubic-bezier(0.465, 0.183, 0.153, 0.946), opacity 0.1s cubic-bezier(0.465, 0.183, 0.153, 0.946); } تُساهم نسبة التحجيم scale في جعل المنظر يبدو وكأنه يسقط على الشاشة بهدوء، مما يُعطي تأثيرًا جميلًا. يُطبّق الانتقال الافتراضي على كلٍ من خاصية التحويل transform والشفافية opacity مع منحني مخصص ومدةٍ تبلغ 0.1 ثانية. تبدو المدة 0.1 ثانية لظهور الواجهة المنبثقة قصيرةً جدًا، إلا أنها مثاليةٌ للمستخدم الذي يريد اغلاق هذه الواجهة والعودة إلى التطبيق. يكمن الجانب السلبي لهذه المدة القصيرة بالظهور السريع المفاجئ للواجهة. يُمكن إصلاح هذا الخلل بتجاوز هذه القيمة للصف المرئي visible ووضع قيمةٍ أكبر: .modal.visible { transform: scale(1); transition: transform 0.3s cubic-bezier(0.465, 0.183, 0.153, 0.946), opacity 0.3s cubic-bezier(0.465, 0.183, 0.153, 0.946); } يستغرق الآن ظهور الواجهة المنبثقة وقتًا أطول (أقل مفاجأةً للمستخدم) مع إخفاءٍ سريع مما يُلبي طموح المستخدم. توقيت التحريك غير المتزامن يُحسِّن توقيت التحريك غير المتزامن من تجربة الاستخدام من خلال السماح بإضفاء هويةٍ للتطبيق مع التجاوب السريع مع تفاعلات المستخدم بنفس الوقت؛ كما يوفر أيضًا تباين التفاعل مما يجعل الواجهة أكثر جاذبيةً. يُستخدم التوقيت غير المتزامن لإضفاء هويةٍ للتطبيق ولتحقيق تباين العمل. يجب دومًا تفضيل تفاعل المستخدم. يجب مثلًا استخدام فتراتٍ أقصر عند الاستجابة لأحداث المستخدم، مثل النقر أو السحب؛ والاحتفاظ بفتراتٍ أطول للحالات الأخرى. يجب دومًا التجريب لمعرفة المناسب للتطبيق تمامًا مثل معظم قواعد التحريك، مع الانتباه إلى أن المستخدم ليس له الصبر الكافي لفعل ذلك. تنص القاعدة الأساسية على وجوب الاستجابة لتفاعل المستخدم بسرعة. وبما أن تفاعل المستخدم غير متزامن معظم الوقت يجب أن يكون التحريك كذلك. مثلًا: في حال نقر المستخدم على شريط تنقُّل جانبي، لا بُدّ من عرضه مباشرًة وخلال فترة حوالي 100 ميلي ثانية؛ بينما يُمكن التباطؤ في عملية التحريك خارجًا لحوالي 300 ميلي ثانية عند إخفاء المستخدم لقائمة. على النقيض من ذلك، عند إحضار واجهة عرض منبثقة مشروطة (عادةً لعرض خطأ أو بعض الرسائل الهامة الأخرى)، يُمكن إظهار العرض على نحوٍ أبطأ قليلاً (أيضًا حوالي 300 ميلي ثانية)؛ أما عند طلب المستخدم لإغلاق الواجهة، فيجب أن يحدث هذا بسرعة كبيرة. نُبين فيما يلي القواعد العامة للتحريك: يكون للتحريك في واجهة المستخدم والذي يُنشّط عند تفاعل المستخدم، مثل التنقل بين واجهات العرض أو إظهار عنصر ما، مقدمةً سريعة (مدة قصيرة)، وخاتمةً بطيئة (مدة أطول). يكون للتحريك في واجهة المستخدم والذي يُنشّط من خلال شيفرة المطور البرمجية، مثل إظهار الأخطاء أو واجهات العرض المنبثقة المشروطة، مقدمةً أبطأ (مدة أطول)، وخاتمةً سريعة (مدة قصيرة). ترجمة -وبتصرف- للمقالات التالية: Animating Between Views للمؤلف: Paul Lewis. Animating Modal Views للمؤلف: Paul Lewis. Asymmetric animation timing للمؤلف: Paul Lewis. اقرأ أيضًا التحكم في تسارع وتباطؤ الحركات المطبقة على عناصر صفحات الويب المرجع الشامل إلى التحريك عبر CSS أفضل 25 مكتبة تحريك في CSS النسخة العربية الكاملة من كتاب: التحريك عبر CSS
  10. تعدّ عمليات دفع الأموال من العملاء أهم الأمور الواجب تسهيلها لهم وتنويع طرقها كي لا نفقد بعض العملاء الذين قد يواجهون صعوبات في عملية الدفع أو حتى عدم توافرها لديهم، كما يجب توفير طرق متنوعة لشحن البضائع للعملاء ولمختلف المناطق. نعرض في هذا الدرس الأخير من السلسلة إعدادات الدفع والشحن التي يوفرها متجر أوبن كارت بالتفصيل. هذا المقال جزء من سلسلة تعريفية بلوحة تحكم متجر أوبن كارت، إليك فهرس مقالات كامل السلسلة: مدخل إلى متجر أوبن كارت وكيفية تثبيته إدارة الأقسام والمنتجات في متجر أوبن كارت إدارة إعدادات متجر أوبن كارت إدارة المتجر في أوبن كارت شرح الإضافات والقوالب في لوحة تحكم متجر أوبن كارت نظرة على خيارات التسويق التي يوفرها متجر أوبن كارت التقارير والإحصائيات: نافذة على أداء متجر أوبن كارت إعدادات الدفع والشحن في متجر أوبن كارت بوابات الدفع لمتجر أوبن كارت يوفر أوبن كارت مجموعة كبيرة من طرق الدفع الممكنة بدءًا من التحويل البنكي إلى الدفع الإلكتروني عبر الويب، كما يُمكن استخدام أكثر من بوابة دفع Payment Gateway في آن واحد. يجب على مدير المتجر تثبيت وتمكين بوابات الدفع المناسبة للمتجر لتصبح متاحة للعملاء في واجهة المتجر، ويُمكن استعراض قائمة بوابات الدفع المتاحة من صفحة "الإضافات" والتي نصل إليها من "لوحة التحكم" ثم "الإضافات"، ثم نختار نوع الإضافة "طرق الدفع" من القائمة "اختيار نوع الإضافة": تظهر جميع بوابات الدفع المتاحة: لتمكين بوابة الدفع، يجب أولًا تثبيتها وذلك بالنقر على الزر الأخضر "تنصيب" المجاور لها ومن ثم تحرير بوابة الدفع لإدخال الإعدادات المناسبة. يُمكن أيضًا تنزيل طرق دفع أخرى من الرابط. ضبط بوابات الدفع تختلف الإعدادات حسب طريقة الدفع إلا أنها تتشارك جميعًا في الحقول التالية: الإجمالي المطلوب لتفعيل طريقة الدفع Total: الحد الأدنى للمبلغ الذي يُمكن للعميل دفعه باستخدام طريقة الدفع. حالة الطلب Order Status: الحالة التي ستكون للطلب بعد إتمام العميل لعملية الدفع. يُنصح وضع الحالة "جاري التجهيز" لإتاحة الوقت للإدارة لمراجعة الطلب وتجهيزه. الحالة Status: "تمكين" عملية الدفع أو تعطيلها. ترتيب الفرز Sort Order: ترتيب العرض. مثلًا من أجل طريقة الدفع "تحويل بنكي": تكون حقول هذه الطريقة (إضافًة للحقول الأربعة السابقة): اسم البنك وصاحب الحساب Bank Account: معلومات الحساب البنكي للمتجر باللغتين العربية والإنكليزية. المنطقة الجغرافية Geo Area: المنطقة الجغرافية التي يُمكن فيها استخدام طريقة الدفع. أما بالنسبة لطريقة الدفع باستخدام PayPal: تكون حقول طريقة الدفع: تتطلب طريقة الدفع باستخدام PayPal الاشتراك المسبق مع الشركة المسؤولة والحصول على معلومات الاشتراك. الدفع في واجهة المتجر تظهر طرق الدفع المتاحة للعميل في واجهة المتجر في "الخطوة الخامسة: طريقة الدفع" من عملية إتمام الطلب Checkout: يُمكن للعميل معاينة طلباته في واجهة المتجر وذلك بالدخول إلى صفحة "تفاصيل الطلب" ليجد جميع تفاصيل طلباته: الضرائب يحتوي أوبن كارت على خيارات عديدة لإضافة الضريبة على السعر الأساسي، ويعتمد سعر الضريبة على الدولة وبهذا يُمكن تحصيل ضريبة مختلفة من العملاء حسب مناطقهم الجغرافية ووفقًا للضريبة المحلية الموافقة. يُمكن إعداد الضريبة من من "لوحة التحكم" ثم "الضبط" ثم "الضرائب" ثم "أسعار الضريبة": يُمكن أن تكون الضريبة نسبة مئوية أو مبلغًا ثابتًا. بعد الانتهاء من ضبط إعدادات الضرائب، يجب تعريف الضريبة لكل منتج من خيارات المنتج نفسه. طرق الشحن تحتاج المتاجر التي تبيع منتجات ملموسة (غير إلكترونية يُمكن تحميلها من المتجر) إلى طرق شحن مناسبة لها. للوصول إلى قائمة طرق الشحن المتاحة بشكل افتراضي في المتجر، نفتح "الإضافات" من "لوحة التحكم" ثم "الإضافات" ثم "الإضافات" ومن ثم نختار "طرق الشحن" من القائمة "اختيار نوع الإضافة": تظهر طرق الشحن المتاحة: يجب تثبيت طريقة الشحن المطلوبة (بالنقر على الزر "تنصيب" الموافق) ومن ثم إدخال الإعدادات المناسبة لها. تتشارك جميع طرق الشحن في الحقول التالية: سعر الشحن Total: الحد الأدنى للمبلغ الإجمالي لاستخدام طريقة الشحن. المنطقة الجغرافية Geo Zone: المنطقة الجغرافية التي تتوفر لها طريقة الشحن. الحالة Status: "تمكين" طريقة الشحن أو تعطيلها في واجهة المتجر. الفرز Sort Order: ترتيب الإظهار. تختلف حقول إعداد طريقة الشحن وفق الطريقة المختارة. مثلًا من أجل طريقة الشحن "تكلفة ثابتة للشحن": تكون الحقول: بينما من أجل الطريقة "الشحن بالقطعة": تكون الحقول: كما يُمكن الشحن عبر الشركات العالمية للشحن مثل UPS: يجب إدخال معلومات الاشتراك والتعامل مع الشركة: يؤدي ضبط مدير المتجر طرق الشحن في لوحة التحكم بالمتجر إلى إتاحة الطرق المختارة إلى العملاء في واجهة المتجر في سلة الشراء Shopping Cart وفي صفحات إتمام الطلب Checkout. ملاحظة: يُمكن إعداد المناطق الجغرافية من صفحة "المناطق الجغرافية" والتي نفتحها من "الضبط" ثم "الأوضاع" ثم "المناطق الجغرافية". تُستخدم المناطق الجغرافية في إعدادات الشحن والضرائب. يُمكن وضع دول ومناطق مختلفة في مجموعة جغرافية واحدة: إضافة أجور الشحن في سلة الشراء تحتوي سلة الشراء التبويب "الشحن المتوقع" "Estimate Shipping & Taxes" والذي يسمح بمعرفة أجور الشحن المترتبة. تظهر أجور الشحن بعد النقر على الزر "إرسال": حيث يُطلب اختيار طريقة الشحن المناسبة ومن ثم التأكيد بالنقر على الزر "اعتمد الشحن"، وستًضاف قيمة الشحن إلى إجمالي الطلبية. لاحظ أنه يُمكن تمكين أو تعطيل هذه الميزة من الإضافة "طريقة الشحن" كما يلي، نفتح صفحة "الإضافات" ونختار "إجماليات الطلب" من القائمة "اختيار نوع الإضافة": حيث تظهر جميع الإضافات والتي يُمكن أن تُعدّل (إضافة أو إنقاص) من إجمالي الطلبية: مثلًا يُمكن تمكين "طريقة الشحن": تحديد الشحن أثناء إتمام الطلب Checkout يتوجب على العميل في الخطوة الرابعة من إتمام الطلب إلى تحديد طريقة الشحن قبل إنهاء عملية الشراء. تُعرض جميع طرق الشحن المُمكنّة من قبل مدير المتجر: خاتمة عرضنا في هذا الدرس مختلف آليات الدفع والشحن المتاحة في أوبن كارت والتي تُناسب مختلف الحالات المُمكنة عمليًا. اقرأ أيضًا كيف تختار السعر الملائم للمنتج؟ مراحل عملية الشراء -عند الإقدام على فعل الشراء-
  11. لا يتحرك أي شيء في الطبيعة من نقطةٍ إلى أخرى خطيًا، حيث تميل الأشياء إلى التسارع أو التباطؤ أثناء تحرُّكها على أرض الواقع. بما أن أدمغتنا مصممةٌ لتوقُّع مثل هذا النوع من الحركة، يجب استخدام ذلك عند التحريك لتحسينه وجعل الحركة تبدو طبيعية مما يؤدي لشعور المستخدمين براحةٍ أكبر والوصول إلى تجربة استخدامٍ أفضل للتطبيق عمومًا. يؤدي التخفيف إلى جعل التحريك يبدو طبيعيًا. يُفضّل استخدام تخفيف السرعة نهاية الحركة ease-out مع عناصر الواجهة. يجب تجنُّب استخدام تخفيف السرعة بداية الحركة ease-in وتخفيف السرعة بداية الحركة ونهايتها ease-in-out ما لم يكن التحريك قصيرًا، لأنهما تتسببان بنوعٍ من الحركة الخمولة. الكلمات المفتاحية في التخفيف تسمح كلٌ من الانتقالات والتحريك في CSS باختيار نوع التخفيف المطلوب للتحريك (راجع فقرة اختيار التخطيط الصحيح). يُمكن استخدام الكلمات المفتاحية التي تؤثر على التخفيف (أو التوقيت timing كما يُطلق عليه أحيانًا) للحركة المعنية؛ كما يُمكن أيضًا تخصيص التخفيف (راجع فقرة تخصيص التخفيف)، مما يمنح الحرية الواسعة لإعطاء هويةٍ مميزة للتطبيق. أهم الكلمات المفتاحية المُمكن استخدامها في أنماط CSS: خطي linear. تخفيف السرعة بداية الحركة ease-in. تخفيف السرعة نهاية الحركة ease-out. تخفيف السرعة بداية الحركة ونهايتها ease-in-out. يُمكن الوصول إلى المصدر في W3C. يُطلق مصطلح "الدخول ببطء slow in" في الرسوم المتحركة للدلالة على الحركة التي تبدأ ببطء ومن ثم تتسارع؛ كما يُطلق مصطلح "الخروج ببطء slow out" على الحركة التي تبدأ مُسرعًة ومن ثم تتباطأ. يُستخدم بصورةٍ مماثلة كلٌ من المصطلحين "تخفيف السرعة بداية الحركة ease in" و"تخفيف السرعة نهاية الحركة ease out" في التحريك على الويب. يُمكن الجمع أحيانًا بين نوعي التحريك السابقين وصولًا إلى "تخفيف السرعة بداية الحركة ونهايتها ease-in-out". يؤدي استخدام التخفيف الحصول على حركة أقل حدًّة وأكثر وضوحًا. يُمكن استخدام الكلمة المفتاحية خطوات steps لإنشاء الانتقالات ذات الخطوات المنفصلة، ولكن تُعدّ الكلمات المفتاحية السابقة أكثر فائدةً في إنشاء التحريك الذي يبدو طبيعيًا. التحريك الخطي يُوصف التحريك الذي لا يستخدم أي تخفيفٍ بالتحريك الخطي linear. يوضّح الرسم البياني التالي مراحل الانتقال الخطي؛ حيث تزداد القيمة زياداتٍ متساوية عبر الزمن. تبدو الحركة الخطية آليةً وغير طبيعية مما يُنفّر المستخدمين، وبالتالي يجب تجنُّب التحريك الخطي. يُمكن استخدام التحريك الخطي دومًا سواءٌ عند استخدام أنماط CSS أو عند استخدام JavaScript. يُمكن معاينة تحريك خطي. للحصول على التأثير السابق باستخدام أنماط CSS: transition: transform 500ms linear; تخفيف السرعة نهاية الحركة يؤدي تخفيف السرعة نهاية الحركة ease-out إلى بدءٍ أسرع للحركة مما هو في التحريك الخطي، وتَباطُؤ في النهاية، كما هو موضحٌ في الرسم البياني التالي. يُعدّ تخفيف السرعة نهاية الحركة ease-out الخيار الأفضل لواجهات المستخدم؛ حيث تُعطي البداية السريعة الانطباع بالتجاوب مع توفير التباطؤ الطبيعي في النهاية. يُمكن معاينة تخفيف السرعة نهاية الحركة. يُمكن تحقيق تخفيف السرعة نهاية الحركة بعدة طرق؛ ومن أسهلها استخدام الكلمة المفتاحية ease-out في CSS: transition: transform 500ms ease-out; تخفيف السرعة بداية الحركة Ease-in يبدأ التحريك من هذا النوع ببطء وينتهي بسرعة خلافًا للتحريك من النوع تخفيف السرعة نهاية الحركة Ease-out، كما هو موضح في الرسم البياني التالي. يشبه هذا التحريك تسارع سقوط حجرٍ ثقيل؛ حيث يبدأ ببطء ويصطدم بالأرض بسرعةٍ كبيرة. يُمكن مع ذلك أن يبدو هذا النوع من الحركة غير طبيعي بسبب نهايتها المفاجئة، حيث تميل الأشياء المتحركة في عالمنا الحقيقي إلى التباطؤ عوضًا عن التوقُّف المفاجئ. يؤدي تخفيف السرعة بداية الحركة إلى الشعور بالركود عند البداية البطيئة؛ مما يؤثر سلبًا على ملاحظة الإستجابة في الموقع أو التطبيق. يُمكن معاينة تخفيف السرعة بداية الحركة. يُمكن تحقيق تخفيف السرعة بداية الحركة باستخدام الكلمة المفتاحية ease-in في CSS: transition: transform 500ms ease-in; تخفيف السرعة بداية الحركة ونهايتها Ease-in-out يُشبه تخفيف السرعة بداية الحركة ونهايتها عمليات تسارع وتباطؤ السيارة ويُمكنه توفير تأثيراتٍ أفضل من تأثيرات تخفيف السرعة نهاية الحركة في حال استخدامه بحكمة. لا يجب وضع مدةٍ طويلةٍ للتحريك بسبب البطء في بداية التحريك مع تخفيف الدخول. يُمكن أن تكون أي قيمةٍ بين 300 و500 ميلي ثانية مناسبةً؛ وتعتمد القيمة الدقيقة على طبيعة المشروع. تؤدي البداية البطيئة والتسارع في المنتصف والنهاية البطيئة إلى مزيدٍ من التباين في التحريك مما يُرضي المستخدمين. يُمكن معاينة تخفيف السرعة بداية الحركة ونهايتها. يُمكن الحصول على تحريك من النوع "تخفيف السرعة بداية الحركة ونهايتها" باستخدام الكلمة المفتاحية ease-in-out: transition: transform 500ms ease-in-out; التخفيف المخصص يُمكن في بعض الأحيان التخلّي عن استخدام الكلمات المفتاحية في CSS، أو واجهة برمجة التطبيقات Web Animations، أو إطار عمل JavaScript، وتعريف منحنياتٍ أو معادلاتٍ مخصصة عوضًا عن ذلك؛ مما يوفر تحكُّمًا أكبر في التحريك المطلوب. يسمح التخفيف المُخصّص بإضفاء هويةٍ شخصيةٍ مُميزةٍ للمشروع. يُمكّن التخفيف المُخصّص من إنشاء منحنيات بيزيه Bézier المكعبة، والتي تُشبه منحنيات التحريك الافتراضية (تخفيف السرعة بداية الحركة، تخفيف السرعة نهاية الحركة، …) مع التركيز على جوانبٍ مختلفة. تُستخدم JavaScript عند الحاجة لتوفير تحكمٍ أكبر في توقيت التحريك وسلوكه، مثل التحريك المرن أو المُرتدّ bounce . يُمكن تعريف منحنيات بيزيه المكعبة في أنماط CSS لتحديد التوقيت؛ حيث توافق الكلمات المفتاحية ease و ease-in و ease-out و linear في الحقيقة منحنيات بيزيه مُعرّفةً مسبقًا. يُمكن الرجوع للتفاصيل في CSS transitions specification و Web Animations specification. تأخذ منحنيات بيزيه أربع قيم (أو زوجين من الأرقام)؛ حيث يُحدّد كل زوجٍ إحداثيات X و Y لنقاط التحكم في منحني بيزيه المكعب. يكون لنقطة البداية لمنحني بيزيه الإحداثيات (0 ، 0)، والإحداثيات (1 ، 1) لنقطة النهاية، ويُمكن ضبط قيم X و Y لنقطتي التحكم. يجب أن تكون قيم X لنقطتي التحكم بين 0 و 1، بينما يُمكن لقيم Y تجاوز المجال [0,1]. لا تُحدّد المواصفات مقدار التجاوز المسموح بوضوح. يُعطي تغيير قيمة X و Y لكل نقطة تحكم منحنًى مختلفٍ تمامًا، وبالتالي شعورًا مختلفًا تمامًا مع التحريك المُخصص. إذا كانت نقطة التحكم الأولى في المنطقة اليمنى السفلية مثلًا، يكون بدء التحريك بطيئًا؛ أما إذا كانت في المنطقة العلوية اليسرى، يكون بدء التحريك سريعًا؛ وعلى العكس من ذلك، إذا كانت نقطة التحكم الثانية في المنطقة اليمنى السفلية من الشبكة، يكون التحريك سريعًا في النهاية؛ أما إذا كانت في المنطقة العلوية اليسرى، يكون التحريك بطيئًا في النهاية. يُمكن مقارنة منحنيين في الشكل التالي، المنحني الأيسر مع تخفيف-داخل أما المنحني الأيمن فهو مُخصص: يُمكن معاينة التحريك مع تخفيف مخصص. تكون أنماط CSS للتخفيف المخصص: transition: transform 500ms cubic-bezier(0.465, 0.183, 0.153, 0.946); يُحدّد الرقمان الأولان إحداثيات X و Y لنقطة التحكم الأولى؛ بينما يحدد الرقمان الثانيان إحداثيات X و Y لنقطة التحكم الثانية. يُعدّ إنشاء منحنًى مخصصًا أمرًا ممتعًا للغاية، ويمنح تحكمًا كبيرًا في طبيعة التحريك. يُشبه المنحنى السابق مثلًا المنحني التقليدي في "تخفيف السرعة بداية الحركة ونهايتها" مع تباطؤ الدخول والخروج. يُمكن تجريب أداة منحني التحريك ومعاينة تأثيرات المنحني على طبيعة التحريك. استخدم أطر عمل JavaScript لتوفير المزيد من التحكم تظهر الحاجة أحيانًا إلى تحكمٍ أكبر مما يوفِّره منحني بيزيه المكعب، حيث يجب مثلًا استخدام أطر عمل JavaScript في حال ضرورة توفير الشعور بالارتداد المرن؛ لأنه لا يُمكن توفير ذلك باستخدام أنماط CSS أو Web Animations. إطار العمل TweenMax يُعدّ إطار العمل GreenSock’s TweenMax (أو الإطار TweenLite في حال الرغبة بإبقاء الشيفرة خفيفة) من الأطر القوية التي توفر قدرًا كبيرًا من التحكم باستخدام مكتبة JavaScript صغيرة؛ علمًا أن هذه المكتبة تحتوي شيفرة قاعدية ناضجة. يُمكن معاينة تخفيف تحريك مرن. لاستخدام TweenMax، يجب تضمين الشيفرة التالية في الصفحة: <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenMax.min.js"></script> بعد ذلك، يُمكن استدعاء TweenMax مع أي عنصرٍ لتحريكه مع ضبط الخصائص المناسبة لأي تخفيفٍ مطلوب. يوجد العديد من خيارات التخفيف المُمكن استخدامها؛ حيث تَستخدم الشيفرة التالية مثلًا تخفيف خروجٍ مرن: var box = document.getElementById('my-box'); var animationDurationInSeconds = 1.5; TweenMax.to(box, animationDurationInSeconds, { x: '100%', ease: 'Elastic.easeOut' }); تُسلِّط وثائق TweenMax الضوء على جميع الخيارات الممكنة. اختيار التخفيف الصحيح بعد مناقشتنا السابقة للخيارات المختلفة المُتاحة لتخفيف التحريك، تبرز الأسئلة التالية: ما نوع التخفيف الواجب استخدامه في المشاريع؟ وما هي المدة الأنسب للتحريك؟ يُفضّل استخدام "تخفيف السرعة نهاية الحركة" لتحريك عناصر الواجهة، ويُعدّ Quintic من أكثر الأنواع جاذبيةً وأناقة وإن كان سريعًا. يجب التأكُّد من ضبط مدة التحريك؛ حيث يُمكن أن تكون مدة 200 إلى 500 ميلي ثانية مناسبةً لتخفيف السرعة بداية الحركة ونهايتها؛ بينما يستلزم التخفيف المرن والمُرتدّ مدًةً أطول بين 800 إلى 1200 ميلي ثانية. يُعدّ "تخفيف السرعة نهاية الحركة" الخيار الصحيح (يجب وضعه الخيار الإفتراضي) عمومًا، ويتميز بسرعة البدء، مما يُعطي الشعور بتجاوب التطبيق، مع تباطؤٍ لطيف في النهاية. توجد مجموعةٌ من المعادلات المعروفة المستخدمة لتنفيذ التحريك مع "تخفيف السرعة نهاية الحركة" والمختلفة عن تلك المحددة بالكلمة المفتاحية ease-out في CSS والتي تتراوح في شدتها. يُمكن استخدام Quintic ease-out للحصول على تأثير "تخفيف السرعة نهاية الحركة". يُمكن معاينة تحريك تخفيف السرعة نهاية الحركة Quintic. يجب الاعتدال في استخدام معادلات التخفيف الأخرى، لا سيما معادلات الارتدادات أو التخفيف المرن، واستخدامها فقط عندما تكون مناسبةً للمشروع؛ فقد تؤدي بعض الأشياء الصغيرة إلى تردِّي تجربة الاستخدام في حالات التحريك السيء المتنافر. إذا لم يكن المرح من أحد أهداف المشروع، فلا يجب إظهار عناصرٍ تتحرك وترتد؛ أما في حال الرغبة بإضفاء جوٍ من المتعة والمرح على التطبيق، يجب استخدام الارتداد بأي طريقة! يجب التجريب واللعب مع طرق التخفيف المختلفة للحكم على الطريقة الأنسب لهوية المشروع. يُمكن الرجوع إلى easings.net لمزيدٍ من التفاصيل. اختيار المدة المناسبة للحركة تُعدّ مسألة اختيار المدّة الصحيحة للحركة من أهم المسائل؛ حيث يُعطي التحريك قصير الأمد شعورًا بالعدوانية والحدّية؛ بينما يصبح التحريك طويل الأمد معرقلًا ومزعجًا. التخفيف الخارج Ease-outs: حوالي 200 إلى 500 ميلي ثانية، حيث تمنح هذه المدّة للعين فرصًة لرؤية التحريك دون أي معوقات. التخفيف الداخل Ease-ins: حوالي 200 إلى 500 ميلي ثانية. يجب الانتباه إلى مسألة السقوط السريع في النهاية مما لا يسمح لتعديلات المدّة بتنعيم الحركة. تأثيرات الارتداد أو المرونة: حوالي 800 إلى 1200 مللي ثانية. يلزم إتاحة الوقت الكافي لاستقرار التأثير المرن أو المرتد. بدون هذا الوقت الإضافي، سيكون الجزء المرتد المرن من التحريك عدوانيًا وغير مريح للعين. ما عرضناه هو مجرد إرشادات، لذلك يجب تجريب طرق التخفيف الممكنة واختيار الأنسب منها للمشروع. ترجمة -وبتصرف- للمقالات التالية: The Basics of Easing للمؤلف: Paul Lewis. Custom Easing للمؤلفين: Paul Lewis و Sam Thorogood. Choosing the Right Easing للمؤلفين: Paul Lewis و Perf Advocate. اقرأ أيضًا المرجع الشامل إلى التحريك عبر CSS أفضل 25 مكتبة تحريك في CSS النسخة العربية الكاملة من كتاب: التحريك عبر CSS
  12. تعدّ التقارير والإحصائيات أهم الأدوات المتوفرة في أوبن كارت التي توفر طريقة سهلة لمعرفة أداء المتجر عن طريق حساب وإظهار مجموعة متنوعة من الإحصائيات والملخصات الإجمالية، فيوفر أوبن كارت بشكل افتراضي 12 تقريرًا حول المبيعات والعملاء والشحن وغيرها. يُمكن الانتقال لصفحة "التقارير" من الخيار "التقارير" في لوحة التحكم ثم "التقارير" ثم اختيار التقرير المطلوب من القائمة "اختر نوع التقرير". يسمح الفلتر الموجود يسار الصفحة بفلترة بيانات التقرير. يُمكن أن تختلف حقول الفلتر وفق التقرير إلا أنه يحوي دائمًا حقلي تاريخ بداية وتاريخ نهاية التقرير. نتعرف في هذا المقال على التقارير التي يوفرها متجر أوبن كارت والتي تساعد في عملية التجارة الإلكترونية وإدارة المتجر ومعرفة أدائه لاتخاذ الخطوة المناسبة. هذا المقال جزء من سلسلة تعريفية بلوحة تحكم متجر أوبن كارت، إليك فهرس مقالات كامل السلسلة: مدخل إلى متجر أوبن كارت وكيفية تثبيته إدارة الأقسام والمنتجات في متجر أوبن كارت التعرف على إعدادات واجهة متجر أوبن كارت تعلم كيفية ضبط متجر أوبن كارت شرح الإضافات والقوالب في لوحة تحكم متجر أوبن كارت نظرة على خيارات التسويق التي يوفرها متجر أوبن كارت التقارير والإحصائيات: نافذة على أداء متجر أوبن كارت إعدادات الدفع والشحن في متجر أوبن كارت تقرير المبيعات Orders Report يُعدّ تقرير المبيعات طريقة سهلة لمعرفة مدى جودة أداء المتجر إذ يسمح بمعاينة إيرادات المبيعات لأيام أو أسابيع أو شهور أو سنوات، ويُبين هذا التقرير عدد الطلبيات التي تمت خلال فترة معينة وعدد المنتجات المباعة وإجمالي المبالغ المُحصّلة والضرائب المترتبة. يعرض هذا التقرير الأعمدة التالية: تاريخ البداية Date Start: تاريخ البداية (أول يوم من الأسبوع إذا كان الفرز وفق الأسابيع). تاريخ النهاية Date End: تاريخ النهاية (آخر يوم من الأسبوع إذا كان الفرز وفق الأسابيع). رقم الطلب No. of Orders: عدد الطلبيات من تاريخ البداية إلى تاريخ النهاية. رقم المنتج No. of Products: عدد المنتجات المباعة من تاريخ البداية إلى تاريخ النهاية. الضريبة Tax: مجموع الضريبة المدفوعة من قبل الزبائن. الإجمالي Total: مجموع المبالغ المدفوعة من الزبائن. تقرير الضريبة Tax Report يسمح هذا التقرير بمعاينة الضرائب التي يدفعها الزبائن، ويُبين الضرائب المدفوعة لكل نوع من أنواع الضرائب خلال فترة التقرير. يعرض هذا التقرير الأعمدة التالية: تاريخ البداية Date Start: تاريخ البداية. تاريخ النهاية Date End: تاريخ النهاية. عنوان الضريبة Tax Title: نوع الضريبة. رقم الطلب No. of Orders: عدد الطلبيات من تاريخ البداية إلى تاريخ النهاية. الإجمالي Total: مجموع الضريبة المدفوعة من قبل الزبائن. تقرير الشحن Shipping Report يسمح هذا التقرير بإظهار طرق الشحن المختلفة المُختارة من قبل الزبائن، ويُبين هذا التقرير المبالغ الإجمالية المدفوعة لقاء كل طريقة من طرق الشحن المختلفة خلال مدة التقرير. يعرض هذا التقرير الأعمدة التالية: تاريخ البداية Date Start: تاريخ البداية. تاريخ النهاية Date End: تاريخ النهاية. عنوان الشحن Shipping Title: طريقة شحن المنتجات في الطلبيات الموافقة. رقم الطلب No. of Orders: عدد الطلبيات من تاريخ البداية إلى تاريخ النهاية. الإجمالي Total: مجموع المبالغ المدفوعة لقاء الشحن. تقرير إرجاع المنتجات Returns Report يسمح هذا التقرير بعرض بيانات المرتجعات حيث يعرض عدد طلبات الإرجاع التي تمت خلال فترة التقرير. يعرض هذا التقرير الأعمدة التالية: تاريخ البداية Date Start: تاريخ البداية. تاريخ النهاية Date End: تاريخ النهاية. رقم الإرجاع No. Returns: عدد طلبات الإرجاع بين تاريخ البداية وتاريخ النهاية. تقرير قسائم التخفيض Sale Coupon Report يسمح هذا التقرير بمتابعة استخدام قسائم التخفيض في المتجر. يُبين التقرير إجمالي مبالغ التخفيضات من أجل كل تخفيض مُعرّف في المتجر. يعرض هذا التقرير الأعمدة التالية: اسم التخفيض Coupon name: اسم التخفيض. الرمز Code: رمز التخفيض. الطلبات Orders: عدد الطلبيات التي استخدمت قسيمة التخفيض. الإجمالي Total: المبلغ الإجمالي للتخفيض الناتج (رقم سالب). تقرير المنتجات التي تمت مشاهدتها Products Viewed Report يُعطي هذا التقرير فكرة عن المنتجات الأكثر مشاهدًة، ويعرض هذا التقرير الأعمدة التالية: اسم المنتج Product Name: اسم المنتج. النوع Model: نوع المنتج. عدد المشاهدات Viewed: عدد المشاهدات الكلي للمنتج. النسبة Percentage: النسبة المئوية لمشاهدات هذا المنتج موازنة مع باقي المنتجات. يؤدي النقر على الزر "استعادة الافتراضي" إلى حذف بيانات هذا التقرير والبدء بإحصاء المشاهدات من جديد. يُمكن الاستفادة من هذا التقرير للتعرف على المنتجات ذات المشاهدات القليلة وبالتالي محاولة رفع مشاهداتها عن طريق الإجابة على الأسئلة التالية: هل تم الإعلان عن هذا المنتج على مواقع أخرى؟ هل تم تضمين صورة المنتج في لافتات المنتج على الصفحة الرئيسية؟ هل تمت إضافة المنتجات إلى المنتجات ذات الصلة بصفحة منتج؟ هل تم منحهم سعرًا مخفضًا خاصًا لمجموعة من العملاء من خلال رسالة إخبارية؟ تقرير المنتجات التي تم شراؤها Products purchased report يُعطي هذا التقرير إجماليات المنتجات المباعة. يُبين التقرير الكمية المباعة من كل منتج والمبالغ الإجمالية الناتجة. يعرض هذا التقرير الأعمدة التالية: اسم المنتج Product Name: اسم المنتج. النوع Model: نوع المنتج. الكمية Qty: العدد المباع. الإجمالي Total: الإجمالي. تقرير المتواجدون الآن Customers Online يسمح هذا التقرير بإعطاء فكرة عن تفاعل العملاء الحالي مع صفحات الموقع إذ يُبين العملاء النشطون حاليًا والصفحات التي يتفاعلون معها. يعرض التقرير الأعمدة التالية: الأي بي - IP: عنوان المستخدم الذي يصل منه للمتجر. العميل Customer: اسم العميل. آخر صفحة تم زيارتها Last Page Visited: آخر صفحة زارها العميل. المرجع Referer: الصفحة السابقة المُزارة. آخر نقرة Last Click: تاريخ وتوقيت آخر نقرة للعميل. ملاحظة: لإظهار هذا التقرير، يجب تحديد "نعم" لحقل "المتواجدون الآن" في تبويب خيارات المتجر (من "الضبط" ثم "الإعدادات" ثم تحرير المتجر). تقرير آخر أحداث العملاء Customer Activity يسمح هذا التقرير بمعاينة نشاطات العملاء إذ يُبين نوع نشاط العميل مع تاريخ تسجيله في الموقع. يعرض التقرير الأعمدة التالية: ملاحظات Comment: نوع نشاط العميل. آي بي IP: عنوان العميل. تاريخ التسجيل Registration date: تاريخ التسجيل. تقرير طلبات العملاء Customer Order Reports يسمح هذا التقرير بمعاينة طلبات العملاء. يُبين التقرير عدد طلبات كل عميل والمبلغ الإجمالي الناتج مما يُعطي فكرة واضحة عن كل عميل. يعرض التقرير الأعمدة التالية: اسم العميل Customer Name: اسم العميل. البريد الالكتروني E-Mail: بريد العميل. مجموعة العميل Customer Group: مجموعة العميل. الحالة Status: حالة العميل (مسموح له الدخول للمتجر). رقم الطلب No. Orders: العدد الكلي للطلبيات. رقم المنتج No. Products: العدد الكلي للمنتجات لطلبيات العميل. الإجمالي Total: المبلغ الإجمالي لطلبيات العميل. تقرير نقاط المكافآت للعملاء Customer Reward Points Report يسمح هذا التقرير بمعاينة نقاط مكافآت العملاء إذ يُبين عدد نقاط المكافآت التي حصل عليها كل عميل، إضافًة إلى عدد طلبياته والإجمالي الناتج. يعرض التقرير الأعمدة التالية: اسم العميل Customer Name: اسم العميل. البريد الالكتروني E-Mail: بريد العميل. مجموعة العميل Customer Group: مجموعة العميل. الحالة Status: حالة العميل (مسموح له الدخول للمتجر). نقاط المكافآت Reward Points: مجموع نقاط المكافآت التي حصل عليها العميل. رقم الطلب No. Orders: العدد الكلي للطلبيات. رقم المنتج No. Products: العدد الكلي للمنتجات لطلبيات العميل. الإجمالي Total: المبلغ الإجمالي لطلبيات العميل. تقرير رصيد العميل Customer Credit Report يسمح هذا التقرير بمعاينة أرصدة العملاء إذ يُبين المبلغ الإجمالي لطلبيات كل عميل. يعرض التقرير الأعمدة التالية: اسم العميل Customer Name: اسم العميل. البريد الالكتروني E-Mail: بريد العميل. مجموعة العميل Customer Group: مجموعة العميل. الحالة Status: حالة العميل (مسموح له الدخول للمتجر). الإجمالي Total: المبلغ الإجمالي لطلبيات العميل. خاتمة عرضنا في هذا الدرس للتقارير الإحصائية التي يوفرها أوبن كارت بشكل افتراضي مما يوفر لمدير النظام جميع الاحصائيات اللازمة لإدارة المتجر واتخاذ القرارات المناسبة. نعرض في الدرس القادم لطرق الدفع والشحن المتوفرة في أوبن كارت. اقرأ أيضًا 12 قاعدة بسيطة لتحسين معدلات التحويل إلى مواقع التجارة الإلكترونية أساسيات تمويل المتاجر الإلكترونية اعتماد المنتج وكيف يمكن تحسينه للزيادة من المبيعات كيف تستخدم المحتوى في زيادة مبيعات تجارتك الإلكترونية
  13. بعد الانتهاء من الإعدادات الأساسية للمتجر التي عرضناها في دروسنا السابقة، فإن أحد أهم الأمور الواجب تتبعها هو مبيعات المتجر. تتسابق المتاجر المتنافسة في سوق التجارة الإلكترونية لإيجاد الطرق المبتكرة لتحسين المبيعات عن طريق تقديم الحسومات التشجيعية أو عن طريق الحملات الترويجية المختلفة. ترتكز الحملات الترويجية على الويب بشكل أساسي على وضع لافتات إعلانية في مواقع مختلفة ومن ثم تتبع المبيعات الناجمة عنها. يُمكن فهم المطلوب من خلال المثال التالي: لنفترض اقتراب تاريخ مناسبة ما وبأننا نريد الترويج لمنتجات معينة من خلال حملة ترويجية في هذه المناسبة، لذا نُصمم مجموعة من اللافتات الإعلانية لوضعها في مجموعة من مواقع التواصل الاجتماعي تناسب تلك المناسبة بالطبع، لن تعرض مواقع الجهات الخارجية اللافتات مجانًا بل سيتعين على المتجر الدفع وفقًا لشروط الموقع. يكون من المهم جدًا تتبع المبيعات الناتجة عن كل لافتة موضوعة في موقع ما لاتخاذ القرار المناسب بمتابعة الإعلان في هذا الموقع أم لا. يساعد متجر أوبن كارت بإضافة ومتابعة حملات التسويق وهذا ما سنعرضه في مقالنا هذا. هذا المقال جزء من سلسلة تعريفية بلوحة تحكم متجر أوبن كارت، إليك فهرس مقالات كامل السلسلة: مدخل إلى متجر أوبن كارت وكيفية تثبيته إدارة الأقسام والمنتجات في متجر أوبن كارت التعرف على إعدادات واجهة متجر أوبن كارت تعلم كيفية ضبط متجر أوبن كارت شرح الإضافات والقوالب في لوحة تحكم متجر أوبن كارت نظرة على خيارات التسويق التي يوفرها متجر أوبن كارت التقارير والإحصائيات: نافذة على أداء متجر أوبن كارت إعدادات الدفع والشحن في متجر أوبن كارت تتبع نظام التسويق يُستحسن عادًة إنشاء حملة تسويقية جديدة عند إضافة لافتة banner إعلانية للمتجر على أي وسيلة تواصل على الويب وتضمين رابط الحملة URL في اللافتة والذي سيُستخدم لتتبع عدد النقرات ومصدرها. مثلًا: لنفرض أن التسويق (الدعاية) سيبدأ على ثلاث منصات مختلفة، يُمكن إنشاء حملة تسويقية لكل منصة (وتضمين الرابط الموافق في كل منها) مما يسمح بمتابعة النقرات التي تأتي من كل منصة. تُميز كل حملة بشيفرة تتبع مختلفة تُضاف إلى نهاية كل رابط للحملة وهو الأمر الذي يسمح بمتابعة كل حملة، ويُمكن فتح صفحة "تتبع نظام التسويق" من الخيار "التسويق" في "لوحة التحكم" ومن ثم "التسويق": تتضمن صفحة "تتبع نظام التسويق" الحقول التالية: اسم الحملة Campaign Name: يجب كتابة اسم للحملة التسويقية. وصف الحملة Campaign Description: يُمكن كتابة وصف للحملة. شفرة التتبع Tracking Code: تولّد هذه الشفرة تلقائيًا، كما يُمكن تعديلها لوضع رقم مخصص أسهل مما يؤدي إلى تعديل الروابط الظاهرة في الحقل "مثال". مثال Example: تظهر روابط الحملة في هذا الحقل (لاحظ انتهاء الروابط بشفرة التتبع). العمولات Affiliates يهدف نظام العمولة إلى زيادة عدد زوار المتجر وذلك عن طريق منح عمولات للعملاء الذين يُساعدون في توجيه الأشخاص الآخرين إلى زيارة المتجر والشراء منه، حيث يُمنح هؤلاء العملاء العمولات المُحدّدة وذلك لكل حركة مبيع ناجمة عن تحويل تنقلات الأشخاص إلى المتجر. يُمكن إنشاء مجموعات مختلفة من العملاء، ويسمح الخيار "العملاء" من لوحة التحكم ثم "مجموعات العملاء" بالانتقال إلى صفحة "مجموعة العميل" والتي تُظهر مجموعة العملاء الافتراضية "عملاء التجزئة": يُمكن مثلًا إنشاء مجموعة عملاء جديدة ("عملاء العمولة"): نُحدّد نسبة العمولة للعملاء من هذه المجموعة من التبويب "خيارات" في صفحة المتجر الحالي والتي نصل إليها من الخيار "الضبط" في لوحة التحكم ثم "الإعدادات" ثم "المتاجر": لإضافة عميل جديد إلى مجموعة عملاء، يجب الانتقال لصفحة "العملاء" من الخيار "العملاء" في لوحة التحكم ثم "العملاء". تحوي صفحة العملاء تبويبين، الأول هو التبويب "عام" والذي يسمح بإدخال بيانات العميل المختلفة: والثاني هو التبويب "نظام العمولة" والذي يسمح بإدخال تفاصيل العمولة والدفع: يُمكن لزوار المتجر طلب أن يكونوا عملاء وذلك من الخيار "نظام العمولة" تحت "إضافات" في الشريط أسفل واجهة المتجر: يؤدي النقر على "نظام العمولة" إلى فتح صفحة "برنامج نظام العمولة": تُشجع هذه الصفحة زوار المتجر على الاشتراك في نظام العمولة لربح إيرادات عن طريق وضعهم روابط لمنتجات المتجر في صفحات الويب المختلفة التي يملكونها، وسيكسب المشتركون العمولة عند قيام أي شخص وصل للمتجر عن طريق هذه الروابط بإتمام عملية شراء من المتجر. يُمكن التسجيل في نظام العمولة بالنقر على الزر "متابعة" في قسم "تسجيل جديد في نظام العمولة": في حال تسجيل الطلب بنجاح، تظهر الرسالة التالية: سيظهر طلب العميل الجديد لمدير النظام في صفحة " عملاء منتظرين موافقة التسجيل" والتي نصل إليها من الخيار "العملاء" في لوحة التحكم ثم "الموافقة للعملاء". يُمكن بالطبع لمدير المتجر أن يوافق أو يحظر العميل كما يُمكن له أن يُعدّل بياناته. ملاحظة: يجب أن يدخل العميل في حسابه إلى "الدخول لبرنامج نظام العمولة" ومن ثم إلى صفحة "شفرة التتبع في نظام العمولة" لمعرفة شفرة التتبع الخاصة به والتي يجب أن يضيفها إلى كل الروابط التي سيضعها (وبهذا يتمكن أوبن كارت من متابعة روابطه): قسائم التخفيض Coupons يُمكن إنشاء قسائم تخفيض وتخصيصها لمنتجات أو أقسام معينة وذلك كنوع من الدعابة والتسويق، ونفعل ذلك من صفحة "قسيمة التخفيض" والتي نصل إليها من خيار "التسويق" في لوحة التحكم ثم "قسائم التخفيض". يحوي التبويب "عام" في صفحة "قسيمة التخفيض" الحقول التالية: اسم القسيمة Coupon Name: يجب إدخال اسم للقسيمة. الرمز Code: يجب إدخال رمز ما، وهو الرمز الذي سيُدخله العميل للحصول على التخفيض. النوع Type: نسبة مئوية أم رقم ثابت. الخصم Discount: قيمة النسبة المئوية أو قيمة مبلغ الخصم. المبلغ الإجمالي Total Amount: يُمكن تحديد مبلغ يجب الوصول إليه في سلة الشراء للاستفادة من الخصم. تسجيل دخول العميل Customer Login: لتحديد هل يجب أن يقوم العميل بتسجيل الدخول للحصول على الخصم أم لا. شحن مجاني Free Shipping: نعم أم لا. المنتجات Products: يُمكن تحديد المنتجات الممكن استخدام قسيمة التخفيض معها. أما إذا ترك هذا الحقل فارغًا يكون التخفيض صالحًا لجميع المنتجات. الأقسام Category: يُمكن اختيار بعض الأقسام ليكون التخفيض متاحًا لمنتجاتها. تاريخ البداية Date Start: تاريخ بداية صلاحية الكوبون. تاريخ النهاية Date End: تاريخ نهاية صلاحية الكوبون. عدد مرات الاستخدام للكوبون Uses per Coupon: يُمكن تحديد عدد معين أو تركه فارغًا ليكون الكوبون صالحًا للاستخدام عدد غير محدود من المرات. عدد مرات الاستخدام للعميل Uses per Customer: يُمكن تحديد عدد معين أو تركه فارغًا ليكون الكوبون صالحًا للاستخدام من قبل نفس العميل عدد غير محدود من المرات. الحالة Status: تعطيل أم تمكين. يحوي التبويب "السجل" Coupon History في صفحة "قسيمة التخفيض" قائمة بجميع استخدامات الكوبون في المتجر تُظهر الحقول التالية: رقم الطلب OrderID العميل Customer المبلغ Amount تاريخ الإضافة DateAdded يجب على مدير النظام تمكين " قسائم التخفيض" في واجهة المتجر وذلك من الخيار "الإضافات" في لوحة التحكم ثم "الإضافات" ثم اختيار من القائمة " اختيار نوع الإضافة " الخيار "إجماليات الطلب" يُمكن للعميل استخدام قسيمة تخفيض من واجهة المتجر وذلك بإدخال رقم قسيمة التخفيض بعد إضافة منتج إلى سلة الشراء: ومن ثم النقر على الزر "اعتمد التخفيض" مما يؤدي إلى تخفيض الإجمالي: البريد Mail تُستخدم هذه الميزة لإرسال رسائل إخبارية أو معلومات عن العروض الخاصة أو لتوصيل أي نوع من معلومات المتجر لمجموعات مختارة من العملاء. يُمكن فتح صفحة "إرسال بريد" من الخيار "التسويق" ثم "إرسال بريد": خاتمة عرضنا في هذا الدرس للإمكانات المختلفة التي يوفرها أوبن كارت من أجل عملية التسويق وتتبع الحملات الترويجية. نعرض في الدرس القادم التقارير الكثيرة التي يوفرها أوبن كارت مما يسمح بالحصول على مختلف المعلومات والإحصائيات المطلوبة لإدارة المتجر. اقرأ أيضًا عناصر التصميم التسويقية التي يحتاجها كل موقع تجارة إلكترونية كيف تزيد مبيعات متجرك اﻹلكتروني باستخدام حملات التسويق بالبريد اﻹلكتروني التسويق والمزيج التسويقي لتوضيح رؤيتك ومهمتك وأهدافك لمحة عامة عن الإعلانات الإلكترونية
  14. يلعب التحريك Animation دورًا كبيرًا في رفع جاذبية تطبيقات ومواقع الويب للمستخدمين الذين أصبحوا يتوقعون دومًا الحصول على واجهات استخدام تفاعلية عالية التجاوب؛ إلا أن تحريك واجهات الاستخدام ليس أمرًا مباشرًا وسهلًا، حيث يستلزم تحديد ما يجب تحريكه وما تأثير هذا التحريك على انطباع وتجربة المستخدمين. يُستخدم التحريك لإضفاء الحياة على المشاريع. يجب أن يدعم التحريك تفاعل المستخدم. يجب الانتباه لتكلفة تحريك الخصائص والتي قد تختلف من خاصيةٍ لأخرى. أساسيات التحريك نعرض فيما يلي أهم القضايا الواجب الانتباه إليها عند التحريك: اختيار الخصائص المناسبة للتحريك يُضيف التحريك كثيرًا من المتعة للمستخدمين ويرفع من تفاعلهم مع المشروع؛ حيث يُمكن عمليًا تحريك أي شيء، مثل العرض والارتفاع والموضع والألوان والخلفيات؛ ولكن يجب الانتباه في نفس الوقت إلى تأثيرات التحريك على الأداء وانعكاساتها على هوية التطبيق، حيث يُمكن أن يؤثر التحريك المتقطع أو المُختار بصورةٍ سيئة على تردِّي تجربة الاستخدام مما يستلزم الانتباه جيدًا إلى حُسن اختيار التحريك المُناسب والفعّال. استخدام التحريك لدعم التفاعل يجب استخدام التحريك بصورةٍ مدروسة بهدف تعزيز تفاعل المستخدمين (وليس فقط لمجرد إمكانية التحريك)، وتجنبًا لمضايقتهم أو إعاقتهم. يُمكن مثلًا استخدام توهجٍ خفيف، أو حركة ارتدادٍ بسيطة لإعلام المستخدم بتلَقّي أفعاله، مثل النقر على أيقونة قائمة، أو السحب لفتح شريط تمرير، أو النقر على زر. يجب تجنُّب التحريك الذي يقطع أو يُعرقل نشاط المستخدم دون أي داعٍ. تجنب تحريك الخصائص المكلفة يُعدّ التحريك الذي يؤدي إلى تقطُّعاتٍ في الصفحة من أسوأ أنواع التحريك، والذي يُحبط المستخدمين ويُشعرهم بعدم الرضا لدرجة أنهم يتمنون بألّا يوجد أي تحريكٍ على الإطلاق. يُمكن أن تكون بعض الخصائص أكثر تكلفةً من غيرها عند تغييرها، كما يُمكن أن يؤدي هذا التغيير إلى ظهور التقطُّعات في الصفحة؛ حيث يُمكن مثلًا أن يتطلب تغيير ظل صندوق box-shadow لعنصرٍ ما عملية طلاء paint أكثر تكلفةً بكثير من تغيير لون نصه. وبالمثل، من المرجح أن يكون تغيير عرض width عنصر ما أكثر تكلفةً من تغيير تحويلاته transform. نعرض المزيد من الإرشادات حول أداء التحريك في الفقرة الأخيرة من هذه المقالة. يُمكن الالتزام فقط بالتحويلات transforms وتعديلات الشفافية opacity واستخدام "سوف يُعدّل" will-change في حال عدم الرغبة بقراءة المزيد والخوض في التفصيلات. يُمكن معرفة ماذا ينشُط تمامًا عند تحريك أي خاصية بالرجوع إلى مُشغّلات أنماط CSS. التحريك باستخدام أنماط CSS موازنة مع استخدام JavaScript يُمكن التحريك، إما باستخدام أنماط CSS، أو JavaScript؛ حيث يعتمد قرار الاختيار بين واحدٍ منهما على الارتباطات الأخرى للمشروع وعلى أنواع التأثيرات المطلوبة. يُستخدم تحريك CSS لتنفيذ الانتقالات البسيطة من النمط "لقطة واحدة one-shot"، مثل تبديل حالات عناصر الواجهة. يُستخدم تحريك JavaScript للحصول على تأثيراتٍ متقدمة، مثل الارتداد أو التوقف أو الإيقاف المؤقت أو الإرجاع أو الإبطاء. يُمكن استخدام واجهة برمجة التطبيقات للتحريك Web Animations API أو أي إطار عمل حديث مناسب عند اختيار التحريك باستخدام JavaScript. يُمكن إنشاء معظم عمليات التحريك الأساسية باستخدام CSS أو JavaScript، لكن يختلف الجهد والزمن اللازمين لإنشاء التحريك حسب الطريقة المختارة (راجع الفقرة الأخيرة من هذه المقالة)؛ حيث يوجد لكل طريقةٍ محاسنها ومساوئها، نعرض فيما يلي الإرشادات العامة: تُستخدم CSS عندما يكون لعناصر الواجهة حالات أقل محتواة ضمن نفس العنصر؛ حيث تكون الانتقالات والتحريك مثالية لجلب قائمة انتقال إلى جهةٍ معينة مثلًا أو إظهار تلميحٍ ما. يُمكن اللجوء إلى JavaScript للتحكم بالحالات إلا أن التحريك نفسه يكون في CSS. تُستخدم JavaScript عند الحاجة للتحكم الواسع في التحريك. تُعدّ واجهة برمجة التطبيقات Web Animations API المنهج المُعتمد على المعايير القياسية والمتاح حاليًا في معظم المتصفحات الحديثة، مما يوفر كائناتٍ حقيقية مثالية للتطبيقات المعقدة الموجهة بالكائنات. تُعدّ JavaScript مفيدةً أيضًا عند الحاجة إلى إيقاف التحريك، أو إيقافه مؤقتًا، أو إبطائه، أو عكسه. يُمكن استخدام إطار التحريك للطلب requestAnimationFrame مباشرًة عند الحاجة لتنسيق مشهدٍ كاملٍ يدويًا. يُعدّ ذلك منهجًا متقدمًا في JavaScript، إلا أنه يكون مفيدًا عند إنشاء لعبة أو الرسم على لوحة HTML canvas. بالمقابل، في حال استخدام إطار عمل JavaScript الذي يتضمن وظائف التحريك، مثل دالة التحريك ‎.animate() في jQuery، فقد يكون من الأنسب الالتزام بذلك في التحريك عمومًا. التحريك باستخدام CSS يُعدّ التحريك باستخدام CSS أبسط طرق تحريك شيءٍ ما على الشاشة، حيث يوصف هذا الأسلوب بأنه تصريحي لأنه يُحدّد ما المطلوب حدوثه. يُبين المثال التالي تحريك صندوقٍ باستخدام CSS بمقدار 100px في كلا المحورين X و Y، حيث ضُبط زمن الانتقال ليأخذ 500 ميلي ثانية (نصف ثانية). تتغير القيمة transform عند إضافة الصف move ويبدأ الانتقال. .box { transform: translate(0, 0); transition: transform 500ms; } .box.move { transform: translate(100px, 100px); } يُمكن تجريب المثال. يوجد إضافًة إلى مدة الانتقال خياراتٍ للتخفيف easing، والتي تُساهم في جعل التحريك يبدو طبيعيًا. يُمكن الرجوع إلى أساسيات التخفيف لمزيدٍ من التفاصيل. في حال إنشاء صفوفٍ مستقلة في CSS لإدارة التحريك كما هو الحال في المثال أعلاه، يُمكن استخدام JavaScript لتبديل حالة التحريك نعم/لا on/off. box.classList.add('move'); يوفِّر ذلك توازنًا جيدًا للتطبيقات؛ إذ يُمكن للمطور التركيز على إدارة الحالة باستخدام JavaScript، وتعيين الصفوف المناسبة للعناصر المستهدفة ببساطة، وترك المتصفح يتعامل مع التحريك. يُمكن في حال اعتماد هذا المنهج الاستماع إلى أحداث نهاية الانتقال transitionend للعنصر، وذلك في حال قبول التخلي عن دعم الإصدارات الأقدم من Internet Explorer، حيث كان الإصدار 10 هو الإصدار الأول لدعم هذه الأحداث. دعمت جميع المتصفحات الأخرى هذه الأحداث منذ فترة. تكون شيفرة JavaScript المطلوبة للاستماع إلى حدث انتهاء الانتقال كما يلي: var box = document.querySelector('.box'); box.addEventListener('transitionend', onTransitionEnd, false); function onTransitionEnd() { //معالجة إنهاء الانتقال } يُمكن استخدام التحريك في CSS إضافًة إلى استخدام الانتقالات للحصول على مزيدٍ من التحكم في الإطارات الرئيسية للتحريك الفردي والمُدّد الزمنية والتكرارات. ملاحظة: يُعدّ الإطار الرئيسي keyframe مصطلحًا قديمًا من مصطلحات الرسوم المتحركة المرسومة يدويًا. يُنشئ رسامو الرسوم المتحركة إطاراتٍ مُحدّدةً لجزءٍ من العمل، تُدعى الإطارات الرئيسية، والتي من شأنها أن تلتقط أشياءً مثل الجزء الأكثر تطرفًا في حركةٍ ما، ثم يشرعون في رسم جميع الإطارات الفردية بين الإطارات الرئيسية. يسلك التحريك في CSS سلوكًا مشابهًا؛ حيث يُعلَم المتصفح ببعض قيم خصائص CSS في نقاط مُحدّدة ويُطلب منه ملء القيم الناقصة. يُمكن مثلًا تحريك صندوق المثال السابق بنفس الطريقة مع انتقالات وبتكرارٍ لا نهائي، ولكن بدون أي تفاعلٍ للمستخدم مثل النقر. كما يُمكن تغيير عدة خصائص في نفس الوقت: .box { /* اختيار التحريك */ animation-name: movingBox; /* مدّة التحريك */ animation-duration: 1300ms; /* عدد مرات التحريك */ animation-iteration-count: infinite; /* تبديل اتجاه التحريك عند كل دورة فردية */ animation-direction: alternate; } @keyframes movingBox { 0% { transform: translate(0, 0); opacity: 0.3; } 25% { opacity: 0.9; } 50% { transform: translate(100px, 100px); opacity: 0.2; } 100% { transform: translate(30px, 30px); opacity: 0.8; } } يُمكن تجريب المثال. يُمكن تعريف التحريك نفسه بصورةٍ مستقلة عن العنصر الهدف، ويُمكن استخدام خاصية اسم التحريك animation-name لاختيار التحريك المطلوب. يجب إضافة بادئات البائع vendor prefixes إذا أردنا أن يعمل تحريك CSS على المتصفحات القديمة. ويُمكن للعديد من الأدوات أن تُساعد في إنشاء إصدارات CSS مع البادئة المطلوبة، مما يسمح للمطوّر بكتابة الإصدار دون البادئات في ملفات المصدر الخاصة به. التحريك باستخدام JavaScript وواجهة برمجة التطبيقات Web Animations API يُعدّ إنشاء التحريك باستخدام JavaScript أكثر تعقيدًا موازنًة مع كتابة الانتقالات أو التحريك في CSS، إلا أنه يوفر قوةً أكبر للمطورين. يُمكن استخدام واجهة برمجة التطبيقات Web Animations API إما لتحريك خصائص CSS معينة، أو لإنشاء كائناتٍ ذات تأثيرات مركبة. يكون استخدام JavaScript للتحريك حتميًا مع كتابة التعليمات سطريًا inline ضمن الشيفرة، كما يُمكن تغليفها داخل كائناتٍ أخرى. تُبيّن الشيفرة التالية كيفية إنشاء نفس تحريك CSS المُوضح في المثال السابق: var target = document.querySelector('.box'); var player = target.animate([ {transform: 'translate(0)'}, {transform: 'translate(100px, 100px)'} ], 500); player.addEventListener('finish', function() { target.style.transform = 'translate(100px, 100px)'; }); تنحصر المهمة الأساسية للتحريك باستخدام Web Animation في تعديل كيفية تقديم وعرض العنصر للمستخدم؛ أما في حال الرغبة ببقاء العنصر في المكان الذي انتقل إليه، فيجب تعديل أنماطه عند انتهاء التحريك كما في المثال السابق. تُعدّ واجهة برمجة التطبيقات Web Animations API معيارًا جديدًا نسبيًا من W3C، وهو مدعومٌ بصورةٍ أساسية في معظم المتصفحات الحديثة؛ أما بالنسبة للمتصفحات الحديثة غير الداعمة، فيُمكن استخدام المشروع من النوع "نقص الدعم" polyfill المُتاح على github؛ وهو مشروع JavaScript يوفر ميزات Web Animation. توفّر JavaScript للمطور تحكمًا كاملًا في أنماط العنصر عند أي خطوة؛ أي أنه يُمكن إبطاء التحريك أو إيقافه مؤقتًا أو توقيفه أو عكسه من خلال التعامل مع العناصر بصورةٍ مناسبة، ويكون هذا مفيدًا جدًا في بناء التطبيقات المعقدة كائنية التوجه؛ حيث يتمكن المطور من تغليف سلوك التحريك بصورةٍ مناسبة. التحريك والأداء يجب الحفاظ على 60 إطارًا في الثانية عند التحريك دومًا؛ حيث تؤدي أي قيمةٍ أقل من ذلك إلى ظهور التقطيع، أو توقُّف التحريك واللذان يكونان واضحين للمستخدمين مما يؤدي إلى تردّي تجربة الاستخدام. يجب الحرص على ألّا يُسبب التحريك أية مشاكل في الأداء؛ حيث يجب معرفة تأثير أي خاصية في أنماط CSS على الأداء. يجب الانتباه إلى أن جميع الخصائص التي تُغيُّر في هندسة الصفحة (التخطيط) أو تتسب في الطلاء تكون مُكلفةً على نحوٍ خاص. يجب الالتزام بتعديل التحويلات والشفافية ما أمكن ذلك. يُمكن استخدام سوف يُعدّل will-change للتأكد من معرفة المتصفح ما يُخطط لتحريكه. لا يكون تحريك الخصائص مجاني، كما أن تحريك بعض الخصائص أقل كلفةً من غيرها؛ حيث يُعدّل مثلًا تحريك العرض width والارتفاع height لعنصرٍ من هندسته، ويُمكن أن يؤدي ذلك إلى تحريك أو تغيير حجوم عناصرٍ أخرى على الصفحة. تُدعى هذه العملية بالتخطيط أو إعادة التدفق في بعض المتصفحات مثل Firefox المعتمدة على محرك المتصفحات Gecko؛ وهي عمليةٌ مكلفةٌ لاسيما إذا احتوت الصفحة على عناصر كثيرة. كلما يُشغّل التخطيط تحتاج الصفحة أو جزءٌ منها إلى إعادة الطلاء والذي يكون أكثر كلفًة من عملية التخطيط نفسها. يجب تجنُّب تحريك الخصائص التي تؤدي إلى تنشيط التخطيط أو الطلاء ما أمكن ذلك؛ وهذا يعني قصر التحريك على الشفافية opacity أو التحويلات transform بالنسبة لمعظم المتصفحات الحديثة، واللتان يتمكن المتصفح من تحسينها بدرجة عالية. لا يُشكّل التعامل مع التحريك باستخدام JavaScript أو CSS فرقًا بالنسبة للأداء. يُمكن الرجوع إلى CSS Triggers للحصول على قائمةٍ كاملة لما يُنشّط تشغيله عند استخدام خصائص CSS الفردية، كما يُمكن الرجوع للمرجع الكامل لإنشاء تحريك عالي الأداء في عناصر HTML5. استخدام خاصية will-change تُعلّم الخاصية will-change المتصفح بالنية في تعديل خاصية عنصر، مما يسمح للمتصفح بوضع التحسينات الأكثر ملاءمةً في مكانها قبل إجراء التعديل. ومع ذلك، لا يجب الإفراط في استخدام الخاصية will-change؛ لأن ذلك يؤدي إلى إضاعة الموارد ومزيدًا من مشاكل الأداء. تنص أحد القواعد التجريبية الأساسية على أنه إذا كان تنشيط التحريك سيبدأ خلال 200 ميلي ثانية القادمة، إما عن طريق تفاعل المستخدم أو بسبب حالة التطبيق، فإن وضع will-change يُعدّ فكرةً جيدة. يجب تمكين will-change في معظم الحالات لكل خاصيةٍ يُخطط لتحريكها لاحقًا. فعلى سبيل المثال، ستكون إضافة will-change للتحويلات والشفافية في أمثلتنا السابقة على النحو التالي: .box { will-change: transform, opacity; } ستُجري المتصفحات التي تدعم هذه الخاصية (حاليًا معظم المتصفحات الحديثة) التحسينات المناسبة في الخلفية لدعم تعديل هذه الخصائص أو تحريكها. أداء CSS موازنة مع أداء JavaScript يوجد العديد من الصفحات والتعليقات في عالم الويب التي تناقش المزايا النسبية للتحريك باستخدام CSS و JavaScript من منظور الأداء. فيما يلي بعض النقاط التي يجب الانتباه لها: يُدعَم التحريك المعتمد على أنماط CSS و Web Animations بصورةٍ أساسية ويُعالج ضمن خيطٍ thread منفصل يُعرف باسم "الخيط المُركَّب compositor thread"؛ والذي يختلف عن "الخيط الرئيسي main thread" للمتصفح، الذي يُنفذّ التصميم والتخطيط والطلاء وسكريبت جافا؛ مما يعني أنه إذا شغَّل المتصفح بعض المهام المكلفة على الخيط الرئيسي، يبقى التحريك مستمرًا دون أي مقاطعة. يُمكن في كثيرٍ من الحالات معالجة التعديلات الأخرى على التحويلات والشفافية باستخدام الخيط المُركّب. إذا أدى أي تحريكٍ إلى تشغيل الطلاء أو التخطيط أو كليهما، فسيُعهد إلى "الخيط الرئيسي" مهمة تنفيذ العمل وذلك في حالة التحريك المُستند إلى CSS أو JavaScript. يُمكن أن يؤدي الحمل الزائد للتخطيط أو الطلاء إلى بطء أي عملٍ مرتبطٍ بتنفيذ CSS أو JavaScript، مما يجعل المسألة موضع نقاش. يُمكن العودة إلى CSS Triggers لمزيدٍ من المعلومات حول العمل المُنّشط عند تحريك خاصيةٍ ما. ترجمة -وبتصرف- للمقالات التالية: Animations للمؤلف: Paul Lewis. CSS Versus JavaScript Animations للمؤلفين: Paul Lewis و Sam Thorogood. Animations and Performance للمؤلفين: Paul Lewis و Sam Thorogood. اقرأ أيضًا أيّهما أفضل للتحريك Animations؟ جافاسكربت أم CSS؟ خاصيات الحركات الحركات المتعددة المتزامنة الانتقالات وجافاسكربت
  15. تُعدّ مسألة تصنيف العملاء أي تجزئتهم إلى مجموعات متشابهة في سلوكها (عمليات الشراء والتسوق) من المسائل الهامة في عالم التسويق وذلك بهدف إعداد حملات تسويقية مختلفة مناسبة لكل مجموعة من المجموعات المُستهدفة. سنعرض في هذه المقالة استخدام خوارزميات العنقدة Clustering لاستكشاف مجموعات العملاء أو الزبائن المختلفة، ويُمكن تنزيل بيانات التدريب والشيفرة البرمجية من الملف المضغوط (والذي تجده أيضًا بنهاية المقال)، لتتمكن من فهم المحتوى أكثر. نستخدم في هذه المقالة التعليمية مجموعة بيانات حول 200 زبون تتألف من عمودين: الدخل السنوي للزبون بآلاف الدولارات Annual Income. تقييم الزبون Spending Score وهو رقم يتراوح بين 1 و 100 ويعكس مدى ولاء الزبون للمتجر والمبالغ التي أنفقها في الشراء منه (100 يعني الزبون الأكثر انفاقًا). يُمكن تنزيل هذه البيانات المتاحة على موقع Kaggle أو من الرابط هنا. ما هي العنقدة Clustering العنقدة هي عملية تجزئة (تقسيم) مجموعة من البيانات إلى عناقيد clusters (مجموعات) وبحيث تكون العناصر الموجودة في عنقود واحد متشابهة فيما بينها وأقل تشابهًا مع عناصر العناقيد الأخرى. تندرج خوارزميات العنقدة ضمن خوارزميات التعلم الآلي المدعوة "ليست تحت الإشراف" unsupervised بمعنى أن البيانات المُقدّمة في البداية لا تحوي أي تسميات labels أو تصنيفات بشكل مُسبق. سنرى مثًلا أن مسألة تحديد عدد العناقيد هو مسألة مهمة يجب الاعتناء بها إذ لا نعرف مُسبقًا ما هو عدد العناقيد الأمثلي. نعرض في هذه المقالة نوعين أساسيين من خوارزميات العنقدة: خوارزميات التجزئة Partitioning: تبدأ هذه الخوارزميات بتجزئة عناصر البيانات إلى k عنقود (مختارة بشكل عشوائي) ومن ثم تُكرر تعديل هذه المجموعات وصولًا إلى حل جيد. من أشهر هذه الخوارزميات الخوارزمية المدعوة k-means (أي k وسطي). الخوارزميات التكتلية Agglomerative: تبني هذه الخوارزمية هرمية من العناقيد حيث تبدأ بوضع كل عنصر من عناصر البيانات في عنقود مستقل ثم تكرر دمج العناقيد المتشابهة وصولًا إلى عنقود واحد في نهاية المطاف. الخوارزمية K-Means تُعدّ الخوارزمية K-Means من أشهر وأبسط خوارزميات العنقدة بالتجزئة: دخل الخوارزمية: عدد العناقيد المطلوب k بيانات التدريب وهي عبارة عن مجموعة من العناصر (أشعة رقمية): {x1, x2, . . . , xN} حيث xi هو شعاع من الأرقام. خرج الخوارزمية: تُسندّ الخوارزمية كل عنصر من عناصر الدخل إلى أحد العناقيد (التي عددها k). المعالجة: تختار الخوارزمية أولًا k شعاع من أشعة الدخل بشكل عشوائي كمراكز العناقيد. تُكرر الخوارزمية ما يلي وصولًا إلى التقارب: إسناد كل شعاع من أشعة الدخل إلى المركز الأقرب حساب المركز الجديد لكل عنقود يعني التقارب عدم انتقال أي شعاع من عنقوده الحالي الموضوع فيه إلى عنقود آخر. يُبين الشكل التالي المراحل الأساسية للخوارزمية: لفهم مراحل الخوارزمية نعرض أولًا خطوات تنفيذها على المثال التعليمي التالي: ليكن لدينا مجموعة العناصر العشرة التالية: D = { (5,3), (10,15), (15,12), (24,10), (30,45), (85,70), (71,80), (60,78), (55,52), (80,91) } وبفرض أننا نريد تقسيمها إلى عنقودين (k=2). لنختار مثلًا العنصر الأول كمركز للعنقود الأول والعنصر الثاني مركزًا للعنقود الثاني أي: c1(x) = 5, c1(y)=3 c2(x) = 10 , c2(y)=15 نحسب الآن بُعد (المسافة الإقليدية euclidean distance) كل عنصر من عناصر البيانات عن كل من المركزين ونُسند العنصر إلى المركز الأقرب. يكون لدينا: table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } رقم العنصر المسافة الإقليدية عن المركز الأول المسافة الإقليدية عن المركز الثاني العنقود المُسند إليه 1 (5,3) 0 13 C1 2 (10,15) 13 0 C2 3 (15,12) 13.45 5.83 C2 4 (24,10) 20.24 14.86 C2 5 (30,45) 48.87 36 C2 6 (85,70) 104.35 93 C2 7 (71,80) 101.41 89 C2 8 (60,78) 93 80 C2 9 (55,52) 70 58 C2 10 (80,91) 115.52 103.32 C2 نحسب الآن مركزي العنقودين فنحصل على: c1(x) = 5, c1(y)=3 c2(x) = (10 + 15 + 24 + 30 + 85 + 71 + 60 + 55 + 80) / 9 = 47.77 c2(y) = (15 + 12 + 10 + 45 + 70 + 80 + 78 + 52 + 91) / 9 = 50.33 نُعيد العملية لنحصل على: رقم العنصر المسافة الإقليدية عن المركز الأول المسافة الإقليدية عن المركز الثاني العنقود المُسند إليه 1 (5,3) 0 63.79 C1 2 (10,15) 13 51.71 C1 3 (15,12) 13.45 50.42 C1 4 (24,10) 20.24 46.81 C1 5 (30,45) 48.87 18.55 C2 6 (85,70) 104.35 42.1 C2 7 (71,80) 101.41 37.68 C2 8 (60,78) 93 30.25 C2 9 (55,52) 70 7.42 C2 10 (80,91) 115.52 51.89 C2 نحسب الآن مركزي العنقودين الجديدين فنحصل على: c1(x) = (5, 10, 15, 24) / 4 = 13.5 c1(y) = (3, 15, 12, 10) / 4 = 10.0 c2(x) = (30 + 85 + 71 + 60 + 55 + 80) / 6 = 63.5 c2(y) = (45 + 70 + 80 + 78 + 52 +91) / 6 = 69.33 نُعيد العملية مرة أخرى لنحصل على: رقم العنصر المسافة الإقليدية عن المركز الأول المسافة الإقليدية عن المركز الثاني العنقود المُسند إليه 1 (5,3) 11.01 88.44 C1 2 (10,15) 6.1 76.24 C1 3 (15,12) 2.5 75.09 C1 4 (24,10) 10.5 71.27 C1 5 (30,45) 38.69 41.4 C1 6 (85,70) 93.33 21.51 C2 7 (71,80) 90.58 13.04 C2 8 (60,78) 82.37 9.34 C2 9 (55,52) 59.04 19.3 C2 10 (80,91) 104.8 27.23 C2 نحسب الآن مركزي العنقودين الجديدين فنحصل على: c1(x) = (5, 10, 15, 24, 30) / 5 = 16.8 c1(y) = (3, 15, 12, 10, 45) / 5 = 17.0 c2(x) = (85 + 71 + 60 + 55 + 80) / 5 = 70.2 c2(y) = (70 + 80 + 78 + 52 + 91) / 5 = 74.2 نُعيد العملية فلا يتغير إسناد أي عنصر مما يعني التقارب وثبات المراكز والعناقيد clusters. دورة الذكاء الاصطناعي احترف برمجة الذكاء الاصطناعي AI وتحليل البيانات وتعلم كافة المعلومات التي تحتاجها لبناء نماذج ذكاء اصطناعي متخصصة. اشترك الآن إعداد المشروع يحتاج تنفذ شيفرات هذه المقالة بيئةً برمجيةً للغة بايثون الإصدار 3.8. ويجب أن تتضمن هذه البيئة البرمجية مدير الحِزم pip لتثبيت الحِزم، ومُنشئ البيئات الافتراضية venv لإنشاء بيئاتٍ افتراضيةٍ. نستخدم محرر الشيفرات البرمجية Jupyter Notebooks، وهو مفيد جدًا لتجربة وتشغيل الأمثلة البرمجية بطريقةٍ تفاعليةٍ، حيث نستطيع من خلاله تشغيل كتلًا صغيرةً من الشيفرات البرمجية ورؤية النتائج بسرعة، مما يُسهّل علينا اختبار الشيفرات البرمجية وتصحيحها. نحتاج أولًا لتثبيت بعض التبعيات، وذلك لإنشاء مساحة عملٍ للاحتفاظ بملفاتنا قبل أن نتمكن من تطوير برنامجنا. نُنشئ مجلدًا جديدًا خاصًا بمشروعنا وندخل إليه هكذا: mkdir clustering cd clustering نُنفذّ الأمر التالي لإنشاء البيئة الافتراضية: python -m venv clustering ومن ثم الأمر التالي في Linux لتنشيط البيئة الافتراضية: source clustering/bin/activate أما في Windows، فيكون أمر التنشيط: "clustering/Scripts/activate.bat" نستخدم إصداراتٍ محددةٍ من المكتبات اللازمة، من خلال إنشاء ملف requirements.txt في مجلد المشروع، وسيُحدِّد هذا الملف المتطلبات والإصدارات التي سنحتاج إليها. نفتح الملف requirements.txt في محرر النصوص، ونُضيف الأسطر التالية، وذلك لتحديد المكتبات التي نريدها وإصداراتها: jupyter==1.0.0 numpy==1.21.5 scikit-learn==1.0.1 scipy==1.7.3 pandas==1.3.5 matplotlib==3.5.1 نحفظ التغييرات التي طرأت على الملف ونخرج من محرر النصوص، ثم نُثَبت هذه المكتبات بالأمر التالي: (clustering) $ pip install -r requirements.txt بعد تثبيتنا لهذه التبعيات، نُصبح جاهزين لبدء العمل على مشروعنا. كتابة شيفرة تطبيق العنقدة للعملاء نُشغّل محرر الشيفرات البرمجية Jupyter Notebook بمجرد اكتمال عملية التثبيت. هكذا: (clustering) $ jupyter notebook ثم نُنشئ ملفًا جديدًا في داخل المحرر ونُسمّه باسم clust مثلًا. تنفيذ المثال التعليمي نبدأ أولًا بإنشاء بيانات المثال التعليمي السابق ورسمها باستخدام المكتبة matplotlib: # المكتبة الرقمية import numpy as np # مكتبة الرسم import matplotlib.pyplot as plt # إنشاء البيانات X = np.array([[5,3], [10,15], [15,12], [24,10], [30,45], [85,70], [71,80], [60,78], [55,52], [80,91],]) # الرسم plt.scatter(X[:,0],X[:,1]) plt.show() مما يُظهر: تُبين الشيفرة التالية استخدام الصف KMeans من مكتبة العنقدة sklearn.cluster. نُنشئ أولًا غرض (نموذج model) من هذا الصف مع تحديد عدد العناقيد المطلوبة. تُنفذّ الطريقة fit خوارزمية KMeans على بيانات التدريب لإيجاد العناقيد المطلوبة. تُرقّم الخوارزمية العناقيد بدءًا من الصفر (تسميات labels). يُمكن طبعًا طباعة مراكز العناقيد. # KMeans from sklearn.cluster import KMeans # إنشاء غرض من الصف # تحديد عدد العناقيد المطلوب kmeans = KMeans(n_clusters=2) # الملائمة مع البيانات kmeans.fit(X) # طباعة المراكز print(kmeans.cluster_centers_) # طباعة تسميات العناقيد print(kmeans.labels_) يكون الخرج: [[70.2 74.2] [16.8 17. ]] [1 1 1 1 1 0 0 0 0 0] يُمكن الآن استخدام النموذج المُتعلم السابق للتنبؤ بعنقود أي مثال جديد وذلك باستخدام الطريقة predict كما تُبين الشيفرة التالية: # التنبؤ print(kmeans.predict([[10,10]])) حيث يكون الخرج مثلًا: [1] يُمكن أيضًا رسم نقاط التدريب مع مراكزها بلون مميز كما تُبين الشيفرة التالية: # الرسم مع المراكز plt.scatter(X[:,0],X[:,1], c=kmeans.labels_, cmap='rainbow') plt.scatter(X[:,0], X[:,1], c=kmeans.labels_, cmap='rainbow') plt.scatter(kmeans.cluster_centers_[:,0] ,kmeans.cluster_centers_[:,1], color='black') يكون الخرج: ننتقل الآن لمعالجة مسألتنا الأساسية وهي عنقدة الزبائن. تعرض الشيفرة التالية تحميل البيانات من الملف shopping-data.csv ووضعها في إطار بيانات من المكتبة pandas. # مكتبة إطار البيانات import pandas as pd # تحميل البيانات customer_data = pd.read_csv('shopping-data.csv') # إظهار ترويسة البيانات customer_data.head() تظهر أوائل البيانات: نحذف في الشيفرة التالية رقم الزبون من إطار البيانات كي لا يدخل في عملية حساب العناقيد. ثم نُنشئ نموذجًا متعلمًا من الصف KMeans مع عدد العناقيد مساويًا لخمسه (نعرض لاحقًا كيفية تحديدنا لهذا الرقم): # حذف رقم الزبون data = customer_data.iloc[:, 1:3].values # إنشاء النموذج المتعلم kmeans = KMeans(n_clusters=5) # الملائمة مع البيانات kmeans.fit(data) # طباعة المراكز print(kmeans.cluster_centers_) # طباعة التسميات print(kmeans.labels_) يكون الإظهار: [[88.2 17.11428571] [55.2962963 49.51851852] [25.72727273 79.36363636] [86.53846154 82.12820513] [26.30434783 20.91304348]] [4 2 4 2 4 2 4 2 4 2 4 2 4 2 4 2 4 2 4 2 4 2 4 2 4 2 4 2 4 2 4 2 4 2 4 2 4 2 4 2 4 2 4 1 4 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 0 3 1 3 0 3 0 3 1 3 0 3 0 3 0 3 0 3 1 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3 0 3] يُمكن الآن أن نرسم النقاط مع المراكز باستخدام الشيفرة التالية: # الرسم plt.scatter(data[:,0],data[:,1], c=kmeans.labels_, cmap='rainbow') plt.scatter(data[:,0], data[:,1], c=kmeans.labels_, cmap='rainbow') plt.scatter(kmeans.cluster_centers_[:,0] ,kmeans.cluster_centers_[:,1], color='black') plt.show() مما يُعطي: تفسير نتائج العنقدة تقييمها يُمكن لنا بمعاينة الشكل السابق استنتاج ما يلي (وهو الهدف الأساسي من عملية العنقدة): الزبائن في أعلى اليمين (نقاط البيانات الصفراء) هم الزبائن ذوو الرواتب المرتفعة والإنفاق المرتفع. هؤلاء هم الزبائن الواجب استهدافهم دومًا والمحافظة عليهم. الزبائن في أعلى اليسار (نقاط البيانات الخضراء) هم الزبائن ذوو الرواتب المنخفضة والإنفاق المرتفع. هؤلاء هم الزبائن الواجب العناية بهم واستهدافهم بحملات التخفيضات مثلًا. الزبائن في أسفل اليمين (نقاط البيانات البنفسجية) هم الزبائن ذوو الرواتب المرتفعة والإنفاق المنخفض. هؤلاء هم الزبائن الواجب جذبهم بالطرق التسويقية ما أمكن ذلك. الزبائن في أسفل اليسار (نقاط البيانات الحمراء) هم الزبائن ذوو الرواتب المنخفضة والإنفاق المنخفض. لا داع لإضاعة الكثير من الوقت والجهد معهم. الزبائن في الوسط (نقاط البيانات الزرقاء) هم الزبائن أصحاب الدخل المتوسط والإنفاق المتوسط. يُمكن استهدافهم أيضًا لاسيما أن عددهم كبيرًا كما يُبين الشكل السابق. يُمكن تقييم نتائج العنقدة باستخدام المعامل المدعو Silhouette Coefficient، ويُحسب هذا المعامل من أجل عنصر بيانات x كما يلي: حيث: a هي وسطي المسافات بين x وبين العناصر الموجودة في نفس العنقود الموجود فيه العنصر x. b هي وسطي المسافات بين x وبين العناصر الموجودة في العناقيد القريبة من عنقود x. كما يُبين الشكل التالي: يُمكن ملاحظة ما يلي حول هذا المعامل: أفضل قيمة له هي 1 وأسوأ قيمة له هي -1. تُشير القيمة 0 إلى وجد تراكب overlapping في العناقيد. تدل القيمة السالبة على وجود العنصر x في عنقود خاطئ إذ يوجد عنقود آخر أقرب إلى x. يكون المعامل silhouette_score لمجموعة من البيانات وسطي قيمة المعامل لكل منها أي: يُمكن تضمين حساب هذا المعامل من sklearn.metrics كما تُبين الشيفرة التالية: from sklearn.metrics import silhouette_score cluster_labels = kmeans.fit_predict(data) # حساب المعامل silhouette_avg = silhouette_score(data, cluster_labels) print(silhouette_avg) يكون لطريقة حساب المعامل silhouette_score معاملي دخل الأول هو البيانات والثاني هو تسميات العناقيد الناتجة عن استدعاء الطريقة fit_predict أولًا. يكون الناتج في مثالنا: 0.553931997444648 إيجاد عدد العناقيد الأمثلي يُمكن استخدام المعامل Silhouette Coefficient لإيجاد عدد العناقيد الأمثلي المناسب لبيانات التدريب وذلك بحساب المعامل مع قيم مختلفة لعدد العناقيد ومن ثم اختيار العدد الذي يُعطي قيمة أعظمية للمعامل كما تُبين الشيفرة التالية: # مجموعة القيم الممكنة range_n_clusters = [2, 3, 4, 5, 6, 7] for n_clusters in range_n_clusters: clusterer = KMeans(n_clusters=n_clusters) cluster_labels = clusterer.fit_predict(data) # حساب المعامل silhouette_avg = silhouette_score(data, cluster_labels) print( "For n =", n_clusters, "silhouette_score is :", silhouette_avg, ) مما يُظهر المعامل من أجل كل قيمة محتملة لعدد العناقيد: For n = 2 silhouette_score is : 0.2968969162503008 For n = 3 silhouette_score is : 0.46761358158775435 For n = 4 silhouette_score is : 0.4931963109249047 For n = 5 silhouette_score is : 0.553931997444648 For n = 6 silhouette_score is : 0.5376203956398481 For n = 7 silhouette_score is : 0.5270287298101395 وبالتالي نلاحظ أن القيمة الأمثلية هي خمسة عناقيد. الخوارزميات التكتلية تمتاز الخوارزميات التكتلية بأنها توفر طريقة معاينة بسيطة لإيجاد عدد العناقيد الأمثلي عن طريق رسم شجرة دمج العناقيد مع بعضها البعض dendrogram: دخل الخوارزمية: بيانات التدريب وهي عبارة عن مجموعة من الأشعة الرقمية: {x1, x2, . . . , xN} حيث xi هو شعاع من الأرقام. خرج الخوارزمية: شجرة دمج العناقيد مع بعضها البعض dendrogram. المعالجة: تبدأ الخوارزمية بوضع كل عنصر من عناصر البيانات في عنقود. تُكرر الخوارزمية ما يلي وصولًا إلى عنقود وحيد: دمج أقرب عنقودين مع بعضهما البعض توجد عدة طرق لإيجاد أقرب عنقودين، من أبسطها الطريقة المسماة بالربط البسيط Single Linkage والتي تحسب المسافة بين عنقودين كما يلي: المسافة بين عنقودين هي أصغر مسافة بين عنصرين من هذين العنقودين. نستخدم فيما يلي الخوارزمية التكتلية مع البيانات التعليمية ومن ثم مع بيانات الزبائن. تعرض الشيفرة التالية طريقة بسيطة لتسمية نقاط البيانات التعليمية (العشرة) لتسهيل عملية المشاهدة والمتابعة: # التسميات : 2,1, ..., 10 labels = range(1, 11) plt.subplots_adjust(bottom=0.1) plt.scatter(X[:,0],X[:,1]) # تسمية النقاط for label, x, y in zip(labels, X[:, 0], X[:, 1]): plt.annotate( label, xy=(x, y), xytext=(-3, 3), textcoords='offset points', ha='right', va='bottom') plt.show() يكون الخرج: نبدأ أولًا بالشيفرة اللازمة لرسم شجرة الدمج dendrogram من أجل إيجاد عدد العناقيد الأمثل: # المكتبات اللازمة from scipy.cluster.hierarchy import dendrogram, linkage # اختيار الربط البسيط linked = linkage(X, 'single') # التسميات: 2,1, .. ,10 labelList = range(1, 11) # dendrogram dendrogram(linked, orientation='top', labels=labelList, distance_sort='descending', show_leaf_counts=True) plt.show() نُعاين شجرة الدمج الناتجة والتي تُبين أن عدد العناقيد المُمكن هو عنقودين: نستدعي الآن الدالة AgglomerativeClustering مع طلب عدد العناقيد مساويًا إلى 2: from sklearn.cluster import AgglomerativeClustering # العنقدة التكتلية cluster = AgglomerativeClustering(n_clusters=2) # الملائمة مع البيانات cluster.fit_predict(X) والتي تُظهر تسميات عنقود كل عنصر: array([1, 1, 1, 1, 0, 0, 0, 0, 0, 0], dtype=int64) يُمكن أيضًا رسم العناقيد: # الرسم plt.scatter(X[:,0],X[:,1], c=cluster.labels_, cmap='rainbow') plt.show() يكون الإظهار: ننتقل الآن إلى مسألة الزبائن باستخدام شيفرة مماثلة: # نوع الربط linked = linkage(data, 'ward') # dendrogram dendrogram(linked, orientation='top', distance_sort='descending', show_leaf_counts=True) # الرسم plt.title("Customer Dendograms") plt.show() يُمكن معاينة شجرة الدمج الناتجة: والتي تُبين أن عدد العناقيد المناسب هو 5. نستدعي الدالة AgglomerativeClustering في الشيفرة التالية: cluster = AgglomerativeClustering(n_clusters=5, affinity='euclidean', linkage='ward') cluster.fit_predict(data) # الرسم plt.scatter(data[:,0], data[:,1], c=cluster.labels_, cmap='rainbow') plt.show() ويكون الخرج: وهو، بالطبع، يُشابه ما حصلنا عليه سابقًا مع الخوارزمية KMeans. الخلاصة عرضنا في هذه المقالة خطوات بناء نموذج تعلّم لعنقدة مجموعة من البيانات مع آليات اختيار عدد العناقيد المناسب للمسألة. يُمكن تجربة المثال كاملًا من موقع Google Colab من الرابط، ولا تنس الاطلاع على ملف بيانات التدريب والشيفرة البرمجية. اقرأ أيضًا تعقيد الخوارزميات Algorithms Complexity أمثلة عن أنواع الخوارزميات مدخل إلى تعلم الآلة (Machine learning) في PHP
  16. يمكن إضافة الكثير من الخدمات والميزات غير الموجودة في متجر أوبن كارت بشكل افتراضي، كما يُمكن تعديل تصميم جميع صفحات المتجر بما يتناسب مع منتجات المتجر. نعرض في هذا الدرس آليات الإضافة وتعديل التصميم باستخدام خياري "الإضافات" و"تصميم" من "لوحة التحكم" للمتجر. هذا المقال جزء من سلسلة تعريفية بلوحة تحكم متجر أوبن كارت، إليك فهرس مقالات كامل السلسلة: مدخل إلى متجر أوبن كارت وكيفية تثبيته إدارة الأقسام والمنتجات في متجر أوبن كارت التعرف على إعدادات واجهة متجر أوبن كارت تعلم كيفية ضبط متجر أوبن كارت شرح الإضافات والقوالب في لوحة تحكم متجر أوبن كارت نظرة على خيارات التسويق التي يوفرها متجر أوبن كارت التقارير والإحصائيات: نافذة على أداء متجر أوبن كارت إعدادات الدفع والشحن في متجر أوبن كارت الإضافات Extensions يُنزّل مع تثبيت أوبن كارت حوالي 26 موديول بشكل افتراضي منها أساسي ومنها إضافي. يختص كل موديول بخدمة (ميزة) معينة في المتجر. يُمكن إضافة الكثير من الخدمات الإضافية المجانية أو المدفوعة (غير الموجودة في أوبن كارت افتراضيًا) للوصول إلى متجر الكتروني متكامل. يحوي خيار "الإضافات" من لوحة التحكم الخيارات الفرعية التالية الموضحة بالصورة: يُمكن الانتقال لصفحة "الإضافات" من خيار "الإضافات" في "لوحة التحكم" ثم "الإضافات"، ومن ثم اختيار "الموديولات" من القائمة "اختيار نوع الإضافة" لتظهر جميع الموديولات المتاحة وفيما إذا كانت معطلة أم لا. مثلًا، يُمكن فتح الموديول: "منتجات مميزة - صفحة البداية" ومسح المنتجات الافتراضية وإدخال أسماء بعض الكتب الجديدة: يؤدي هذا التعديل إلى تعديل المنتجات المُميزة في الصفحة الرئيسية للمتجر والتي تظهر للعملاء: تثبيت/إزالة تنصيب الإضافات تضاف العديد من الإضافات بشكل افتراضي في المتجر إلا أنه لا يُمكن تمكينها قبل القيام بتثبيتها. من الإضافات المهمة "تحليلات جوجل" والذي يُعدّ من أفضل الأدوات لقياس الزيارات على الموقع ومعدلات الدخول والخروج، كما يُحدّد الكلمات البحثية التي يصل بها المستخدمون للمتجر من جوجل ويتتبع عمليات تعامل المستخدمين مع المتجر. إن أردت تثبيت إضافة "تحليلات جوجل" نختارها من القائمة "اختيار نوع الإضافة" ثم ننقر الزر الأخضر "تنصيب" لتثبيت الموديول الموافق: يجب بعدها تحرير الموديول لتمكينه: يجب الحصول على كود تحليلات جوجل من أجل لصقه في الحقل الموافق وذلك من رابط تحليلات جوجل. متجر الإضافات Marketplace يُمكن من الخيار " الإضافات" في "لوحة التحكم" ثم "شراء الإضافات" فتح صفحة "شراء الإضافات": يُمكن استخدام القائمة والأزرار الأربعة (الجميع، مجاني، مدفوع، تم شراؤه) لفلترة الإضافات والوصول للإضافة المطلوبة. مثلًا، تتوفر بعض الإضافات لترجمة صفحات المتجر إلى لغة معينة. بعضها مجاني والبعض الآخر مدفوع، فيمكن انتقاء خيار "اللغات" من القائمة والزر "مدفوع" لمعاينة بعض الإضافات المدفوعة المتعلقة باللغات: يجب تسجيل المتجر قبل تنزيل الإضافات عن طريق فتح الصفحة الرئيسية لأوبن كارت: والتسجيل في الموقع: يجب الدخول بعد التسجيل إلى الرابط "Your Stores": ومن ثم تسجيل بيانات المتجر بالنقر على الزر "ADD STORE": حيث يُطلب إدخال رابط المتجر على الويب: يعد الإرسال SUBMIT، نحصل على معلومات الوصول لواجهة برمجة التطبيقات API: يُمكن معاينة هذه المعلومات بالنقر على زر العين: يُمكن نسخ Copy كلمة السر من الزر الأزرق، ومن ثم العودة إلى صفحة "شراء الإضافات" والنقر على الزر الأحمر أعلى يسار الصفحة لإدخال كلمة السر واسم المستخدم في الحقول الموافقة: مثبت الموديولات Extension Installer تسمح صفحة " مثبت الموديولات" برفع ملف الإضافة الذي حصلنا عليه وتثبيته في الموقع، كما تسمح بمعاينة التثبيتات السابقة وإزالة التثبيت حين الحاجة لذلك: القوالب: تصميم المتجر يُمكن أن يكون التصميم من أهم الأمور في عملية جذب العملاء ولذا يجب إيلائه الاهتمام الكبير. تنزيل قالب تصميم جديد يتحكم أوبن كارت بمظهر المتجر عن طريق مجموعة من القوالب Themes. يُمكن تنزيل قوالب إضافية أخرى من متجر القوالب Theme والذي يوفر مجموعة من الإضافات: يُمكن استعراض القوالب المتوفرة بالنقر على خيار القوالب Themes في قائمة الفئات Category يسار الصفحة، والتي يتوفر البعض منها بشكل مجاني والبعض الآخر بشكل مدفوع. يُمكن اختيار القوالب المجانية بالنقر على الخيار "مجاني" Free أعلى الصفحة، كما يُمكن استخدام قائمة "الترتيب وفق" لاختيار ترتيب ظهور القوالب. انظر مثلًا: يُمكن النقر المزدوج على قالب لمعاينة توافقيته Compatibility مع نسخة أوبن كارت ومعاينة أمثله عن استخدامه: يُمكن تنزيل القالب المطلوب بالنقر على الزر الأخضر "DOWNLOAD" للحصول على ملف مضغوط. تثبيت قالب آليًا يُمكن تثبيت القالب آليًا في أغلب الأحيان (إذا كان اسم الملف المضغوط ينتهي بـ ocmod.zip) وذلك بفتح الصفحة "مثبت الموديولات" من "الإضافات" ثم "مثبت الموديولات" ومن ثم رفع الملف المضغوط: يُمكن تمكين القالب بفتح صفحة "الإضافات" من الخيار "الإضافات" ثم "الإضافات"، ثم نختار من قائمة "نوع الإضافة" خيار القوالب: ثم نحرر القالب الافتراضي ونختار في الحقل "مسار مجلد القالب" اسم القالب الجديد مع "الحالة" تمكين: بعد الانتهاء من هذه الخطوات يُمكن فتح واجهة المتجر ومعاينة القالب الجديد: تعديل تخطيط الصفحات يُمكن تعديل تخطيط الصفحات المختلفة للمتجر، وذلك بفتح الصفحة "صفحات" من الخيار "تصميم" في "لوحة التحكم" ثم "صفحات" لاستعراض صفحات المتجر الممكن تعديل تخطيطها: يمكن مثلًا تغيير تخطيط صفحة البداية الافتراضية التي تظهر للعميل: عن طريق تحرير "صفحة البداية": ومن ثم وضع "أقسام المتجر" في العمود الأيمن لصفحة البداية، وصفحة "حساب العميل" في العمود الأيسر، إضافًة إلى حذف "سلايد شو-صفحة البداية": ستظهر، نتيجة ذلك، صفحة البداية للعميل في واجهة المتجر كما يلي: تعديل القائمة الرئيسية للمتجر تعرض القائمة الرئيسية للمتجر أقسام المنتجات بشكل افتراضي: يُمكن تعديل هذه القائمة: مثلًا: وضع "كتب" لتكون أول عنصر في القائمة وتعديل "ملحقات الأجهزة" إلى "ملحقات" وحذف "مشغلات أم بي ثري". يُمكن القيام بجميع هذه التعديلات من صفحة "الأقسام". لوضع الكتب أول عنصر في القائمة، يجب تعديل قيمة ترتيب الفرز إلى القيمة 0. لتعديل اسم القسم، يُمكن تحرير القسم الموافق وتعديل قيمة الحقل "اسم القسم" في التبويب "بيانات". يُمكن حذف أي قسم بتحديد الصندوق أيمن اسمه في صفحة الأقسام ومن ثم النقر على زر الحذف أعلى يسار الصفحة. بعد إتمام العمليات السابقة، تُصبح القائمة الرئيسية: خاتمة عرضنا في هذا الدرس كيفية إضافة الكثير من الخدمات والميزات غير الموجودة في متجر أوبن كارت بشكل افتراضي، إضافًة إلى إمكانات تعديل تصميم جميع صفحات المتجر بما يتناسب مع منتجات المتجر. ننتقل في الدرس القادم إلى طرق التسويق المتاحة في أوبن كارت. اقرأ أيضًا 10 مجموعات أيقونات مجانية لمواقع التجارة الإلكترونية الدليل الشامل لأشهر أنظمة إنشاء وإدارة المتاجر الإلكترونية كيف تستخدم شركات التجارة الإلكترونية واجهات متعددة لإدارة مجموعات مختلفة من العملاء
  17. تُعدّ مسألة تحليل تعليقات وتغريدات الأشخاص على مواقع التواصل الاجتماعي من المسائل المهمة والتي لها الكثير من التطبيقات العملية. مثلًا: تهتم المتاجر الالكترونية كثيرًا بتحليل تعليقات الزبائن على منتجاتهم لاستكشاف توجهات الزبائن ومواطن الضعف والقوة في المتجر. نعرض في هذه المقالة استخدام تقنيات التعلّم العميق deep learning في تحليل المشاعر لنصوص مكتوبة باللغة العربية وباللهجة السعودية بمعنى أن اللغة المستخدمة ليست بالضرورة اللغة العربية الفصحى، بل يُمكن أن تدخل فيها ألفاظ عامية يستخدمها المغردون عادةً. بيانات التدريب تحوي مجموعة البيانات المتوفرة dataset (التي تجدها أيضًا موضحةً بملف بنهاية المقال) حوالي 23500 تغريدة لتعليقات الأشخاص وملاحظاتهم حول مجموعة من الأماكن العامة في المملكة العربية السعودية. جُمّعت هذه التغريدات عن طريق مجموعة من الطلاب الجامعيين وذلك من مجموعة متنوعة من مواقع التواصل الاجتماعي. نُعطي فيما يلي أمثلة عن هذه التغريدات (تعليقات حول حديقة حيوانات مثلًا): "أنصحكم والله بزيارته مكان جميل جدا مرتب ونظيف" "جميلة وكبيرة وتحتاج واحد عنده لياقه يمشي فيها" "حيوانات قليلة جدا ولا يوجد اهتمام مكثف" "كان يعيبها وقت الافتتاح والاغلاق وعدم وجود خريطه" "أول مرة أزور حديقة حيوانات" "أيام العوائل الخميس والجمعة والسبت" يُمكننا، كبشر، تصنيف التغريدات السابقة وبشكل سريع إلى ثلاث فئات: التغريدات الموجبة (الأولى والثانية) أي التغريدات التي تحمل معاني إيجابية تُعّبر عن الرضا والارتياح. التغريدات السالبة (الثالثة والرابعة) أي التغريدات التي تحمل معاني سلبية تُعبّر عن الاستياء. التغريدات المحايدة (الخامسة والسادسة) أي التغريدات التي يُمكن أن تُعطي معلومات ولا تحمل أية مشاعر فيها سواء موجبة أم سالبة. نعرض في هذه المسألة كيفية بناء مُصنّف حاسوبي آلي يُصنّف أي جملة عربية إلى موجبة أو سالبة أو محايدة. تصنيف بيانات التدريب يتطلب استخدام خوارزميات تعلّم الآلة (خوارزميات تصنيف النصوص في حالتنا) توفر بيانات للتدريب أي مجموعة من النصوص مُصنفّة مُسبقًا إلى: موجبة، سالبة، محايدة. يُمكن، في بعض الأحيان، اللجوء إلى الطرق اليدوية: أي الطلب من مجموعة من الأشخاص قراءة النصوص وتصنيفها. وهو حل يصلح في حال كان عدد النصوص صغيرًا نسبيًا. يتميز هذا الحل بالدقة العالية لأن الأشخاص تُدرك، بشكل عام، معاني النصوص من خلال خبرتها اللغوية المُكتسبة وتُصنّف النصوص بشكل صحيح غالبًا. نستخدم، في حالتنا، حلًا إحصائيًا بسيطًا لتصنيف نصوص التدريب إلى موجبة، سالبة، محايدة وذلك باستخدام قاموس للكلمات الموجبة وقاموس آخر للكلمات السالبة. يحوي قاموس الكلمات الموجبة على مجموعة من الكلمات الموجبة الشائعة مع نقاط لكل كلمة (1 موجبة، 2 موجبة جدًا، 3 موجبة كثيرًا). مثلًا: روعة، 3 جيد، 2 معقول، 1 يحوي قاموس الكلمات السالبة على مجموعة من الكلمات السالبة الشائعة مع نقاط لكل كلمة (-1 سالبة، -2 سالبة جدًا، -3 سالبة كثيرًا). مثلًا: مقرف، -3 سيء، -2 زحمه، -1 اختيرت كلمات القواميس الموجبة والسالبة من قبل مجموعة من الطلاب بعد أنا طلبنا منهم استعراض التغريدات المُتاحة وانتقاء الكلمات التي تُعطي التغريدة معنى موجب أو معنى سالب، وإعطاء كل كلمة موجبة نقاط تدل على شدة الإيجابية لها (1,2,3) وكل كلمة سالبة نقاط تدل على شدة السلبية (-3،-2،-1) نعدّ، فيما يلي، نصًا ما أنه موجبًا إذا كان مجموع نقاط الكلمات الموجبة الواردة ضمن النص أكبر من مجموع نقاط الكلمات السالبة الواردة ضمنه. وبالمقابل، نعدّ نصًا ما أنه سالبًا إذا كان مجموع نقاط الكلمات السالبة الواردة ضمن النص أكبر من مجموع نقاط الكلمات الموجبة الواردة ضمنه. يكون نصًا ما محايدًا إذا تساوى مجموع نقاط الكلمات الموجبة فيه مع مجموع نقاط الكلمات السالبة. بالطبع، لا تُعدّ هذه الطريقة صحيحة دومًا إذ يُمكن أن تُخطئ في بعض الحالات إلا أنها على وجه العموم تُستخدم عوضًا عن الطريقة اليدوية. المعالجة الأولية للنصوص تهدف المعالجة الأولية إلى الحصول على الكلمات المهمة فقط من النصوص وذلك عن طريق تنفيذ بعض العمليات اللغوية عليها. تُنفذّ هذه العمليات على كل من التغريدات وكلمات القواميس. لتكن لدينا مثلًا الجملة التالية: "أنا أحب الذهاب إلى الحديقة، كل يوم 9 صباحاً، مع رفاقي هؤلاء!" سنقوم بتنفيذ العمليات التالية: أولًا، حذف إشارات الترقيم المختلفة كالفواصل وإشارات الاستفهام وغيرها، ويكون ناتج الجملة السابقة: ثانيًا، حذف الأرقام الواردة في النص، فيكون ناتج الجملة السابقة: ثالثًا، حذف كلمات التوقف stop words وهي الكلمات التي تتكرر كثيرًا في النصوص ولا تؤثر في معانيها كأحرف الجر (من، إلى، …) والضمائر (أنا، هو، …) وغيرها، فيكون ناتج الجملة السابقة: رابعًا، تجذيع الكلمات stemming أي إرجاع الكلمات المتشابهة إلى كلمة واحدة (جذع أو جذر) مما يُساهم في إنقاص عدد الكلمات الكلية المختلفة في النصوص، ومطابقة الكلمات المتشابهة مع بعضها البعض. مثلًا: يكون للكلمات الأربع: (رائع، رايع، رائعون، رائعين) نفس الجذع المشترك: (رايع). فيكون ناتج الجملة السابقة: ننتبه إلى أن الجذع يختلف عن الجذر اللغوي إذ الجذر هو عملية لغوية لرد الكلمة إلى أصلها وجذرها الأساسي لأغراض مختلفة أشهرها البحث في القاموس، أما الجذع فهو كلمة مشتركة بين مجموعة من الكلمات لا توجد بالضرورة في قاموس اللغة العربية وإنما إيجاد شكل موحد للكلمات. إعداد المشروع يُمكن تنزيل بيانات التدريب والقواميس والشيفرة البرمجية من الملف المرفق هنا. يحتاج تنفذ شيفرات هذه المقالة بيئةً برمجيةً للغة بايثون الإصدار 3.8. ويجب أن تتضمن هذه البيئة البرمجية مدير الحِزم pip لتثبيت الحِزم، ومُنشئ البيئات الافتراضية venv لإنشاء بيئاتٍ افتراضيةٍ. نستخدم محرر الشيفرات البرمجية Jupyter Notebooks، وهو مفيد جدًا لتجربة وتشغيل الأمثلة الخاصة بتَعَلّم الآلة بطريقةٍ تفاعليةٍ، حيث نستطيع من خلاله تشغيل كتلًا صغيرةً من الشيفرات البرمجية ورؤية النتائج بسرعة، مما يُسهّل علينا اختبار الشيفرات البرمجية وتصحيحها. نحتاج أولًا لتثبيت بعض التبعيات، وذلك لإنشاء مساحة عملٍ للاحتفاظ بملفاتنا قبل أن نتمكن من تطوير برنامجنا. نُنشئ مجلدًا جديدًا خاصًا بمشروعنا وندخل إليه هكذا: mkdir sa cd sa نُنفذّ الأمر التالي لإنشاء البيئة الافتراضية: python -m venv sa ومن ثم الأمر التالي في Linux لتنشيط البيئة الافتراضية: source sa/bin/activate أما في Windows، فيكون أمر التنشيط: "sa/Scripts/activate.bat" نستخدم إصداراتٍ محددةٍ من المكتبات اللازمة، من خلال إنشاء ملف requirements.txt في مجلد المشروع، وسيُحدِّد هذا الملف المتطلبات والإصدارات التي سنحتاج إليها. نفتح الملف requirements.txt في محرر النصوص، ونُضيف الأسطر التالية، وذلك لتحديد المكتبات التي نريدها وإصداراتها: jupyter==1.0.0 keras==2.6.0 Keras-Preprocessing==1.1.2 matplotlib==3.5.1 nltk==3.6.5 numpy==1.19.5 pandas==1.3.5 scikit-learn==1.0.1 seaborn==0.11.2 sklearn==0.0 snowballstemmer==2.2.0 tensorflow==2.6.0 wordcloud==1.8.1 python-bidi==0.4.2 arabic-reshaper==2.1.3 نحفظ التغييرات التي طرأت على الملف ونخرج من محرر النصوص، ثم نُثَبت هذه المكتبات بالأمر التالي: (sa) $ pip install -r requirements.txt بعد تثبيتنا لهذه التبعيات، نُصبح جاهزين لبدء العمل على مشروعنا. كتابة شيفرة برنامج تحليل المشاعر في النصوص العربي نُشغّل محرر الشيفرات البرمجية Jupyter Notebook بمجرد اكتمال عملية التثبيت. هكذا: (sa) $ jupyter notebook ثم نُنشئ ملفًا جديدًا في داخل المحرر ونُسمّه باسم asa مثلًا. يجب أولًا وضع كل من الملفات التالية في مجلد المشروع: ملف التغريدات: tweets.csv. القواميس: lexicon_positive.csv و lexicon_negative.csv. ملف الخط العربي: DroidSansMono.ttf. دورة الذكاء الاصطناعي احترف برمجة الذكاء الاصطناعي AI وتحليل البيانات وتعلم كافة المعلومات التي تحتاجها لبناء نماذج ذكاء اصطناعي متخصصة. اشترك الآن تحميل البيانات نبدأ أولًا بتحميل التغريدات من الملف tweets.csv ضمن إطار من البيانات DataFrame من مكتبة Pandas ومن ثم عرض بعضها: import pandas as pd # قراءة التغريدات وتحميلها ضمن إطار من البيانات tweets_data = pd.read_csv('tweets.csv',encoding = "utf-8") tweets = tweets_data[['tweet']] # إظهار الجزء الأعلى من إطار البيانات tweets.head() يظهر لنا أوائل التغريدات: نُحمّل قاموس الكلمات الموجبة positive.csv وقاموس الكلمات السالبة negative.csv: # قراءة قاموس الكلمات الموجبة positive_data = pd.read_csv('positive.csv' ,encoding = "utf-8") positive = positive_data[['word', 'polarity']] # قراءة قاموس الكلمات السالبة negative_data = pd.read_csv('negative.csv' ,encoding = "utf-8") negative = negative_data[['word', 'polarity']] positive.head() نُظهر مثلًا أوائل الكلمات الموجبة ونقاطها: المعالجة الأولية للنصوص نستخدم فيما يلي بعض الخدمات التي توفرها المكتبة nltk لمعالجة اللغات الطبيعية كتوفير قائمة كلمات التوقف باللغة العربية (حوالي 700 كلمة) واستخراج الوحدات tokens من النصوص. كما نستخدم مجذع الكلمات العربية من مكتبة snowballstemmer. # مكتبة السلاسل النصية import string # مكتبة التعابير النظامية import re # مكتبة معالجة اللغات الطبيعية import nltk nltk.download('punkt') nltk.download('stopwords') # مكتبة كلمات التوقف from nltk.corpus import stopwords # مكتبة استخراج الوحدات from nltk.tokenize import word_tokenize # مكتبة المجذع العربي from snowballstemmer import stemmer ar_stemmer = stemmer("arabic") # دالة حذف المحارف غير اللازمة def remove_chars(text, del_chars): translator = str.maketrans('', '', del_chars) return text.translate(translator) # دالة حذف المحارف المكررة def remove_repeating_char(text): return re.sub(r'(.)\1{2,}', r'\1', text) # دالة تنظيف النصوص def cleaningText(text): # حذف الأرقام text = re.sub(r'[0-9]+', '', text) # حذف المحارف غير اللازمة # علامات الترقيم العربية arabic_punctuations = '''`÷×؛<>_()*&^%][ـ،/:"؟.,'{}~¦+|!”…“–ـ''' # علامات الترقيم الانكليزية english_punctuations = string.punctuation # دمج علامات الترقيم العربية والانكليزية punctuations_list = arabic_punctuations + english_punctuations text = remove_chars(text, punctuations_list) # حذف المحارف المكررة text = remove_repeating_char(text) # استبدال الأسطر الجديدة بفراغات text = text.replace('\n', ' ') # حذف الفراغات الزائدة من اليمين واليسار text = text.strip(' ') return text # دالة تقسيم النص إلى مجموعة من الوحدات def tokenizingText(text): tokens_list = word_tokenize(text) return tokens_list # دالة حذف كلمات التوقف def filteringText(tokens_list): # قائمة كلمات التوقف العربية listStopwords = set(stopwords.words('arabic')) filtered = [] for txt in tokens_list: if txt not in listStopwords: filtered.append(txt) tokens_list = filtered return tokens_list # دالة التجذيع def stemmingText(tokens_list): tokens_list = [ar_stemmer.stemWord(word) for word in tokens_list] return tokens_list # دالة دمج قائمة من الكلمات في جملة def toSentence(words_list): sentence = ' '.join(word for word in words_list) return sentence شرح الدوال التي كتبناها في الشيفرة: cleaningText: تحذف الأرقام وعلامات الترقيم العربية والإنكليزية من النص. remove_repeating_char: تحذف المحارف المكررة والتي قد يستخدمها كاتب التغريدة. tokenizingText: تعمل على تجزئة النص إلى قائمة من الوحدات tokens. filteringText: تحذف كلمات التوقف من قائمة الوحدات. stemmingText: تعمل على تجذيع كلمات قائمة الوحدات المتبقية. يُبين المثال التالي تجذيع بعض الكلمات المتشابهة: # مثال stem = ar_stemmer.stemWord(u"رايع") print (stem) stem = ar_stemmer.stemWord(u"رائع") print (stem) stem = ar_stemmer.stemWord(u"رائعون") print (stem) stem = ar_stemmer.stemWord(u"رائعين") print (stem) يكون ناتج التنفيذ: رايع رايع رايع رايع يُبين المثال التالي نتيجة استدعاء كل دالة من الدوال السابقة: # مثال text= "!أنا أحب الذهاب إلى الحديقة، كل يووووم 9 صباحاً، مع رفاقي هؤلاء " print(text) text=cleaningText(text) print(text) tokens_list=tokenizingText(text) print(tokens_list) tokens_list=filteringText(tokens_list) print(tokens_list) tokens_list=stemmingText(tokens_list) print(tokens_list) يكون ناتج التنفيذ: !أنا أحب الذهاب إلى الحديقة، كل يووووم 9 صباحاً، مع رفاقي هؤلاء أنا أحب الذهاب إلى الحديقة كل يوم صباحاً مع رفاقي هؤلاء ['أنا', 'أحب', 'الذهاب', 'إلى', 'الحديقة', 'كل', 'يوم', 'صباحاً', 'مع', 'رفاقي', 'هؤلاء'] ['أحب', 'الذهاب', 'الحديقة', 'يوم', 'صباحاً', 'رفاقي'] ['احب', 'ذهاب', 'حديق', 'يوم', 'صباح', 'رفاق'] تعرض الشيفرة التالية تنفيذ جميع دوال المعالجة الأولية على نصوص التغريدات ومن ثم حفظ النتائج في ملف جديد tweet_clean.csv. وبنفس الطريقة، نُنفذ دوال المعالجة الأولية على قاموس الكلمات الموجبة وقاموس الكلمات السالبة ونحفظ النتائج في ملفات جديدة لاستخدامها لاحقًا: positive_clean.csv و negative_clean.csv. # المعالجة الأولية للتغريدات tweets['tweet_clean'] = tweets['tweet'].apply(cleaningText) tweets['tweet_preprocessed'] = tweets['tweet_clean'].apply(tokenizingText) tweets['tweet_preprocessed'] = tweets['tweet_preprocessed'].apply(filteringText) tweets['tweet_preprocessed'] = tweets['tweet_preprocessed'].apply(stemmingText) # حذف التغريدات المكررة tweets.drop_duplicates(subset = 'tweet_clean', inplace = True) # التصدير إلى ملف tweets.to_csv(r'tweet_clean.csv',encoding="utf-8", index = False, header = True,index_label=None) # معالجة القاموس الموجب positive['word_clean'] = positive['word'].apply(cleaningText) positive.drop(['word'], axis = 1, inplace = True) positive['word_preprocessed'] = positive['word_clean'].apply(tokenizingText) positive['word_preprocessed'] = positive['word_preprocessed'].apply(filteringText) positive['word_preprocessed'] = positive['word_preprocessed'].apply(stemmingText) # حذف التكرار والخطأ positive.drop_duplicates(subset = 'word_clean', inplace = True) nan_value = float("NaN") positive.replace("", nan_value, inplace=True) positive.dropna(subset= ['word_clean'], inplace=True) # التصدير إلى ملف positive.to_csv(r'positive_clean.csv',encoding="utf-8", index = False, header = True,index_label=None) # معالجة القاموس السالب negative['word_clean'] = negative['word'].apply(cleaningText) negative.drop(['word'], axis = 1, inplace = True) negative['word_preprocessed'] = negative['word_clean'].apply(tokenizingText) negative['word_preprocessed'] = negative['word_preprocessed'].apply(filteringText) negative['word_preprocessed'] = negative['word_preprocessed'].apply(stemmingText) # حذف التكرار والخطأ negative.drop_duplicates(subset = 'word_clean', inplace = True) negative.replace("", nan_value, inplace=True) negative.dropna(subset= ['word_clean'], inplace=True) # التصدير إلى ملف negative.to_csv(r'negative_clean.csv', encoding="utf-8", index = False, header = True,index_label=None) تعرض الشيفرة التالية بناء قاموسين dict الأول للكلمات الموجبة والثاني للكلمات السالبة وبحيث يكون المفتاح key هو الكلمة والقيمة value هي نقاط الكلمة. يُعدّ استخدام بنية القاموس dict في بايثون مفيدًا جدًا للوصول المباشر إلى نقاط أي كلمة دون القيام بأي عملية بحث. لاحظ أننا نقرأ الكلمات الموجبة والسالبة من الملفات الجديدة ناتج المعالجة الأولية لملفات الكلمات الأصلية. # التصريح عن قاموس للكلمات الموجية dict_positive = dict() # بناء قاموس الكلمات الموجبة myfile = 'positive_clean.csv' positive_data = pd.read_csv(myfile, encoding='utf-8') positive = positive_data[['word_clean', 'polarity']] for i in range(len(positive)): dict_positive[positive_data['word_clean'][i].strip()] = int(positive_data['polarity'][i]) # التصريح عن قاموس للكلمات السالبة dict_negative = dict() # بناء قاموس الكلمات السالبة myfile = 'negative_clean.csv' negative_data = pd.read_csv(myfile, encoding='utf-8') negative = negative_data[['word_clean', 'polarity']] for i in range(len(negative)): dict_negative[negative_data['word_clean'][i].strip()] = int(negative_data['polarity'][i]) تقوم الدالة التالية sentiment_analysis_dict_arabic بحساب مجموع نقاط score قائمة من الكلمات وذلك بجمع نقاط الكلمات الواردة في قاموسي الكلمات الموجبة والسالبة. وفي النهاية تُعدّ قطبية polarity قائمة الكلمات موجبة positive إذا كان مجموع نقاطها أكبر من الصفر، وتُعدّ سالبة negative إذا كان مجموع نقاطها أصغر من الصفر، وإلا فإنها تكون محايدة neutral. # دالة حساب قطبية قائمة من الكلمات def sentiment_analysis_dict_arabic(words_list): score = 0 for word in words_list: if (word in dict_positive): score = score + dict_positive[word] for word in words_list: if (word in dict_negative): score = score + dict_negative[word] polarity='' if (score > 0): polarity = 'positive' elif (score < 0): polarity = 'negative' else: polarity = 'neutral' return score, polarity نستخدم الدالة السابقة في حساب قطبية كل تغريدة وذلك بتنفيذ الدالة على قائمة الكلمات التي حصلنا عليها بعد المعالجة الأولية لنص التغريدة tweet_preprocessed. أي أنه سيكون لكل تغريدة في نهاية المطاف قطبية polarity موجبة أو سالبة أو محايدة وفق مجموع النقاط الحاصلة عليها polarity_score. نحفظ نتائج الحساب في ملف جديد tweets_clean_polarity.csv. # حساب قطبية التغريدات results = tweets['tweet_preprocessed'].apply(sentiment_analysis_dict_arabic) results = list(zip(*results)) tweets['polarity_score'] = results[0] tweets['polarity'] = results[1] # كتابة النتائج في ملف tweets.to_csv(r'tweets_clean_polarity.csv', encoding='utf-8', index = False, header = True,index_label=None) تعرض الشيفرة التالية حساب عدد التغريدات من كل قطبية (موجبة، سالبة، محايدة) ومن ثم استخدام المكتبة matplotlib لرسم مخطط بياني من النوع pie يعرض نسب قطبية التغريدات: # رسم نسب قطبية التغريدات import matplotlib.pyplot as plt fig, ax = plt.subplots(figsize = (6, 6)) # حساب عدد التغريدات من كل قطبية x = [count for count in tweets['polarity'].value_counts()] # تسميات الرسم labels = list(tweets['polarity'].value_counts().index) explode = (0.1, 0, 0) # تنفيذ الرسم ax.pie(x = x, labels = labels, autopct = '%1.1f%%', explode = explode, textprops={'fontsize': 14}) # عنوان الرسم ax.set_title('Tweets Polarities ', fontsize = 16, pad = 20) # الإظهار plt.show() يكون الإظهار: يُمكن الآن إظهار التغريدات الأكثر إيجابيًة باستخدام الشيفرة التالية: # طباعة أكثر التغريدات إيجابية pd.set_option('display.max_colwidth', 3000) positive_tweets = tweets[tweets['polarity'] == 'positive'] positive_tweets = positive_tweets[['tweet_clean', 'polarity_score', 'polarity']].sort_values(by = 'polarity_score', ascending=False).reset_index(drop = True) positive_tweets.index += 1 positive_tweets[0:10] يكون الإظهار: كما يُمكن إظهار التغريدات الأكثر سلبيًة: # طباعة أكثر التغريدات سلبية pd.set_option('display.max_colwidth', 3000) negative_tweets = tweets[tweets['polarity'] == 'negative'] negative_tweets = negative_tweets[['tweet_clean', 'polarity_score', 'polarity']].sort_values(by = 'polarity_score', ascending=True)[0:10].reset_index(drop = True) negative_tweets.index += 1 negative_tweets[0:10] يكون الإظهار: يُمكن استخدام مكتبة سحابة الكلمات WordCloud لرسم مجموعة من الكلمات بشكل فني كما تُبين الشيفرة التالية: # سحابة الكلمات from wordcloud import WordCloud # مكتبة للغة العربية import arabic_reshaper from bidi.algorithm import get_display # انتقاء بعض الكلمات المعالجة list_words='' i=0 for tweet in tweets['tweet_preprocessed']: for word in tweet: i=i+1 if i>100: break list_words += ' '+(word) # ضبط اللغة العربية reshaped_text = arabic_reshaper.reshape(list_words) artext = get_display(reshaped_text) # إعدادات سحابة الكلمات wordcloud = WordCloud(font_path='DroidSansMono.ttf', width = 600, height = 400, background_color = 'black', min_font_size = 10).generate(artext) fig, ax = plt.subplots(figsize = (8, 6)) # عنوان السحابة ax.set_title('Word Cloud of Tweets', fontsize = 18) ax.grid(False) ax.imshow((wordcloud)) fig.tight_layout(pad=0) ax.axis('off') plt.show() يكون الإظهار: تُجمّع الدالة التالية words_with_sentiment الكلمات الموجبة والكلمات السالبة المستخرجة من قائمة الكلمات المُمررة للدالة list_words في قائمتين منفصلتين الأولى للكلمات الموجبة والثانية للكلمات السالبة. تستخدم الدالة قاموسي الكلمات الموجبة والسالبة السابقين. # تجميع الكلمات الموجبة والكلمات السالبة def words_with_sentiment(list_words): positive_words=[] negative_words=[] for word in list_words: score_pos = 0 score_neg = 0 if (word in dict_positive): score_pos = dict_positive[word] if (word in dict_negative): score_neg = dict_negative[word] if (score_pos + score_neg > 0): positive_words.append(word) elif (score_pos + score_neg < 0): negative_words.append(word) return positive_words, negative_words نستخدم الدالة السابقة في الشيفرة التالية لاستخراج قائمة الكلمات الموجبة وقائمة الكلمات السالبة من التغريدات، ومن ثم إنشاء سحابتي كلمات لكل منهما لعرض الكلمات الموجبة والكلمات السالبة بشكل فني: # سحابة الكلمات الموجبة والسالبة # فرز الكلمات الموجبة والسالبة sentiment_words = tweets['tweet_preprocessed'].apply(words_with_sentiment) sentiment_words = list(zip(*sentiment_words)) # قائمة الكلمات الموجبة positive_words = sentiment_words[0] # قائمة الكلمات السالبة negative_words = sentiment_words[1] # سحابة الكلمات الموجبة fig, ax = plt.subplots(1, 2,figsize = (12, 10)) list_words_postive='' for row_word in positive_words: for word in row_word: list_words_postive += ' '+(word) reshaped_text = arabic_reshaper.reshape(list_words_postive) artext = get_display(reshaped_text) wordcloud_positive = WordCloud(font_path='DroidSansMono.ttf',width = 800, height = 600, background_color = 'black', colormap = 'Greens' , min_font_size = 10).generate(artext) ax[0].set_title(' Positive Words', fontsize = 14) ax[0].grid(False) ax[0].imshow((wordcloud_positive)) fig.tight_layout(pad=0) ax[0].axis('off') # سحابة الكلمات السالبة list_words_negative='' for row_word in negative_words: for word in row_word: list_words_negative += ' '+(word) reshaped_text = arabic_reshaper.reshape(list_words_negative) artext = get_display(reshaped_text) wordcloud_negative = WordCloud(font_path='DroidSansMono.ttf',width = 800, height = 600, background_color = 'black', colormap = 'Reds' , min_font_size = 10).generate(artext) ax[1].set_title('Negative Words', fontsize = 14) ax[1].grid(False) ax[1].imshow((wordcloud_negative)) fig.tight_layout(pad=0) ax[1].axis('off') plt.show() يكون الإظهار: تحويل النصوص إلى أشعة رقمية لا تقبل بنى تعلم الآلة النصوص كمدخلات لها، بل تحتاج إلى أشعة رقمية كمدخلات، لذا نستخدم الشيفرة التالية لتحويل الشعاع النصي لكل تغريده tweet_preprocessed إلى شعاع رقمي: # تحويل التغريدات إلى أشعة رقمية from keras.preprocessing.text import Tokenizer from keras.preprocessing.sequence import pad_sequences # تركيب جمل التغريدات من المفردات المعالجة sentences = tweets['tweet_preprocessed'].apply(toSentence) print(sentences.values[25]) max_words = 5000 max_len = 50 # التصريح عن المجزئ # مع تحديد عدد الكلمات التي ستبقى # بالاعتماد على تواترها tokenizer = Tokenizer(num_words=max_words ) # ملائمة المجزئ لنصوص التغريدات tokenizer.fit_on_texts(sentences.values) # تحويل النص إلى قائمة من الأرقام S = tokenizer.texts_to_sequences(sentences.values) print(S[0]) # توحيد أطوال الأشعة X = pad_sequences(S, maxlen=max_len) print(X[0]) X.shape نقاط في الشيفرة السابقة لشرحها: يُحدّد المتغير max_words عدد الكلمات الأعظمي التي سيتم الاحتفاظ بها حيث يُحسب تواتر كل كلمة في كل النصوص ومن ثم تُرتب حسب تواترها (المرتبة الأولى للكلمة ذات التواتر الأكبر). ستُهمل الكلمات ذات المرتبة أكبر من max_words. يُحدّد المتغير max_len طول الشعاع الرقمي النهائي. إذا كان طول الشعاع الرقمي الموافق لنص أقل من max_len تُضاف أصفار للشعاع حتى يُصبح طوله مساويًا إلى max_len. أما إذا كان طوله أكبر يُقتطع جزءًا منه ليُصبح طوله مساويًا إلى max_len. تقوم الدالة fit_on_texts(sentences.values)‎ بملائمة المُجزء tokenizer لنصوص جمل التغريدات أي حساب تواتر الكلمات والاحتفاظ بالكلمات ذات التواتر أكبر أو يساوي max_words. نطبع في الشيفرة السابقة، بهدف التوضيح، ناتج كل مرحلة. اخترنا مثلًا شعاع التغريدة 25 بعد المعالجة: [مكان جميل انصح زيار رسوم دخول] تكون نتيجة تحويل الشعاع السابق النصي إلى شعاع من الأرقام: [246, 1401, 467, 19, 87, 17, 74, 515, 2602, 330, 218, 579, 507, 465, 270, 45, 54, 343, 587, 7, 33, 58, 434, 30, 74, 144, 233, 451, 468] وبعد عملية توحيد الطول يكون الشعاع الرقمي النهائي الناتج: [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 246 1401 467 19 87 17 74 515 2602 330 218 579 507 465 270 45 54 343 587 7 33 58 434 30 74 144 233 451 468] تجهيز دخل وخرج الشبكة العصبية تعرض الشيفرة التالية حساب شعاع الخرج أولًا، حيث نقوم بترميز القطبيات الثلاث إلى 0 للسالبة و1 للمحايدة و2 للموجبة. نستخدم الدالة train_test_split لتقسيم البيانات المتاحة إلى 80% منها لعملية التدريب و20% لعملية الاختبار وحساب مقاييس الأداء: # ترميز الخرج polarity_encode = {'negative' : 0, 'neutral' : 1, 'positive' : 2} # توليد شعاع الخرج y = tweets['polarity'].map(polarity_encode).values # مكنبة تقسيم البيانات إلى تدريب واختبار from sklearn.model_selection import train_test_split # تقسيم البيانات إلى تدريب واختبار X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0) print(X_train.shape, y_train.shape) print(X_test.shape, y_test.shape) نطبع في الشيفرة السابقة حجوم أشعة الدخل والخرج للتدريب وللاختبار: (16428, 50) (16428,) (4107, 50) (4107,) نموذج الشبكة العصبية المتعلم تُعدّ المكتبة Keras من أهم مكتبات بايثون التي توفر بناء شبكات عصبية لمسائل التعلم الآلي. تعرض الشيفرة التالية التصريح عن دالة بناء نموذج التعلّم create_model مع إعطاء جميع المعاملات المترفعة قيمًا ابتدائية: # تضمين النموذج التسلسلي from keras.models import Sequential # تضمين الطبقات اللازمة from keras.layers import Embedding, Dense, LSTM # دوال التحسين from tensorflow.keras.optimizers import Adam, RMSprop # التصريح عن دالة إنشاء نموذج التعلم # مع إعطاء قيم أولية للمعاملات المترفعة def create_model(embed_dim = 32, hidden_unit = 16, dropout_rate = 0.2, optimizers = RMSprop, learning_rate = 0.001): # التصريح عن نموذج تسلسلي model = Sequential() # طبقة التضمين model.add(Embedding(input_dim = max_words, output_dim = embed_dim, input_length = max_len)) # LSTM model.add(LSTM(units = hidden_unit ,dropout=dropout_rate)) # الطبقة الأخيرة model.add(Dense(units = 3, activation = 'softmax')) # بناء النموذج model.compile(loss = 'sparse_categorical_crossentropy', optimizer = optimizers(learning_rate = learning_rate), metrics = ['accuracy']) # طباعة ملخص النموذج print(model.summary()) return model نستخدم من أجل مسألتنا نموذج شبكة عصبية تسلسلي يتألف من ثلاث طبقات: الطبقة الأولى: طبقة التضمين Embedding نستخدم هذه الطبقة لتوليد ترميز مكثف للكلمات dense word encoding مما يُساهم في تحسين عملية التعلم. نطلب تحويل الشعاع الذي طوله input_length (في حالتنا 50) والذي يحوي قيم ضمن المجال input_dim (من 1 إلى 5000 في مثالنا) إلى شعاع من القيم ضمن المجال output_dim (مثلًا 32 قيمة). الطبقة الثانية LSTM يُحدّد المعامل المترفع units عدد الوحدات المخفية لهذه الطبقة. يُساهم المعامل dropout في معايرة الشبكة خلال التدريب حيث يقوم بإيقاف تشغيل الوحدات المخفية بشكل عشوائي أثناء التدريب، وبهذه الطريقة لا تعتمد الشبكة بنسبة 100٪ على جميع الخلايا العصبية الخاصة بها، وبدلاً من ذلك، تُجبر نفسها على العثور على أنماط أكثر أهمية في البيانات من أجل زيادة المقياس الذي تحاول تحسينه (الدقة مثلًا). الطبقة الثالثة Dense يُحدّد المعامل units حجم الخرج لهذه الطبقة (3 في حالتنا: 0 سالبة، 1 محايدة، 2 موجبة) ويُبين الشكل التالي ملخص النموذج: معايرة المعاملات الفائقة وصولا لنموذج أمثلي يُمكن الوصول لنموذج تعلم أمثلي بمعايرة معاملاته الفائقة وفق معطيات المشروع. لنُبين أولًا الفرق بين المعاملات الفائقة لنموذج والمعاملات الأخرى له: المعاملات الفائقة hyperparameters: هي إعدادات خوارزمية التعلّم قبل التدريب (والتي وضعها مصممو الخوارزمية) . المعاملات parameters: هي المعاملات التي يتعلّمها النموذج أثناء التدريب مثل أوزان الشبكة العصبية. تؤثر عملية معايرة المعاملات الفائقة على أداء النموذج لاسيما لجهة التوزان المطلوب بين مشكلة قلة التخصيص underfitting ومشكلة فرط التخصيص overfitting واللتان تؤديان إلى نموذج غير قادر على تعميم أمثلة التدريب وبالتالي لن يتمكن من التصنيف مع معطيات جديدة (يُمكن العودة للرابط من أكاديمية حسوب للمزيد من التفصيل حول هاتين المشكلتين). تظهر مشكلة قلة التخصيص عندما لا يكون للنموذج درجات حرية كافية ليتعلّم الربط بين الميزات والهدف، وبالتالي يكون له انحياز كبير نحو قيم معينة للهدف. يُمكن تصحيح قلة التخصيص بجعل النموذج أكثر تعقيدًا. أما مشكلة فرط التخصيص فتظهر عندما يقوم النموذج بتخزين بيانات التدريب فيكون له بالتالي تباين كبير والذي يُمكن تصحيحه بالحد من تعقيد النموذج باستخدام التسوية regularization. تكمن المشكلة في معايرة المعاملات الفائقة بأن قيمها المثلى تختلف من مسألة لأخرى! وبالتالي، فإن الطريقة الوحيدة للوصول لهذه القيم المثلى هي تجريب قيم مختلفة مع كل مجموعة بيانات تدريب جديدة. يوفر Scikit-Learn العديد من الطرق لتقويم المعاملات الفائقة وبالتالي سنعتمد في مشروعنا عليها دون أن نُعقّد الأمور أكثر. البحث الشبكي مع التقييم المتقاطع تُدعى الطريقة التي سنستخدمها في إيجاد القيم المثلى بالبحث الشبكي مع التقويم المتقاطع grid search with cross validation: البحث الشبكي grid search: نُعرّف شبكة grid من بعض القيم المُمكنة ومن ثم نولد كل التركيبات المُمكنة بينها. التقييم المتقاطع cross validation: وهو الطريقة المستخدمة لتقييم مجموعة قيم مُحدّدة للمعاملات الفائقة. عوضًا عن تقسيم البيانات إلى بيانات للتدريب وبيانات للتقييم مما يُخفّض من البيانات التي يُمكن لنا استخدامها للتدريب، نستخدم التقييم المتقاطع مع عدد محدّد من الحاويات K-Fold. تُقسم بيانات التدريب إلى عدد K من الحاويات ومن ثم نقوم بتكرار ما يلي K مرة: في كل مرة نقوم بتدريب النموذج مع بيانات K-1 حاوية ومن ثم تقويمه مع بيانات الحاوية K. في النهاية، يكون مقياس الأداء النهائي هو متوسط الخطأ لكل التكرارات. يُمكن تلخيص خطوات البحث الشبكي مع التقييم المتقاطع كما يلي: إعداد شبكة من المعاملات الفائقة. توليد كل تركيبات قيم المعاملات الفائقة. إنشاء نموذج لكل تركيب من القيم. تقييم النموذج باستخدام التقويم المتقاطع. اختيار تركيب قيم المعاملات ذو الأداء الأفضل. بالطبع، لن نقوم ببرمجة هذه الخطوات لأن الكائن GridSearchCV في Scikit-Learn يقوم بكل ذلك (يجب ملاحظة أن تنفيذ الشيفرة قد يستغرق بعض الوقت: حوالي الساعة على حاسوب ذو مواصفات عالية): from sklearn.model_selection import GridSearchCV from keras.wrappers.scikit_learn import KerasClassifier # حساب القيم الأمثلية للمعاملات المترفعة model = KerasClassifier(build_fn = create_model, epochs = 25, batch_size=128) # بعض القيم الممكنة للمعاملات المترفعة embed_dim = [32, 64] hidden_unit = [16, 32, 64] dropout_rate = [0.2] optimizers = [Adam, RMSprop] learning_rate = [0.01, 0.001, 0.0001] epochs = [10, 15, 25 ] batch_size = [128, 256] param_grid = dict(embed_dim = embed_dim, hidden_unit = hidden_unit, dropout_rate = dropout_rate, learning_rate = learning_rate, optimizers = optimizers, epochs = epochs, batch_size = batch_size) # تقويم النموذج لاختيار أفضل القيم grid = GridSearchCV(estimator = model, param_grid = param_grid, cv = 3) grid_result = grid.fit(X_train, y_train) results = pd.DataFrame() results['means'] = grid_result.cv_results_['mean_test_score'] results['stds'] = grid_result.cv_results_['std_test_score'] results['params'] = grid_result.cv_results_['params'] print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_)) # حفظ النتائج results.to_csv(r'gridsearchcv_results.csv', index = False, header = True) results.sort_values(by='means', ascending = False).reset_index(drop=True) يُبين خرج الشيفرة السابقة أفضل القيم للمعاملات المترفعة: Best: 0.898588 using {'batch_size': 256, 'dropout_rate': 0.2, 'embed_dim': 32, 'epochs': 10, 'hidden_unit': 64, 'learning_rate': 0.001, 'optimizers': <class 'keras.optimizer_v2.adam.Adam'>} نحفظ نتائج حساب المعاملات الأمثلية في الملف gridsearchcv_results.csv. يُمكن معاينة هذه القيم: # قراءة نتائج معايرة المعاملات المترفعة results = pd.read_csv('gridsearchcv_results.csv') results.sort_values(by='means', ascending = False).reset_index(drop=True) print (results) يكون الخرج: حساب أوزان الصفوف يُمكن أن نلاحظ أن عدد التغريدات ذات القطبية الموجبة (73% من التغريدات) تطغى على عدد التغريدات السلبية (13%) والتغريدات المحايدة (13%) مما قد يؤدي إلى انحراف نتائج التعلم نحو القطبية الموجبة. يُمكن تلافي ذلك عن طريق الموازنة بين هذه الصفوف الثلاثة. نحسب في الشيفرة التالية عدد التغريدات الموجبة والسالبة والمحايدة ونسبها: # حساب أوزان القطبيات posCount=0 negCount=0 neuCount=0 # حساب عدد التغريدات الموجبة والسالبة والمحايدة for index, row in tweets.iterrows(): if row['polarity']=='negative': negCount=negCount+1 elif row['polarity']=='positive': posCount=posCount+1 else: neuCount=neuCount+1 print(negCount, neuCount, posCount) total=posCount+ negCount+ neuCount # حساب النسب weight_for_0 = (1 / negCount) * (total / 3.0) weight_for_1 = (1 / neuCount) * (total / 3.0) weight_for_2 = (1 / posCount) * (total / 3.0) print(weight_for_0, weight_for_1, weight_for_2) class_weight = {0: weight_for_0, 1: weight_for_1, 2:weight_for_2} يكون ناتج طباعة هذه الأوزان ما يلي (لا حظ الوزن الأصغر للتغريدات الموجبة): 2.4954429456799123 2.504573728503476 0.45454545454545453 بناء نموذج التعلم النهائي نستخدم الدالة KerasClassifier من scikit لبناء المُصنف مع الدالة السابقة create_model : # مكتبة التصنيف from keras.wrappers.scikit_learn import KerasClassifier # إنشاء النموذج مع قيم المعاملات المترفعة الأمثلية model = KerasClassifier(build_fn = create_model, # معاملات النموذج dropout_rate = 0.2, embed_dim = 32, hidden_unit = 64, optimizers = Adam, learning_rate = 0.001, # معاملات التدريب epochs=10, batch_size=256, # نسبة بيانات التقييم validation_split = 0.1) # ملائمة النموذج مع بيانات التدريب # مع موازنة الصفوف الثلاثة model_prediction = model.fit(X_train, y_train, class_weight=class_weight) يُمكن الآن رسم منحني الدقة accuracy لكل من بيانات التدريب والتقييم (لاحظ أننا في الشيفرة السابقة احتفاظنا بنسبة 10% من بيانات التدريب للتقييم): # معاينة دقة النموذج # التدريب والتقييم fig, ax = plt.subplots(figsize = (10, 4)) ax.plot(model_prediction.history['accuracy'], label = 'train accuracy') ax.plot(model_prediction.history['val_accuracy'], label = 'val accuracy') ax.set_title('Model Accuracy') ax.set_xlabel('Epoch') ax.set_ylabel('Accuracy') ax.legend(loc = 'upper left') plt.show() يكون للمنحني الشكل التالي: حساب مقاييس الأداء يُمكن الآن حساب مقاييس الأداء المعروفة في مسائل التصنيف (الصحة Accuracy، الدقة Precision، الاستذكار Recall، المقياس F1) للنموذج المتعلم باستخدام الشيفرة التالية: # مقاييس الأداء # مقياس الصحة from sklearn.metrics import accuracy_score # مقياس الدقة from sklearn.metrics import precision_score # مقياس الاستذكار from sklearn.metrics import recall_score # f1 from sklearn.metrics import f1_score # مصفوفة الارتباك from sklearn.metrics import confusion_matrix # تصنيف بيانات الاختبار y_pred = model.predict(X_test) # حساب مقاييس الأداء accuracy = accuracy_score(y_test, y_pred) precision=precision_score(y_test, y_pred , average='weighted') recall= recall_score(y_test, y_pred, zero_division=1, average='weighted') f1= f1_score(y_test, y_pred, zero_division=1, average='weighted') print('Model Accuracy on Test Data:', accuracy*100) print('Model Precision on Test Data:', precision*100) print('Model Recall on Test Data:', recall*100) print('Model F1 on Test Data:', f1*100) confusion_matrix(y_test, y_pred) تكون النتائج (لاحظ ارتفاع جميع المقاييس مما يعني جودة المُصنف): Model Accuracy on Test Data: 90.1144387630874 Model Precision on Test Data: 90.90281584915091 Model Recall on Test Data: 90.1144387630874 Model F1 on Test Data: 90.32645671662543 array([[ 366, 129, 24], [ 53, 444, 62], [ 20, 118, 2891]], dtype=int64) يُمكن رسم مصفوفة الارتباك confusion matrix بشكل أوضح باستخدام المكتبة seaborn: # رسم مصفوفة الارتباك import seaborn as sns sns.set(style = 'whitegrid') fig, ax = plt.subplots(figsize = (8,6)) sns.heatmap(confusion_matrix(y_true = y_test, y_pred = y_pred), fmt = 'g', annot = True) ax.xaxis.set_label_position('top') ax.xaxis.set_ticks_position('top') ax.set_xlabel('Prediction', fontsize = 14) ax.set_xticklabels(['negative (0)', 'neutral (1)', 'positive (2)']) ax.set_ylabel('Actual', fontsize = 14) ax.set_yticklabels(['negative (0)', 'neutral (1)', 'positive (2)']) plt.show() مما يُظهر: يُمكن حساب بعض مقاييس الأداء الأخرى المُستخدمة في حالة وجود أكثر من صف في المسألة (Micro, Macro, Weighted): # مقاييس الأداء في حالة أكثر من صفين print('\nAccuracy: {:.2f}\n'.format(accuracy_score(y_test, y_pred))) print('Micro Precision: {:.2f}'.format(precision_score(y_test, y_pred, average='micro'))) print('Micro Recall: {:.2f}'.format(recall_score(y_test, y_pred, average='micro'))) print('Micro F1-score: {:.2f}\n'.format(f1_score(y_test, y_pred, average='micro'))) print('Macro Precision: {:.2f}'.format(precision_score(y_test, y_pred, average='macro'))) print('Macro Recall: {:.2f}'.format(recall_score(y_test, y_pred, average='macro'))) print('Macro F1-score: {:.2f}\n'.format(f1_score(y_test, y_pred, average='macro'))) print('Weighted Precision: {:.2f}'.format(precision_score(y_test, y_pred, average='weighted'))) print('Weighted Recall: {:.2f}'.format(recall_score(y_test, y_pred, average='weighted'))) print('Weighted F1-score: {:.2f}'.format(f1_score(y_test, y_pred, average='weighted'))) # تقرير التصنيف from sklearn.metrics import classification_report print('\nClassification Report\n') print(classification_report(y_test, y_pred, target_names=['Class 1', 'Class 2', 'Class 3'])) مما يُعطي (لاحظ ارتفاع جميع المقاييس مما يعني جودة المُصنف): Accuracy: 0.88 Micro Precision: 0.88 Micro Recall: 0.88 Micro F1-score: 0.88 Macro Precision: 0.79 Macro Recall: 0.83 Macro F1-score: 0.80 Weighted Precision: 0.90 Weighted Recall: 0.88 Weighted F1-score: 0.89 Classification Report precision recall f1-score support Class 1 0.79 0.75 0.77 519 Class 2 0.59 0.82 0.69 559 Class 3 0.98 0.92 0.95 3029 accuracy 0.88 4107 macro avg 0.79 0.83 0.80 4107 weighted avg 0.90 0.88 0.89 4107 يُمكن أيضًا اختيار مجموعة تغريدات عشوائية جديدة وتصنيفها وحفظ النتائج في ملف results.csv: # تصنيف مجموعة اختبار text_clean = tweets['tweet_clean'] text_train, text_test = train_test_split(text_clean, test_size = 0.2, random_state = 0) result_test = pd.DataFrame(data = zip(text_test, y_pred), columns = ['text', 'polarity']) polarity_decode = {0 : 'Negative', 1 : 'Neutral', 2 : 'Positive'} result_test['polarity'] = result_test['polarity'].map(polarity_decode) pd.set_option('max_colwidth', 300) # حفظ النتائج result_test.to_csv("results.csv") result_test تكون النتائج مثلًا: الخلاصة عرضنا في هذه المقالة خطوات بناء نموذج تعلّم لتصنيف النصوص العربية إلى موجبة وسالبة ومحايدة. يُمكن تجربة المثال كاملًا من موقع Google Colab، ولا تنسى الاطلاع على مجموعة البيانات المتوفرة الخاصة بهذا المقال. اقرأ أيضًا دليل المبتدئين لفهم أساسيات التعلم العميق لذكاء الاصطناعي: مراحل البدء والتطور والأسس التي نشأ عليها تعلم الآلة: التحديات الرئيسية وكيفية التوسع في المجال
  18. تسند عملية إدارة المتجر إلى مدير (أو أكثر) يكون مسؤولًا عن هذه المهمة، ويعتمد نجاح المتجر بشكل كبير على حسن الإدارة والمتابعة لعمليات المتجر المختلفة. تسمح عمليات الضبط المتاحة في أوبن كارت بإدارة المتجر بشكل كامل والتحكم بكافة خياراته الممكنة، ويجب على مدير المتجر الانتباه جيدًا لإعدادات المتجر لأنها ستلعب الدور الرئيسي في جميع عمليات الشحن والدفع والضرائب وغيرها وهي العمليات التي تُشكّل محور عمل المتجر. تعرفنا في المقال السابق على كامل قسم واجهة المتجر في لوحة تحكم أوبن كارت وسنمر في هذا المقال بالتفصيل على الخيارات المندرجة ضمن قسم "الضبط" في لوحة التحكم وهي أربعة: "الإعدادات" و "المدراء" و "الأوضاع" و"الأدوات". هذا المقال جزء من سلسلة تعريفية بلوحة تحكم متجر أوبن كارت، إليك فهرس مقالات كامل السلسلة: مدخل إلى متجر أوبن كارت وكيفية تثبيته إدارة الأقسام والمنتجات في متجر أوبن كارت التعرف على إعدادات واجهة متجر أوبن كارت تعلم كيفية ضبط متجر أوبن كارت شرح الإضافات والقوالب في لوحة تحكم متجر أوبن كارت نظرة على خيارات التسويق التي يوفرها متجر أوبن كارت التقارير والإحصائيات: نافذة على أداء متجر أوبن كارت إعدادات الدفع والشحن في متجر أوبن كارت الإعدادات Settings تسمح الإعدادات بضبط الإعدادات العامة للمتجر وذلك من الخيار "الضبط" ثم "الإعدادات" لفتح صفحة "المتاجر" لنجد المتجر الافتراضي الذي يُعرّف تلقائيًا عند تثبيت أوبن كارت. يُمكن تحرير المتجر الافتراضي لإدخال البيانات المناسبة للمتجر. تحتوي صفحة المتجر سبعة تبويبات نعرضها فيما يلي: التبويب "عام" General يحوي هذا التبويب الحقول التالية والتي تسمح بإعطاء الطابع المميز للمتجر: عنوان الميتا تاغ Title: يجب كتابة اسم المتجر والذي سيظهر في شريط العنوان للمتصفح في صفحات المتجر. وصف الميتا تاغ Meta Tag Description: يُمكن كتابة وصف للمتجر لمساعدة محركات البحث في الوصول للمتجر. كلمات الميتا تاغ Meta Tags: يُمكن كتابة كلمات دليلية لمساعدة بعض محركات البحث للوصول إلى المتجر وتُكتب مفصولة بفاصلة بين كل كلمه وكلمه. مثلًا: كتب , حواسيب , جوال. القالب أو الاستايل Template: يُمكن اختيار قالب المتجر. يحتوي المتجر الافتراضي لأوبن كارت قالب افتراضي واحد فقط، كما يُمكن شراء قوالب جديدة من منصات بيع القوالب المنتشرة على الويب. التخطيط الافتراضي Default Layout: يُمكن اختيار التخطيط الافتراضي لواجهة المتجر من مختلف التخطيطات المتاحة. التبويب "المتجر" Store يحوي هذا التبويب الحقول التالية والتي تسمح بتوفير المعلومات الأساسية عن المتجر: اسم المتجر Store Name: يجب كتابة اسم المتجر والذي سيظهر للعملاء في صفحة التواصل مع المتجر (اتصل بنا) في واجهة المتجر. صاحب المتجر Store Owner: يجب كتابة اسم صاحب المتجر والذي سيُستخدم في التواصل مع العملاء عن طريق البريد الإلكتروني. العنوان Address: يجب كتابة عنوان المتجر والذي سيظهر في صفحة التواصل مع المتجر (اتصل بنا). إحداثية المتجر Geocode: يُمكن كتابة احداثيات موقع المتجر والذي يُمكن الحصول عليها من خرائط غوغل Google Maps. مثال: 55.2048,55.2708. البريد الالكتروني E-Mail: يجب إدخال البريد الإلكتروني والذي سيُستخدم في جميع مراسلات المتجر. تليفون Telephone: يجب إدخال رقم التليفون الذي سيظهر في صفحة "اتصل بنا" وفي الشريط العلوي من واجهة المتجر. فاكس Fax: يُمكن إدخال رقم الفاكس الذي سيظهر في صفحة "اتصل بنا" في واجهة المتجر. صورة Image: يُمكن اختيار صورة لتكون الشعار الخاص بالمتجر والتي ستظهر أيضًا في صفحة "اتصل بنا". أوقات دوام عمل المتجر Opening Times: يُمكن إدخال أوقات العمل بالمتجر. ملاحظات Comment: يُمكن إدخال ملاحظات تخص التعامل مع المتجر. التبويب "محلي" Local يجب إعداد بيانات هذا التبويب بدقة إذ تعتمد على هذه البيانات خدمات الشحن والدفع وعمليات حساب الكلفة والضرائب وغيرها. يحوي هذا التبويب الحقول التالية والتي تسمح بتخصيص المتجر: الدولة Country: يجب اختيار الدولة التي يقع بها المتجر. المنطقة/المحافظة Region/State: يُمكن اختيار المنطقة أو المحافظة التي يقع بها المتجر. اللغة الافتراضية للمتجر Language: يجب اختيار اللغة الافتراضية لواجهة المتجر. اللغة الافتراضية للوحة التحكم Administration Language: يجب اختيار اللغة الافتراضية للوحة التحكم بالمتجر. العملة الافتراضية للمتجر Currency: يجب اختيار العملة الافتراضية التي ستُستخدم لأسعار المنتجات والضرائب وغيرها. تحديث تلقائي للعملة Auto Update Currency: يُمكن اختيار "نعم" في حال استخدام أكثر من عملة ونريد تحديث معدل التحويل بين العملات المختلفة يوميًا. نوع الطول Length Class: يُمكن اختيار وحدة الطول الافتراضية (سنتيمتر، ملليمتر، إنش) والتي ستظهر في صفحة إدخال المنتج. نوع الوزن Weight Class: يُمكن اختيار وحدة الوزن الافتراضية (كيلو جرام، جرام، باوند، أونصة) والتي ستظهر في صفحة إدخال المنتج. لاحظ، مثلًا، أن اختيار العملة "US Dollar" يؤدي إلى ظهور إشارة "$" لأسعار المنتجات في واجهة المتجر: التبويب "خيارات" Option يحوي هذا التبويب على مجموعة من الأقسام. يختص كل قسم بمجموعة متجانسة من الخيارات. المنتجات Products يحوي هذا القسم الحقول التالية: عداد المنتج Product counter: يؤدي تحديد "نعم" إلى عرض عدد المنتجات المتاحة داخل كل قسم فرعي من الأقسام الرئيسية الموجودة في القائمة العلوية للمتجر كما يُبين الشكل التالي: عدد المنتجات لكل صفحة Default Items Per Page (للوحة التحكم Admin): يُحدّد هذا الحقل عدد العناصر الواجب إظهارها في صفحات لوحة التحكم. التقييمات Reviews يوفر أوبن كارت إمكانية تقييم المنتجات والخدمات من قبل العملاء. يحوي هذا القسم الحقول التالية والتي تُقيد هذه الإمكانية أم لا: السماح بالتقييمات Allow Reviews: يؤدي اختيار "نعم" إلى إمكانية إضافة تعليقات من قبل العملاء في صفحة المنتج. السماح بالتقييم للأعضاء غير المسجلين بالموقع Allow Reviews for all: يؤدي اختيار "نعم" إلى إمكانية إضافة تعليق من قبل الزوار (غير المسجلين في المتجر) في صفحة المنتج. يتمكن العميل في واجهة المتجر، في حال السماح بالتقييمات، من معاينة تقييمات الآخرين وكتابة تقييمه الشخصي واختيار عدد النجوم (5 يعني ممتاز) للكتاب كما يُبين الشكل التالي: قسائم الهدايا Vouchers يوفر أوبن كارت إمكانية شراء أي عميل قسيمة هدايا من أجل إهدائها إلى شخص آخر عن طريق صفحة "شراء قسيمة هدايا" والتي يُمكن الدخول إليها من الرابط "قسائم الهدايا" الموجود تحت "إضافات" أسفل صفحة واجهة المتجر. يحوي هذا القسم الحقول التالية والتي تسمح بوضع بعض الشروط على مبالغ قسائم الهدايا: أقل قيمة لقسيمة الهدايا Voucher min: يجب إدخال الحد الأدنى للمبلغ (بالعملة الافتراضية) الذي يُمكن للعميل إدخاله لشراء قسيمة هدايا. أكبر قيمة لقسيمة الهدايا Voucher max: يجب إدخال الحد الأعلى للمبلغ الذي يُمكن للعميل إدخاله لشراء قسيمة هدايا. يتم التأكد من الحد الأدنى والحد الأعلى لمبلغ الهدية عند شراء العميل قسيمة هدايا: الضرائب Taxes تتغير الضريبة عادًة حسب بلد تواجد العميل إذ أن الضرائب تعتمد على القوانين الخاصة بكل بلد. يحوي هذا القسم الحقول التالية والتي تسمح بضبط إعدادات الضريبة: عرض السعر مع الضريبة Display Prices With Tax: يؤدي اختيار "نعم" إلى عرض الضريبة مع سعر المنتج في صفحة المنتج في واجهة المتجر. استخدم ضريبة عنوان المتجر Use Store Tax Address: يُمكن الاختيار بين "عنوان الشحن" و "عنوان الدفع". يُستخدم هذا العنوان في حال لم يقم المستخدم بتسجيل الدخول في المتجر. استخدم ضريبة عنوان العميل Use Customer Tax Address: يُمكن الاختيار بين "عنوان الشحن" و "عنوان الدفع". يُستخدم هذا العنوان في حال قيام المستخدم بتسجيل الدخول في المتجر. لنضرب مثالًا عمليًا، لنفرض أن الضريبة في المملكة العربية السعودية هي 10% من سعر المنتج وأنها في الإمارات العربية المتحدة 5% ونريد أن يقوم أوبن كارت بحساب الضريبة آليًا حسب البلد، يجب القيام بما يلي: تعريف المنطقة الجغرافية "السعودية" من "الضبط" ثم "الأوضاع" ثم "المناطق الجغرافية" كما يلي: تعريف المنطقة الجغرافية "الإمارات" من "الضبط" ثم "الأوضاع" ثم "المناطق الجغرافية. تعريف سعر الضريبة "ضريبة السعودية" من "الضبط" ثم "الأوضاع" ثم "سعر الضريبة" لتكون 10%: تعريف سعر الضريبة "ضريبة الإمارات" من "الضبط" ثم "الأوضاع" ثم "سعر الضريبة" لتكون 5%. تعريف نوع الضريبة "ضريبة مئوية" ووضع ضريبة السعودية وضريبة الإمارات ضمنها من "الضبط" ثم "الأوضاع" ثم "نوع الضريبة": نُسند نوع الضريبة "ضريبة مئوية" إلى كتاب "تعلم الآلة" مثلًا: في حال كانت خيارات الضرائب استخدام عنوان الشحن، ستتغير قيمة ضريبة الكتاب "تعلم الآلة" في واجهة المتجر وفق عنوان الشحن. إذا كان الشحن للملكة العربية السعودية تكون الضريبة 10%: أما إذا كان الشحن للإمارات العربية المتحدة تُحسب الضريبة 5%. حسابات العملاء Account يحوي هذا القسم الحقول التالية والتي تسمح بضبط إعدادات العملاء: المتواجدون الآن Customers Online: يؤدي اختيار "نعم" إلى عرض العملاء المتواجدون الآن بالمتجر في صفحة التقارير. نشاط العملاء Customers Activities: يؤدي اختيار "نعم" إلى إمكانية تتبع نشاط العملاء بالمتجر من خلال صفحة التقارير. تقرير بحث العملاء Customers Search Report: يؤدي اختيار "نعم" إلى إمكانية البحث عن العملاء من خلال صفحة التقارير. مجموعة العميل Customer Group: يُمكن اختيار المجموعة الافتراضية التي سوف ينتمي لها العميل عند تسجيله بالمتجر. عرض مجموعات العميل Customer Groups: يُمكن تحديد مجموعات العملاء التي سوف يتم عرضها في صفحة التسجيل للزوار الذين يقومون بالتسجيل في المتجر. عرض السعر بعد تسجيل الدخول Login Display Prices: يؤدي اختيار "نعم" إلى عرض سعر المنتج فقط للعملاء المسجلين في المتجر. الحد الأقصى لمحاولات تسجيل الدخول Max Logins Attempts: يُمكن تحديد عدد المحاولات الممكنة لعملية تسجيل الدخول بالمتجر وبعدها سوف يتم قفل الحساب بشكل مؤقت لمدة ساعة واحدة. شروط إنشاء حساب Account Terms: يُمكن اختيار صفحة من صفحات المعلومات لعرضها على زائر الموقع وطلب الموافقة عليها قبل عملية إتمام التسجيل بالمتجر. أما في حال اختيار "لا يوجد"، فيُمكن للزائر التسجيل بالمتجر دون الحاجة إلى الموافقة على شروط ما. إتمام الطلب Checkout ينتقل العميل في واجهة المتجر بعد انتهائه من اختيار المنتجات ووضعها في سلة الشراء إلى صفحة إتمام الطلب التالية: يحوي هذا القسم على الحقول التالية والتي تقوم بضبط إعدادات عملية إتمام الطلب من قبل العميل: بادئة الفواتير Invoice Prefix: يُمكن تحديد بادئة معينة لأرقام فواتير العميل. عرض الوزن في صفحة سلة الشراء Display Weight on Cart Page: يؤدي اختيار "نعم" إلى عرض وزن المنتج في أعلى صفحة سلة الشراء وفي صفحة إنهاء الطلب في واجهة المتجر. الطلب للزوار Guest Checkout: يؤدي اختيار "نعم" إلى تمكين الزوار من الشراء من المتجر وإنهاء الطلب دون الحاجة إلى التسجيل. إلا أنه في حالة المنتجات الرقمية ستتعطل هذه الخاصية بسبب ضرورة تنزيل المنتجات الرقمية من صفحة "التحميلات" في حساب العميل. شروط إتمام الطلب Checkout Terms: يُمكن اختيار صفحة من صفحات المعلومات لعرضها على العميل والطلب منه الموافقة عليها قبل إتمام طلبيته في المتجر .سيتمكن العميل عند اختيار "لا يوجد" من إتمام طلبيته دون الحاجة إلى أي موافقة. حالة الطلب Order Status: يُمكن اختيار الحالة الافتراضية للطلب بعد تأكيد العميل عند الدفع. يُمكن للعميل متابعة حالة طلبه ضمن صفحة "حسابي" ثم "طلباتي" في واجهة المتجر. حالة الطلب لقسائم التخفيض ونقاط المكافآت Processing Order Status: يُمكن اختيار حالة الطلب الذي تُستخدم معه قسائم الهدايا أو التخفيض أو نقاط المكافآت وذلك بهدف إتاحة مراجعة الطلب من قبل الإدارة. حالة الطلب للمنتجات الرقمية Order Status for digital products: يُمكن اختيار حالة الطلب لعمليات الشراء للمنتجات الرقمية. حالة الاحتيال Fraud Status: يُمكن اختيار حالة الطلب المناسبة لعملية محاولة إدخال العميل لبيانات دفع خاطئة (مثل بيانات البطاقة الائتمانية)، أو محاولة إدخاله رقم قسيمة تخفيض أو قسيمة هدايا غير صحيحة (يُفضّل اختيار حالة "ملغي" أو "مرفوض"). API User: يُمكن الاختيار من واجهات برمجة API والتي تُستخدم عادةً للربط مع تطبيقات مختلفة مثل تطبيقات الجوال (لربط عمليات الدفع والتسجيل بالموقع) أو تطبيقات الويب مثل التسجيل بالمتجر من خلال الفيسبوك وتويتر وغيرها من مواقع التواصل الاجتماعي. يُمكن إنشاء "واجهة برمجة - APIs" من صفحة "واجهة برمجة API" والتي يُمكن فتحها من الخيار "المدراء" ثم "واجهة برمجة API". التوفر Stock يحوي هذا القسم على الحقول التالية والتي تسمح بضبط إعدادات حالة توفر أو عدم توفر المنتج حاليًا في المتجر: اظهار كمية المنتج المتوفرة Display Stock: يؤدي اختيار "نعم" إلى عرض كمية المنتج المتوفرة في صفحة المنتج. أما في حال اختيار "لا" يتم عرض "المنتج متوفر" أو "غير متوفر" في صفحة المنتج. عرض تحذير عدم توفر المنتج في السلة Show Out Of Stock Warning: يؤدي اختيار "نعم" إلى عرض رسالة في صفحة سلة الشراء تُبين أن المنتج غير متوفر. أما في حال اختيار "لا" فيجب أن تُختار القيمة "نعم" في حقل "السماح لإتمام الطلب اذا كانت الكمية غير متوفرة" لإتمام الطلب حتى إذا كانت الكمية غير متوفرة لإخفاء رسالة التنبيه. السماح لإتمام الطلب اذا كانت الكمية غير متوفرة Stock Checkout: يؤدي اختيار "نعم" للسماح للعملاء بإتمام عملية الشراء ولو لم تكن الكمية متوفرة. نظام العمولة Affiliates يوفر أوبن كارت نظام عمولة متكامل يسمح للعملاء بكسب المال لقاء مساعدتهم في تسويق منتجات المتجر. يحوي هذا القسم على الحقول التالية والتي تسمح بإعداد نظام العمولة: مجموعة نظام العمولة Affiliate Group: يجب اختيار مجموعة العملاء التي تستطيع التسجيل في نظام العمولة بالمتجر. موافقة نظام العمولة Affiliate Require Approval: عند اختيار "نعم" سوف يُشترط موافقة الإدارة قبل تفعيل نظام العمولة للعميل، أما في حال اختيار "لا" فسيُضم العميل لنظام العمولة تلقائيًا حال إنهائه لعملية التسجيل في الموقع. الموافقة على إضافة مبلغ العمولة Automatic Commission: عند اختيار "نعم" سوف تُضاف قيمة العمولة الى حساب العميل تلقائيًا بعد عملية إكمال كل طلب، أما في حال اختيار "لا" سوف يُشترط موافقة الإدارة على إضافة قيمة العمولة. نسبة نظام العمولة (%) Affiliate Commission: وهي النسبة الافتراضية التي سيكسبها العميل عند شراء أحد الزبائن عن طريقه. شروط نظام العمولة Affiliate Terms: يُمكن اختيار صفحة من صفحات المعلومات والتي ستُعرض على العميل للموافقة عليها قبل عملية إنهاء التسجيل في نظام العمولة. عند تحديد الخيار "لا يوجد" يتمكن العميل من إتمام التسجيل في نظام العمولة دون الحاجة إلى الموافقة على أي صفحة. الإرجاع Return يطلب العميل في بعض الأحيان إرجاع المنتج لسبب أو لآخر. يحوي هذا القسم على الحقول التالية التي تضبط عملية الإرجاع: شروط إرجاع المنتج Return Terms: يُمكن اختيار صفحة من صفحات المعلومات والتي ستُعرض للعميل للموافقة عليها قبل إتمام عملية طلب إرجاع منتج ما. عند اختيار "لا يوجد" يتمكن العميل من إتمام عملية الإرجاع دون الحاجة إلى الموافقة على أي صفحة. حالة إرجاع المنتج Return Status: يُمكن اختيار الحالة التي ستظهر للعميل بعد الموافقة على عملية الإرجاع. التحقق Captcha يسمح التحقق بتجنب المضايقات وعمليات التسجيل أو الإرسال المتكررة بغرض سيئ مثل إغراق المتجر بالبريد المزعج لإخراجه عن الخدمة. يحوي هذا القسم على الحقول التالية التي تسمح بإعداد التحقق:: التحقق Captcha: يُمكن اختيار نوع التحقق. صفحة التحقق Captcha Pages: يُمكن تحديد الصفحات المطلوب إظهار التحقق فيها. مثلًا: من المستحسن التحقق في صفحة "اتصال" تجنبًا لإغراق بريد المتجر بالبريد العشوائي spams. ملاحظة: يجب تنزيل وتمكين التحقق المطلوب وذلك بفتح صفحة "الإضافات" من الخيار "الإضافات" في "لوحة التحكم" ومن ثم الاختيار من القائمة "اختيار نوع الإضافة" الخيار "تحقق كابتشا" ثم تنزيل وتمكين التحقق المطلوب: التبويب "الصور" Image تلعب الصور دورًا مهمًا في جذب الزوار للمتجر. يحوي هذا التبويب على الحقول التالية: شعار المتجر Store Logo: يُمكن اختيار شعار للمتجر. الأيقونة Icon: يُمكن اختيار أيقونة للمتجر والتي تظهر بجانب اسم الموقع في الشريط العلوي للمتصفح. التبويب "بريد الكتروني" Mail يُمكن إرسال البريد للعملاء في الكثير من الأحيان. يحوي هذا التبويب على قسمين: القسم "عام" General يحتوي على الحقول التالية: Mail Engine: يُمكن اختيار البروتوكول الذي سوف يُستخدم لإرسال البريد ( Mail أو SMTP). Mail Parameters: يُمكن في حالة استخدام البروتوكول Mail إضافة بريد إلكتروني خاص بالموقع حتى تأتي عليه تنبيهات رسائل الكترونية في حالة فشل الإرسال من المتجر SMTP Hostname: يُمكن إدخال عنوان مزود الخدمة. مثلًا: smtp.gmail.com. SMTP Username: يُمكن إدخال اسم الدخول المُعطى من قبل مزود خدمة البريد الإلكتروني. SMTP Password: يُمكن إدخال كلمة المرور لمزود خدمة البريد الالكتروني. SMTP Port: يُمكن إدخال رقم منفذ البريد الإلكتروني لمزود خدمة البريد الإلكتروني. SMTP Timeout: يُمكن إدخال زمن الانتظار بين إرسال كل حزمة بريد والأخرى. القسم " تنبيه البريد الإلكتروني" يحتوي على الحقول التالية: تنبيه البريد الالكتروني Alert Mail: يُمكن تحديد الصفحات المطلوب إرسال بريد تنبيه منها لبريد مدير المتجر في حالة قيام أي عميل بنشاط في هذه الصفحات. مثلًا: في حال تحديد الصفحة "تسجيل"، سيُرسل بريد لمدير المتجر في كل مرة يقوم بها أحد الزوار بالتسجيل في المتجر. بريد إلكتروني إضافي Additional Alert E-mails: يُمكن إضافة عناوين بريد إضافية لتصل إليها التنبيهات. التبويب "السيرفر" Server يحوي هذا التبويب أربعة أقسام: القسم "عام" General يحوي الحقول التالية: وضع الصيانة Maintenance Mode: يؤدي اختيار "نعم" إلى إغلاق المتجر أمام الزوار الذين تظهر لهم رسالة بأن الموقع تحت الصيانة، ولن يستطيع الدخول للموقع غير المدراء والمشرفين. SEO- استخدام روابط السيو Use SEO URL's: يؤدي تحديد "نعم" إلى استخدام الروابط المختصرة التي تنُشئ عند إضافة المنتجات والاقسام والشركات وصفحات المعلومات في روابط الصفحات. وهي روابط تساعد على أرشفة الموقع لدى محركات البحث بصورة أسرع وأوضح. Robots: يُمكن الإضافة أو الحذف لإعداد قائمة بالزواحف web crawler لمحركات البحث. مستوى ضغط الإخراج Outpout Compression Level: تُحدّد القيمة المدخلة مستوى ضغط البيانات المُرسلة من الخادم الى متصفح العميل. يتراوح مستوى الضغط من 0 الى 9 وكلما زاد الرقم عن صفر زاد مستوى الضغط Gzip مما يؤدي إلى سرعة التحميل على المتصفح، إلا أن ذلك قد يؤثر على أداء الخادم لاسيما إذا كان محدود الإمكانات. الحماية Protection يحوي الحقول التالية: SSL- استخدام شهادات الأمان Use SSL: يؤدي تحديد القيمة "نعم" إلى تمكين الطلبات الآمنة HTTPS. يجب، في هذه الحالة، توفير شهادة SSL صالحة على الخادم. اظهار زر نسيت كلمة المرور Allow Forgotten Password: يؤدي تحديد الخيار "نعم" إلى إظهار الرابط "هل نسيت كلمة المرور؟" في لوحة الدخول لمدير المتجر مما يُساعد المدير، في حال نسيان كلمة السر، من طلب إرسال رسالة إلى بريده الإلكتروني تحتوي على رابط استعادة كلمة مرور جديدة. Use Shared Sessions: يؤدي تحديد الخيار "نعم" إلى مشاركة بيانات الجلسات في حالة المتاجر المتعددة. مفتاح التشفير Encryption Key: يُمكن إدخال سلسلة طويلة من الحروف والأرقام والتي ستُستخدم لتشفير البيانات الخاصة. التحميل Upload يحوي الحقول التالية: حجم الملف الأقصى للصور Max File Size: يُمكن تحديد الحجم الأعظمي لملفات الصور التي يُمكن تحمليها. تُدخل القيمة بالبايتات: مثلًا: 300000 بايت تساوي 0.3 ميجا او 300 كيلوبايت تقريبًا . السماح برفع الملفات بالامتدادات التالية Allowed File Extensions: يُمكن تحديد امتدادات الملفات المسموح برفعها على المتجر. Allowed File Mime Types: يُمكن تحديد أنواع MIME الملفات المسموح برفعها على المتجر. معالجة الأخطاء Errors يحوي الحقول التالية: عرض الأخطاء Display Errors: يؤدي تحديد "نعم" إلى عرض جميع الأخطاء والتحذيرات التي قد تنجم عن أخطاء في الشيفرة. يجب تحديد "لا" عند وضع المتجر على الويب. تسجيل الأخطاء Log Errors: يؤدي تحديد "نعم" إلى تسجيل الأخطاء والإشعارات في ملف معين. اسم ملف تسجيل الاخطاء Error Log Filename: يُمكن إدخال اسم الملف الذي ستُسجل الأخطاء فيه. المدراء Users يُمكن أن تُسند إدارة المتجر لشخص أو أكثر مع تحديد الصلاحيات المناسبة لكل منهم. يحتوي الخيار "المدراء" (تحت الخيار "الضبط") في "لوحة التحكم" الخيارات الفرعية التالية: "المدراء" و"مجموعات المدراء" و"واجهة برمجة - API". مجموعات المدراء Users Groups يُمكن إنشاء مجموعة مدراء وتعيين الصلاحيات المناسبة لهم. تحتوي صفحة "مجموعات المدراء" الحقول التالية: اسم مجموعة المدراء User Group Name: يجب إعطاء اسم مجموعة المدراء. صلاحيات الدخول Access Permission: يُمكن تحديد الصفحات التي يحق للمستخدمين ضمن هذه المجوعة الوصول إليها وقراءة بياناتها. صلاحيات التعديل Modify Permission: يُمكن تحديد الصفحات التي يحق للمستخدمين ضمن هذه المجوعة الوصول إليها وتعديل بياناتها. المدراء Users يُمكن من صفحة "المدراء" تعريف مستخدمين وتحديد مجموعة المدراء التي ينتمون لها مع إمكانية تعطيل/تمكين المستخدم: واجهة برمجة - APIs يوفر أوبن كارت واجهة برمجة تطبيقات API تسمح بالتعامل مع أوبن كارت عن طريقها لإجراء مختلف العمليات الممكنة من شراء المنتجات وغيرها. الأوضاع Localization يحوي هذا الخيار الروابط التالية: عنوان متجرنا Store Location: إذا كان المتجر الإلكتروني مرتبطًا مع متجر حقيقي فيُمكن إدخال بيانات المتجر الحقيقي في صفحة "عنوان متجرنا". يُمكن إظهار معلومات المتجر في صفحة "اتصل بنا" من التبويب "المتجر" في صفحة "الإعدادات" تحت الخيار "الضبط" (وتحرير المتجر الافتراضي) ومن ثم تحديد المتجر: اللغات Language: يُمكن إضافة لغات جديدة غير اللغات الافتراضية (العربية والإنكليزية). يجب أولًا تثبيت حزمة اللغة الجديدة من "الإضافات". العملات Currency: يُمكن إضافة عملات جديدة للمتجر من خلال صفحة "العملات". حالة التوفر Stock Status: يُمكن من صفحة "وضع حالة التوفر" إنشاء حالات مختلفة لعرضها في حال عدم توفر المنتج. حالة الطلبات Order Status: يُمكن من صفحة "حالة الطلبات" إنشاء حالات مختلفة لعرضها حالة الطلبية. إرجاع المنتجات Returns: يسمح بإنشاء حالات الإرجاع وإجراءات الإرجاع وأسماء أسباب الإرجاع التي يمكن تحديدها في طلبات الإرجاع. الدول Countries: تحتوي صفحة "الدول" بيانات 239 دولة (تنزل مع أوبن كارت). يُمكن إضافة وتعديل بيانات الدول. المناطق Zone: تحتوي صفحة "المناطق" بيانات 3948 منطقة (تنزل مع أوبن كارت). يُمكن إضافة وتعديل بيانات المناطق. المناطق الجغرافية Geo zone: تُستخدم المناطق الجغرافية في حساب الشحن والضرائب. الضرائب Taxes: يُمكن تعريف فئات الضرائب وخصائص كل منها. نوع الطول Length class: يُمكن تعريف وحدات طول مختلفة لاستخدامها في المتجر. نوع الوزن Weight class: يُمكن تعريف وحدات وزن مختلفة لاستخدامها في المتجر. الأدوات Maintenance يحوي هذا الخيار الروابط التالية: نسخة احتياطية/استعادة Backup/Restore يجب أخذ نسخة احتياطية من قاعدة بيانات المتجر بشكل دوري لاستعادتها في حال حصول أي طارئ يؤدي إلى عطب قاعدة بيانات المتجر. يسمح التبويب "نسخة احتياطية" من الصفحة "نسخة احتياطية/استعادة" بإجراء نسخة احتياطية من جداول قاعدة البيانات (يُمكن اختيار بعضها فقط). تُخزّن النسخة الاحتياطية في ملف ينتهي باللاحقة sql. يُمكن استعادة النسخة الاحتياطية من التبويب "استعادة" ملفات التنزيل Uploads يسمح هذا الخيار بمعاينة جميع الملفات التي تم رفعها على أوبن كارت. تقرير الأخطاء Error logs تُسجّل جميع الأخطاء (البرمجية) التي قد تنجم خلال تعامل العميل مع المتجر في سجل خاص يُدعى سجل الأخطاء. يمكن لمطوري الويب استخدام هذا السجل لتتبع الأخطاء في الترميز. يُمكن أن يمتلئ سجل الأخطاء بمرور الوقت، لذا من الجيد مسح السجل من وقت لآخر. يؤدي الضغط على "مسح السجل" إلى مسح سجل الأخطاء. خاتمة أنهينا في هذا الدرس شرح مختلف عمليات إدارة المتجر والتحكم بكافة خياراته الممكنة، ونعرض في الدرس القادم كيفية إضافة الكثير من الخدمات والميزات غير الموجودة في متجر أوبن كارت بشكل افتراضي عن طريق تثبيت الإضافات، كما نعرض آليات تعديل تصميم جميع صفحات المتجر بما يتناسب مع منتجات المتجر. اقرأ أيضًا الدليل الشامل لأشهر أنظمة إنشاء وإدارة المتاجر الإلكترونية أنواع المتاجر الإلكترونية ونماذج إيراداتها أساسيات تمويل المتاجر الإلكترونية تبني المنتج: الطريق إلى إقبال العملاء على منتجك
  19. تتميز تطبيقات الويب التقدميّة Progressive Web Apps (تختصر إلى PWA) بواجهات ويب شبيهة جدًا بواجهات التطبيقات المألوفة للجميع مما يوفر تجربة استخدام عالية الجودة وسريعة وموثوقة وجذابة. على الرغم من أن تطبيقات الويب يُمكن أن توفر تجارب استخدام رائعة وجديدة إلا أن أغلبية المستخدمين تتوقع من هذه التطبيقات واجهات استخدام شبيهة بالواجهات التي اعتادوا عليها أثناء تشغيلهم لمختلف التطبيقات على حواسبهم، وعندها ستكون جاذبية استخدام هذه التطبيقات أعلى من المتوسط وفق معظم المقاييس. من المعروف أن متجر Play Store هو متجر تطبيقات أندرويد، وغالبًا ما يرغب المطورون بفتح صفحات الويب التقدميّة المُطوّرة من تطبيقات أندرويد. يسمح معيار نشاط الويب الموثوق Trusted Web Activity للمتصفحات بتوفير حاوية متوافقة تمامًا مع منصة الويب التي تُظهر صفحات الويب التقدميّة داخل تطبيق أندرويد. تتوفر هذه الميزة في المتصفح Chrome حاليًا وهي قيد التطوير في المتصفح Firefox Nightly. عارض الويب وكوردوفا: حلول متوفرة ولكن قاصرة كان من الممكن دومًا تضمين سلوك الويب في تطبيق أندرويد باستخدام تقانات مثل عارض الويب WebView في أندرويد أو أطر العمل الخاصة مثل كوردوفا Cordova. لا يوفر عارض الويب WebView في أندرويد جميع ميزات منصات الويب الحديثة مثل منتقي جهات الاتصال contact picker وملفات النظام filesystem، إذ أنه لم يُصمم في الأساس ليكون بديلًا عن المتصفح. أما بالنسبة لبيئة كوردوفا، فعلى الرغم من أنها صُمّمت لتجاوز محدودية عارض الويب إلا أن واجهات برمجة التطبيقات APIs تقتصر على هذه البيئة مما يعني أن المطور يحتاج شيفرة أساسية إضافية لاستخدام واجهات برمجة تطبيقات كوردوفا منفصلة عن شيفرة صفحات الويب التقدميّة اللازمة لعرض الصفحات على متصفحات الويب. علاوًة على ذلك، قد لا يعمل اكتشاف الميزات في التطبيق كما هو متوقع منه، إضافًة إلى إمكانية ظهور العديد من مشكلات التوافق بين الإصدارات المختلفة أو المصنعين المتعددين لأجهزة أندرويد. مما قد يستغرق وقتًا طويلًا من قبل المطورين لإيجاد حلول بديلة لضمان جودة المنتج النهائي. حاوية جديدة لتطبيقات الويب على أندرويد: نشاط الويب الموثوق يُمكن للمطورين اليوم تضمين صفحة ويب تقدميّة كنشاط تشغيل launch activity في تطبيق أندرويد باستخدام نشاط الويب الموثوق Trusted Web Activity والذي يُمكّن المتصفح من إخراج صفحة الويب التقدميّة ملء الشاشة مما يضمن التوافقية الكاملة مع ميزات منصة الويب وجميع واجهات برمجة التطبيقات التي يستدعيها المتصفح. يوجد العديد من الأدوات المساعدة مفتوحة المصدر لتسهيل تطوير تطبيق أندرويد يستخدم صفحات الويب التقدميّة. من الميزات الإضافية لاستخدام حاوية نشاط الويب الموثوق أن هذه الحاوية تتشارك التخزين مع المتصفح مما يعني أن حالات تسجيل الدخول وتفضيلات المستخدم متاحة لكل منهما بشكل سلس عبر التجارب المتتالية للمستخدمين. توافقية المتصفحات تتوفر هذه الميزة منذ الإصدار رقم 75 للمتصفح Chrome إلا أنها ما زالت قيد التطوير للنسخة القادمة من Firefox. معايير الجودة يجب على مطور الويب استخدام نشاط الويب الموثوق عندما يريد تضمين محتوى الويب في تطبيق أندرويد، إذ يجب أن يُحقق محتوى الويب في نشاط الويب الموثوق معايير إمكانية تثبيت صفحات الويب التقدميّة. بهدف تحقيق توقعات المستخدمين لسلوك تطبيقات أندرويد، أدخلت النسخة 86 من المتصفح Chrome تعديلًا يعدّ الفشل في معالجة أحد السيناريوهات التالية عطلًا: الفشل في التحقق من رابط بروتوكول مشاركة الموارد digital asset links عند تشغيل التطبيق الفشل في إرجاع HTTP 200 عند طلب مورد دون اتصال إعادة HTTP 404 أو خطأ 5xx عند طلب تنقل يتسبب الوقوع في أحد هذه السيناريوهات في نشاط الويب الموثوق بإظهار عطل للمستخدم في تطبيق أندرويد. يجب على المطور التحقق من الإرشادات الخاصة guidance للتعامل مع هذه السيناريوهات في عامل النشاط service worker. يجب أن يُحقق التطبيق المعايير الخاصة بأندرويد مثل سياسة الامتثال policy compliance. تحذير: إذا كان التطبيق مُصمم بشكل أساسي للأطفال تحت سن 13 عامًا، فيجب مراعاة سياسة العائلة على متجر Play store والتي يُمكن أن تمنع من استخدام نشاط الويب الموثوق. يُبين الشكل التالي شارة صفحات الويب التقدميّة والتي تستخدم أداة Lighthouse لإظهار معايير إمكانية التثبيت installability: تحويل تطبيق ويب تقدمي إلى تطبيق أندرويد لا يحتاج مطور الويب الذي يرغب في استخدام نشاط الويب الموثوق إلى تعلم تقنيات أو واجهات برمجة تطبيقات جديدة لتحويل صفحات الويب التقدميّة إلى تطبيق أندرويد، إذ يوفر كل من طوق الفقاعات Bubblewrap وباني صفحات الويب التقدميّة PWABuilder الأدوات اللازمة في مكتبة مخصصة وواجهة سطر أوامر (CLI) وواجهة مستخدم رسومية (GUI). المكتبة Bubblewrap يولد المشروع Bubblewrap تطبيقات أندرويد على شكل مكتبة NodeJS وواجهة سطر أوامر (CLI). يُمكن توليد مشروع جديد عن طريق تنفيذ الأداة مع تمرير رابط URL لملف بيان الويب Web Manifest كما يلي: npx @bubblewrap/cli init --manifest=https://pwa-directory.appspot.com/manifest.json يُمكن للأداة أيضًا بناء المشروع وذلك بتنفيذ الأمر التالي والذي يولد تطبيق أندرويد جاهز للرفع على متجر Play store: npx @bubblewrap/cli build يُصبح الملف app-release-signed.apk متاحًا في مجلد جذر المشروع root بعد تنفيذ الأمر السابق، وهو ما يجب رفعه على المتجر Play store. باني صفحات الويب التقدميّة PWABuilder يُساعد باني صفحات الويب التقدميّة PWABuilder المطورين على تحويل مواقع الويب الحالية إلى صفحات ويب تقدميّة. يتكامل هذا الباني مع المكتبة Bubblewrap لتوفير واجهة مستخدم رسومية تُغلّف صفحات الويب التقدميّة في تطبيق أندرويد. يُمكن العودة لنشرة فريق عمل باني PWABuilder للحصول على تفاصيل أكثر حول توليد الأداة لتطبيق أندرويد. التحقق من ملكية تطبيقات الويب التقدمية في تطبيق أندرويد لضمان عدم استخدام صفحة ويب تقدميّة أي مطور آخر دون استئذان المطور الأصلي لها يجب إقران تطبيق أندرويد مع صفحات الويب التقدمية باستخدام أداة تُدعى روابط الأصول الرقمية Digital Asset Links. يتولى كل من Bubblewrap و PWABuilder الضبط configuration المطلوب على تطبيق أندرويد إلا أنه يتبقى خطوة وحيدة وهي إضافة الملف assetlinks.json إلى صفحات الويب التقدميّة. لإنشاء هذا الملف، يحتاج المطور إلى التوقيع SHA-256 للمفتاح المستخدم لتوقيع ملف APK الذي يُنزله المستخدمون. يُمكن توليد هذا المفتاح بعدة طرق من أسهلها إيجاد المفتاح المتوفر مع ملف APK نفسه الذي ينزله المستخدمون من متجر Play store. لتجنب إظهار تطبيق معطل للمستخدمين، انشر التطبيق أولًا على قناة اختبار مغلقة closed test channel ثم ثبتّه في جهاز اختبار واستخدم أداة Peter's Asset Link Tool لإنشاء ملف الأصول assetlinks.json الصحيح الخاص بالتطبيق وإتاحته على ‎/.well-known/assetlinks.json في النطاق الذي تحققت من صحته. ختامًا توفر صفحات الويب التقدميّة تجربة استخدام عالية الجودة ويُعدّ نشاط الويب الموثوق طريقة جديدة لتحقيق ذلك عند استيفاء الحد الأدنى من معايير الجودة. يُمكنك، إذا كنت في خطواتك الأولى لاستخدام صفحات الويب التقدميّة، قراءة إرشادات إنشاء هذه الصفحات. أما إذا كنت مطورًا لهذه الصفحات فاستخدم أداة Lighthouse للتحقق من أن صفحاتك توافق معايير الجودة المطلوبة. بعدها، استخدم Bubblewrap و PWABuilder لإنشاء تطبيق أندرويد ومن ثم ارفع التطبيق المطور على قناة اختبار مغلقة وأقرنه بصفحات الويب التقدميّة باستخدام Peter's Asset Link Tool في نهاية المطاف انقل تطبيقك المطور من قناة الاختبار إلى الاستخدام للعموم بنشره في متجر التطبيقات. ترجمة -وبتصرف- للمقال Using a PWA in your Android app للكاتب: André Cipriani Bandarra. اقرأ أيضًا ما هي تطبيقات الويب التقدمية ولماذا يجب على المصممين الاهتمام بها؟ تشغيل تطبيقات الويب التقدمية PWA في وضع انقطاع الاتصال نماذج اقتراحات تثبيت تطبيقات الويب التقدمية PWA
  20. يُسهّل تثبيت تطبيقات الويب التقدميّة PWA إيجاده واستخدامه، وعلى الرغم من ترويج المتصفح لتثبيت التطبيق إلا أن بعض المستخدمين لا يدركون أنه يُمكنهم تثبيته، ولذا من المفيد جدًا توفير تجربة داخل التطبيق نفسه للترويج لتثبيت التطبيق. لن تعرض هذه المقالة قائمة شاملة لجميع نماذج الاقتراح لتثبيت تطبيق الويب التقدمي، إلا أنها ستُقدّم نقطة الانطلاق لطرق الاقتراح المختلفة لا سيما أن الشيفرة التي تُشغّل تدفق التثبيت install flow هي نفسها مهما كان النموذج pattern أو النماذج المستخدمة. يُمكن الرجوع إلى المقالة توفير تجربة تثبيت مخصصة داخل التطبيق للحصول على توثيق هذه الشيفرة. يُبين الشكل التالي مثلًا زر تثبيت بسيط في تطبيق: أفضل ممارسات اقتراح تثبيت التطبيق نعرض فيما يلي بعض أفضل الممارسات المُمكنة لاقتراح تثبيت التطبيق، وذلك بغض النظر عن نماذج الاقتراح المستخدمة في موقع الويب: لا تضع الاقتراح ضمن تدفق التثبيت بل خارجه. مثلًا: ضع عبارة الاقتراح أسفل نموذج تسجيل الدخول أي تحت زر الإرسال إذ أن استخدام الاقتراح بشكل مُشتت لانتباه المستخدم سيؤدي إلى تخفيض كل من استخدام التطبيق ومعايير التفاعل معه. يجب أن يتمكن المستخدم من إخفاء أو رفض الاقتراح بسهولة، مع ضرورة حفظ تفضيلات المستخدم عند قيامه بذلك لإعادة إظهار ترويج التثبيت حال حصول تغيير ما في سلوك المستخدم مثل تسجيله للدخول أو إتمامه لعملية شراء مثلًا. حاول الجمع بين أكثر من نموذج للترويج مع مراعاة عدم إغراق المستخدم أو إزعاجه مرارًا وتكرارًا بترويج التثبيت. لا تُظهر الاقتراح إلا بعد إطلاق حدث "قبل طلب التثبيت" `beforeinstallprompt` عند استيفاء معايير معينة ستُظهر المتصفحات ترويجًا تلقائيًا للمستخدم، مثلًا يعرض المتصفح Chrome زر التثبيت في الصندوق متعدد الاستخدام omnibox. يعرض الشكل التالي ترويج المتصفح للتثبيت على نظام سطح المكتب (يسار) وعلى الجوّال (يمين): يعرض المتصفح Chrome في أندرويد الاقتراح ضمن شريط معلومات صغير. يُمكن حجب هذا السلوك باستخدام التابع "حجب السلوك الافتراضي" preventDefault()‎ في الحدث "قبل طلب التثبيت" beforeinstallprompt، أما إذا لم يُستدع هذا التابع فسيُعرض الاقتراح للتطبيق (متوافقًا مع معايير التثبيت في أندرويد) عند أول زيارة للمستخدم للموقع وبعد حوالي تسعين يومًا أيضًا. نماذج الاقتراح في واجهات التطبيق يُمكن استخدام نماذج الاقتراح لمعظم أنواع صفحات الويب التقدميّة مع إظهارها ضمن أقسام واجهات التطبيق مثل لائحة التنقل site navigation والأشرطة banners، مع ضرورة الانتباه لسياق المستخدم الحالي بهدف عدم إزعاجه أو تشتيته. تُحقّق المواقع التي تُطلق ترويج التثبيت في الوقت المناسب أكبر عدد من عمليات التثبيت مع تجنبها مضايقة المستخدم غير المهتم بالتثبيت. زر تثبيت بسيط من أبسط نماذج تجربة المستخدم UX تضمين زر "التثبيت" Install أو "الحصول على التطبيق" Get app في المكان المناسب ضمن محتوى الويب. يجب التأكد من أن الزر لا يُعطّل وظائف هامة أخرى وأنه ليس ضمن مسار تفاعل المستخدم مع التطبيق. يُبين الشكل التالي مثالًا لزر بسيط: ترويسة ثابتة يُمكن وضع زر التثبيت في ترويسة header الموقع، والتي تحوي عادًة العلامة التجارية للموقع والقوائم السريعة. يُمكن أن تكون الترويسة ثابتة position:fixed أم لا، وذلك وفق وظائف الموقع واحتياجات المستخدمين. يُبين الشكل التالي مثالًا لزر تثبيت في الترويسة: يُسهّل استخدم ترويج التثبيت في الترويسة تجربة استخدام سهلة لاسيما للزبائن المعتادين على التعامل مع الموقع. يجب التأكد من أن عبارة الاقتراح الموضوعة في الترويسة لها الحجم المناسب وتبدو بأهمية أكبر من بقية محتوى الترويسة، مع التحقق من عدم تداخلها معه، ومع الإشارة لأهمية كل بيكسل في الترويسة عادًة. وفي جميع الأحوال يجب: عدم إظهار زر التثبيت ما لم يُطلق الحدث beforeinstallprompt. تقييم أهمية تثبيت التطبيق للمستخدمين وبالتالي الاستهداف الانتقائي لهم وبحيث يتم الاقتراح للمستخدمين المحتملين فقط. استخدام الترويسة بكفاءة بحيث يُحقّق التوازن بين ترويج التثبيت وبقية الخيارات الهامة الواجب وضعها في الترويسة أيضًا. يُبين الشكل التالي زر تثبيت مخصص في الترويسة: قائمة التنقل تُعدّ قائمة التنقل navigation menu مناسبة جدًا للترويج لتثبيت التطبيق، لاسيما أن فتح المستخدم لهذه القائمة يدّل بوضوح على تفاعله مع تجربة التطبيق. يجب التأكد مما يلي: تجنب تعطيل محتوى التنقل المهم وذلك بوضع الاقتراح في أسفل القائمة. العرض الموجز والملائم لأهمية التطبيق للمستخدم وماذا يستفيد المستخدم من تثبيته. يُبين الشكل التالي زر ترويج التثبيت في أسفل قائمة التنقل: صفحة الهبوط تُعدّ صفحة الهبوط landing page من الأمكنة المناسبة لوضع ترويج التثبيت، إذ أنها تُستخدم أصلًا للترويج للمنتجات والخدمات المختلفة. بالطبع، يجب عرض أهداف الموقع أولًا ومن ثم اقتراح تثبيت التطبيق. يجب التأكد دومًا مما يلي: إظهار الميزات الأكثر أهمية للتطبيق والتركيز على الكلمات المفتاحية التي قادت المستخدمين لصفحة الهبوط. استخدام شيئًا ملفتًا للنظر مع توضيح قيمة وأهمية التطبيق. وضع الاقتراح في الأقسام التي يتصفحها المستخدمون ويمضون أغلب الوقت فيها . يُبين الشكل التالي مثالًا لترويج التثبيت على صفحة هبوط: شريط التثبيت تُعدّ أشرطة التثبيت installation banners مكانًا مناسبًا لوضع ترويج التثبيت لاسيما أن معظم المستخدمين تعاملوا معها سابقًا وبالتالي تكون تجربتها مألوفة لهم. يجب الانتباه أيضًا لعدم إزعاج أو تشتيت المستخدم عند استخدام الاقتراح على شريط التثبيت. يجب التأكد مما يلي: عدم إظهار الاقتراح ما لم يقم المستخدم بإظهار بعض الاهتمام بالموقع، فإذا أخفى المستخدم الشريط فلا يجب إظهاره ثانيًة ما لم يبرهن المستخدم على رفع مستوى تفاعله مع الموقع كأن يُسجل فيه أو يُكمل عملية شراء منه. تقديم الشرح الكافي والمختصر في الشريط لأهمية تثبيت التطبيق، كأن يُشار إلى المساحة البسيطة التي يُمكن أن يتطلبها التطبيق على الأنظمة المختلفة iOS / Android وأنه سيُثبت فورًا دون الحاجة لإعادة التوجيه لأي متجر. يُبين الشكل التالي شريط قابل للإخفاء في أعلى الصفحة: واجهة مستخدم مؤقتة تُعلّم الواجهة المؤقتة Temporary UI (مثل نموذج تصميم الشريط الخفيف Snackbar) المستخدم بإجراء ما وتسمح له بإتمامه بسهولة. يمتاز استخدام هذه الواجهة لترويج التثبيت بأنه لا يُقاطع تفاعل المستخدم الذي يُمكنه تجاهلها وبالتالي تُخفى الواجهة تلقائيًا. يُبين الشكل التالي استخدام واجهة مؤقتة لإظهار إمكانية التثبيت: يُستحسن عرض الواجهة المؤقتة بعد التأكد من تفاعل المستخدم مع التطبيق، إذ يؤدي ظهور هذه الواجهة حال تحميل التطبيق أو خارج سياق تجربة الاستخدام إلى إرباك المستخدم الذي سيلجأ، بعدها، لرفض كل ما يظهر له. على الأخص، لا يجب إظهار الواجهة المؤقته للمستخدمين الجدد قبل الحصول على مؤشرات اهتمامهم بالتطبيق كتكرار الزيارات أو تسجيل الدخول. يجب التأكد مما يلي: عرض الواجهة المؤقتة لفترة تتراوح بين 4 و 7 ثوانٍ لإتاحة الوقت الكافي للمستخدمين للتفاعل معها دون أي إعاقة لعملهم. تجنب عرض الواجهة المؤقتة على واجهات مؤقتة أخرى مثل الأشرطة banners. عدم استخدام الواجهات المؤقتة قبل التأكد من اهتمام المستخدم مثل تكراره للزيارات أو تسجيله في الموقع أو أي تفاعل مشابهه مع الموقع. يُبين الشكل التالي استخدام واجهة مؤقته لإظهار إمكانية التثبيت: بعد التفاعل يُعدّ إنهاء المستخدم لعملية تفاعل فرصة مناسبة لترويج التثبيت. مثلًا: بعد إتمامه لعملية شراء على موقع تجارة الكترونية حيث يدل ذلك على اهتمام المستخدم بمحتوى الموقع وبأنه سيتفاعل مع خدماته مرًة أخرى. يُبين الشكل التالي إظهار ترويج تثبيت بعد إتمام المستخدم لعملية شراء: إتمام تسلسل تنقل في الموقع أو الخروج منه من المناسب إظهار ترويج التثبيت بعد انتهاء المستخدم من عملية معينة تستلزم مجموعة تنقلات في الموقع كعمليات الشراء أو الحجز. يجب التأكد مما يلي: تضمين الاقتراح المناسب طبقًا لارتباط التطبيق بالعمليات المُنفذّة من قبل المستخدم والمحتمل استفادتهم من التطبيق. إظهار العروض المتاحة بشكل واضح. إبعاد الاقتراح عن تسلسل عمليات المستخدم اللازمة لإتمام عملية تحويل مما قد يؤثر سلبًا على إتمامه للعملية. لاحظ في المثال التالي وضع عبارة طلب الدفع من المستخدم أعلى إعلان ترويج التثبيت: تسلسل التسجيل والدخول والخروج يُعدّ الاقتراح في هذه الحالات حالة خاصة من نمط الاقتراح بعد إتمام تسلسل تنقل إلا أنه يُمكن أن يكون أكثر وضوحًا. يفتح المستخدمون المهتمون بالموقع صفحات التسجيل Sign up والدخول Sign in والخروج Sign out عادًة وحيث أُظهرت أهمية تثبيت التطبيق لهم سابقًا. علاوًة على ذلك، لا تحوي هذه الصفحات عادًة محتوى مفيد ولذا يكون من المناسب وضع الاقتراح فيها لاسيما أنه لن يعرقل تنقلات المستخدم. يجب التأكد مما يلي: تجنب تعطيل تنقلات المستخدم داخل نموذج التسجيل لاسيما إذا احتوى على عدة خطوات إذ يكون من الأجدر انتظار المستخدم لغاية إتمامه لعملية التسجيل. اقتراح ميزات التطبيق المناسبة للمستخدمين المسجلين. وضع زر ترويج إضافي في صفحة تسجيل الدخول للتطبيق. يُبين الشكل التالي زر تثبيت مخصص في صفحة التسجيل: نماذج الاقتراح المُضمّنة تدمج نماذج الاقتراح المُضمّنة Inline promotional patterns عروض الاقتراح مع محتوى الموقع، مما يجعل الاقتراح فيه أكثر ملائمة من وضعه في واجهات المستخدم. وبشكل عام يجب المقايضة والموازنة بين إظهار الاقتراح بما يكفي ليُلاحظه المستخدمون المهتمون والإكثار من إظهاره مما يؤدي لتردي جودة تجربة المستخدم. خلال نشر المحتوى يُمكن إظهار الاقتراح ما بين عمليات نشر المحتوى In-feed الجديد مثل المقالات الجديدة أو بطاقات المعلومات. يجب التركيز على ميزات ووظائف التطبيق المفيدة للمستخدمين لاسيما أن الهدف هو التوضيح للمستخدمين كيفية الوصول للمحتوى المفيد لهم بسهولة. يجب التأكد مما يلي: الحدّ قدر الإمكان من تكرار الاقتراح لتجنب إزعاج المستخدمين. منح المستخدمين إمكانية رفض الاقتراح. حفظ تفضيلات المستخدم (رفضه للترويج). يُبين الشكل التالي إظهار ترويج خلال تغذية المحتوى: ترجمة -وبتصرف- للمقال Patterns for promoting PWA installation للمؤلفين: Penny McLachlan و Mustafa Kurtuldu. اقرأ أيضًا ما هي تطبيقات الويب التقدمية ولماذا يجب على المصممين الاهتمام بها؟ تشغيل تطبيقات الويب التقدمية PWA في وضع انقطاع الاتصال شرح ملف البيان manifest لتطبيق الويب التقدمي PWA تهيئة تطبيقات الويب التقدمية PWA لاستخدامها كتطبيقات أندرويد
  21. تُعدّ مرحلة ضبط إعدادات قوائم المتجر من طرف مدير المتجر في البداية من أهم مراحل إدارة المتجر عمليًا لاسيما أن جميع خيارات الإدارة في هذه المرحلة ستنعكس في عمليات تشغيل المتجر والتفاعل مع عملائه. تحوي خيارات القائمة "واجهة المتجر" من "قائمة التحكم بالمتجر" جميع روابط الصفحات التي تسمح لمدير المتجر بإدارة بيانات الصفحات المختلفة (واجهة المتجر) التي يتعامل معها زوار وعملاء المتجر. عرضنا في الدرس السابق خياري إدارة الأقسام وإدارة المنتجات، ونكمل نعرض في هذا الدرس جميع بقية الخيارات والتي تسمح لمدير النظام بضبط جميع إعدادات صفحات المتجر مثل عوامل التصفية (الفلاتر) التي يُمكن وضعها في الصفحات لتسهيل الوصول إلى المنتجات أو طريقة دفع العميل بالتقسيط وغيرها من الإعدادات المختلفة. هذا المقال جزء من سلسلة تعريفية بلوحة تحكم متجر أوبن كارت، إليك فهرس مقالات كامل السلسلة: مدخل إلى متجر أوبن كارت وكيفية تثبيته إدارة الأقسام والمنتجات في متجر أوبن كارت التعرف على إعدادات واجهة متجر أوبن كارت تعلم كيفية ضبط متجر أوبن كارت شرح الإضافات والقوالب في لوحة تحكم متجر أوبن كارت نظرة على خيارات التسويق التي يوفرها متجر أوبن كارت التقارير والإحصائيات: نافذة على أداء متجر أوبن كارت إعدادات الدفع والشحن في متجر أوبن كارت المدفوعات المتكررة Profiles تُستخدم المدفوعات المتكررة في حال الرغبة بتقسيط ثمن المنتجات على شكل دفعات دورية (كطريقة من طرق التسويق وتحفيز العملاء). مثلًا: بفرض أننا نريد تقسيط سعر الكتاب على دفعتين وذلك بمعدل دفعة واحدة كل شهر. يجب أولًا تعريف "مدفوعات متكررة" جديدة من صفحة "المدفوعات المتكررة" من "واجهة المتجر" كما يلي: تحوي صفحة "المدفوعات المتكررة" الحقلين التاليين: الاسم Name: يجب إعطاء اسم للمدفوعات المتكررة. ترتيب الفرز Sort Order: ترتيب عرض المدفوعات. والقسمين التاليين: المدفوعات المتكررة والمدفوعات المتكررة التجريبية. أما قسم المدفوعات المتكررة، فيحوي الحقول التالية: السعر Price: السعر الإجمالي. الفترة Duration: عدد مرات تحصيل الدفعات من العميل. يُمكن وضع القيمة صفر في حال الرغبة بتحصيل الدفعات بشكل مستمر (حالات الاشتراك مثلًا) إلى أن يتم إلغاء التحصيل. الدورة Cycle: عدد مرات التكرار. مثلًا: إذا تم تحديد التكرار كل أسبوع والدورة 2، سيتم تحصيل دفعة من العميل كل أسبوعين. التكرار Frequency: يُمكن الاختيار من القائمة الموافقة: يوم، أسبوع، شهر، سنة. الحالة Status: "تمكين" أم "تعطيل". أما قسم المدفوعات المتكررة التجريبية، فيوفر إمكانية إضافة فترة تجريبية للمدفوعات المتكررة، يُمكن أن تكون مثلًا فترة تجريبية مجانية، ويكون لهذا القسم حقول مشابهة للقسم السابق. ملاحظة: لا تعمل المدفوعات المتكررة مع طرق الدفع العادية مثل التحويل البنكي أو باي بال العادي، بل تعمل فقط مع بوابات الدفع التي تقبل المدفوعات المتكررة مثل باي بال اكسبرس. لاستخدام "مدفوعات متكررة" مع منتج، نُضيف هذه المدفوعات إلى المنتج من التبويب "المدفوعات المتكررة للمنتج" في صفحة المنتج. مثلًا نُضيف هذه المدفوعات إلى كتاب "تعلم الآلة" الذي أضفناه من المقال السابق: يُمكن الآن للعميل في واجهة المتجر اختيار الدفع تقسيطًا كما يُبين الشكل التالي: الفلاتر Filters يُسهّل الفلتر عملية وصول العميل إلى الأقسام والمنتجات بسرعة إذ قد يؤدي استخدام حقول البحث البسيطة المتوفرة افتراضيًا، في الكثير من الأحيان، إلى ظهور نتائج كثيرة تملأ الواجهة لاسيما إذا كان المتجر يحوي على عدد كبير من المنتجات. مثلًا: لنفرض في مثال قسم "الكتب " والذي يوجد فيه قسم فرعي "علوم الحاسوب" أننا نريد تقسيم كتب الحاسوب إلى فئات متعددة مثل "الذكاء الاصطناعي" و "الخوارزميات" و "تصميم الويب". يُمكن طبعًا إنشاء أقسام فرعية لها، إلا أنه قد يكون من الأسهل إنشاء فلتر لها كي لا نتشعب كثيرًا في تفريع الأقسام. يؤدي إنشاء الفلتر إلى ظهور قسم "بحث محسن" في واجهة المتجر (بعد تمكين الفلاتر) يُساعد العميل في الوصول للمنتج المطلوب بسرعة. إدراج مجموعة فلاتر جديدة يُمكن فتح صفحة "الفلاتر" من "واجهة المتجر" ثم إدراج مجموعة فلتر جديدة. يُبين الشكل التالي مجموعة الفلتر "أنواع كتب علوم الحاسوب" والتي تحوي ثلاثة فلاتر: "الذكاء الاصطناعي" و "الخوارزميات" و "تصميم الويب": تحوي صفحة "الفلاتر" على قسمين: الأول قسم "مجموعة الفلتر" Filter Group والذي يحوي الحقلين التاليين: اسم مجموعة الفلتر Filter Group Name: يجب إدخال اسم لمجموعة الفلتر. فرز الطلب Sort Order: ترتيب الفرز. أما القسم الثاني فهو قسم "قيمة الفلتر" Filter Values والذي يحوي الحقلين التاليين (جدول): اسم الفلتر Filter Name: يجب إدخال اسم للفلتر. فرز الطلب Sort Order: ترتيب الفرز. ربط الفلاتر مع الأقسام يُمكن ربط الفلاتر مع الأقسام: مثلًا: يُمكن ربط الفلاتر السابقة مع قسم "علوم الحاسوب" بتحرير قسم "علوم الحاسوب" واختيار الفلاتر في التبويب "بيانات" كما يُبين الشكل التالي: يُمكن النقر بالفأرة في حقل الفلاتر أو كتابة حرف أو أكثر من اسم الفلتر لاختيار فلتر . ربط الفلاتر مع المنتجات يُمكن ربط الفلاتر مع منتج. مثلًا: يُمكن ربط الفلتر "كتب>علوم الحاسوب" مع الكتاب "مقدمة في الذكاء الاصطناعي" بتحرير المنتج "مقدمة في الذكاء الاصطناعي" ومن ثم اختيار الفلتر في التبويب "روابط" كما يُبين الشكل التالي: تمكين موديول الفلاتر يجب تمكين موديول الفلاتر الذي يكون معطلًا بشكل افتراضي بالانتقال إلى صفحة "الإضافات" من "لوحة التحكم" كما يُبين الشكل التالي: ثم ننتقل إلى سطر الفلاتر: يجب أولًا تثبيت موديول الفلاتر (غير مثبت افتراضيًا) وذلك بالنقر على الزر الأحمر "تثبيت" في سطر الفلاتر ثم تحرير سطر الفلاتر وتعديل "الحالة" إلى "تمكين": تسمح إضافة هذا الموديول بإجراء عمليات الفلترة في صفحات المتجر المختلفة. تحديد مكان ظهور الفلاتر في الصفحات يُمكن تحديد مكان ظهور الفلتر في الصفحات المختلفة للمتجر بالانتقال إلى صفحة "صفحات" من "تصميم" ثم "صفحات": يُمكن تحرير "صفحة أقسام الموقع" مثلًا ومن ثم اختيار "الفلاتر" لتكون في العمود الأيسر كما يُبين الشكل التالي: نقوم بنفس الخطوات السابقة في "صفحة المنتج". تجربة الفلاتر في واجهة المتجر بعد تنفيذ الخطوات السابقة، نفتح واجهة المتجر (كعميل) ثم ننتقل لقسم الكتب لنجد "بحث محسن" يسار الصفحة. كذلك تظهر في صفحة المنتج: مواصفات المنتجات Attributes تُمكّن إعدادات المواصفات من إضافة مواصفات جديدة للمنتجات مثل إضافة سرعة المعالج وحجم الذاكرة للحواسيب مثلًا. يحتوي الخيار "مواصفات المنتجات" خيارين فرعيين هما "مواصفات المنتجات" و"أنواع المواصفات". مثلًا: سنضيف للكتب في المتجر المواصفات التالية: عدد صفحات الكتاب ووجود غلاف فني للكتاب أم لا. يجب أولًا إعداد أنواع المواصفات من صفحة "أنواع المواصفات". مثلًا نضيف المواصفة "فنية" من أجل الكتب: تحتوي صفحة "أنواع المواصفات" Attribute Groups الحقلين التاليين: اسم نوع الوصف Attribute Name: يجب إدخال اسم لنوع (مجموعة) الوصف. ترتيب الفرز Sort Order: ترتيب الفرز. كما يجب إعداد مواصفات المنتجات من صفحة "مواصفات المنتجات، مثلًا نضيف "عدد الصفحات" و "غلاف فني": تحتوي صفحة "مواصفات المنتجات" Attributes الحقلين التاليين: اسم الوصف Attribute Name: يجب إدخال اسم للوصف. نوع الوصف Attribute Group: يُمكن الاختيار من قائمة أنواع الوصف. ترتيب الفرز Sort Order: ترتيب الفرز. يُمكن إضافة المواصفات لمنتج من تبويب "المواصفات" في صفحة المنتج: تظهر المواصفات للعميل في صفحة المنتج في واجهة المتجر كما يُبين الشكل التالي: تُستخدم المواصفات أيضًا للمقارنة بين المنتجات مثلًا: يُمكن للعميل مقارنة المواصفات "الفنية" لبعض الكتب وذلك بإضافة كل كتاب أولًا إلى المقارنة وذلك بالنقر على زر "إضافة للمقارنة" في صفحة كل كتاب: يُمكن بعدها للعميل فتح صفحة "مقارنة المنتجات" إما من الرابط "قائمة المقارنة" والذي يظهر بعد طلب المقارنة: أو من الرابط "مقارنة المنتج" الذي يظهر في قسم الكتب الموافق: تُظهر صفحة مقارنة المنتجات التالية المواصفات التي أُضيفت للمنتجات إضافًة لمواصفاتها الأساسية: خيارات المنتجات Options تسمح الإعدادات "خيارات" بإضافة خيارات جديدة مخصصة للمنتجات مثل الألوان والمقاسات وغيرها. يُمكن مثلًا إضافة الخيار "طباعة الكتاب" (اختيار من قائمة: "طالب" للطباعة بدون تجليد فني، "فنية" للطباعة مع تجليد فني أنيق). نُضيف الخيار "نسخة الكتاب" (اختيار من قائمة: "طالب"، "فنية") في صفحة "خيارات": تحتوي صفحة "خيارات" قسمين: قسم الخيار Option والذي يحوي الحقول التالية: اسم الخيار Option Name: اسم الخيار الجديد. النوع Type: يُمكن الاختيار من 4 مجموعات: اختار (قائمة منسدلة، راديو، تحديد) ادخال (نص، حقل نصي) ملف (ملف) تاريخ (تاريخ، وقت، التاريخ والوقت) ترتيب الفرز Sort Order: ترتيب الفرز. والقسم الثاني هو قسم قيمة الخيارات Option Values، ويظهر هذا القسم في حالة اختيار النوع من المجموعة "اختار" وذلك لكتابة الخيارات المختلفة. يحوي الحقول التالية: قيمة اسم الخيار Option Value Name: قيمة الخيار. الصورة Image: الصورة. ترتيب الفرز Sort Order: ترتيب الفرز. لاحظ أنه يُمكن إضافة الخيار إلى المنتجات من التبويب "خيارات" في صفحة المنتج. مثلًا: يتوفر لكتاب "مقدمة في الذكاء الاصطناعي" نوعين من النسخ: "طالب" و"فنية". يُمكن القيام بالإعدادات التالية في تبويب "خيارات" للكتاب: يُمكن تغيير كل من السعر والنقاط والوزن حسب كل قيمة من قيم خيارات "نسخة الكتاب". لاحظ مثلًا إنقاص سعر الكتاب في المثال السابق لنسخة "طالب" بقيمة 10 مع 5 نقاط إضافية للعميل. تظهر هذه الخيارات في صفحة المنتج للعميل في واجهة المتجر: الشركات المُصنّعة Manufacturers يسمح هذا الإعداد بتعريف الشركات المُصنّعة للمنتجات. تحتوي صفحة "الشركة" على تبويبين: التبويب "عام" General يحوي الحقول التالية: اسم الشركة Manufacturer name: يجب كتابة اسم الشركة. المتاجر Stores: يكون المتجر الافتراضي محدّدًا. يُمكن اختيار أكثر من متجر في حل إدارة متاجر متعددة. الصورة Image: يُمكن اختيار صورة للشركة. تبويب "روابط السيو" SEO يُمكن كتابة كلمات السيو لكل متجر من خلال هذا التبويب وذلك بغرض جعل صفحة الشركة صديقة لمحركات البحث. يحوي هذا التبويب الحقول التالية: المتاجر Stores: اسم المتجر. كلمات السيو SEO keywords: كلمات السيو والتي تسمح تجعل صفحة الشركة صديقة لمحركات البحث. إضافة الشركات المُصنّعة للمنتجات يُمكن إضافة شركة لمنتج من التبويب "روابط" للمنتج. يُمكن للعميل من واجهة المتجر استعراض منتجات شركة معينة بفتح رابط "الشركات" تحت "إضافات" في الشريط أسفل الصفحة: يُبين الشكل التالي صفحة "الشركة" في واجهة المتجر: وعند اختيار شركة معينة تظهر صفحة منتجات هذه الشركة: ملفات التنزيل Downloads تحوي صفحة "ملفات التنزيل" الحقول التالية: اسم ملف التنزيل Download Name: يجب كتابة اسم للملف. اسم الملف Filename: يجب رفع Upload ملف على الموقع. اسم قناع للملف Mask: يجب كتابة اسم مختلف عن اسم الملف لمنع الأشخاص من الوصول إلى الملف من الرابط الأساسي للملف. تُمكّن هذه الصفحة من رفع ملفات وذلك لإرفاقها مع المنتجات. يُمكن وضع الملف السابق مع كتاب "مقدمة في الذكاء الاصطناعي" مثلًا: التقييم Reviews تسمح صفحة "التقييم" لمدير النظام بمعاينة جميع التقييمات التي قام بها العملاء، كما يُمكن له تحرير هذه التقييمات والموافقة على عرضها أم لا. كما يُمكن لمدير المتجر السماح بالتقييمات من "الضبط" ثم "الإعدادات" ثم تحرير المتجر ثم التبويب "خيارات": يستطيع العميل مشاهدة التقييمات السابقة للعملاء في واجهة المتجر، أو كتابة التقييم لمنتج معين من صفحة المنتج في واجهة المتجر: معلومات Information يُمكن من خلال صفحة "معلومات" كتابة كل المعلومات المطلوب عرضها لروابط قسم المعلومات في أسفل واجهة المتجر: تحوي صفحة "معلومات" بشكل افتراضي 4 روابط يُمكن الإضافة إليها أو تعديلها. خاتمة أنهينا في هذا الدرس شرح مختلف خيارات إعدادات صفحات المتجر والتي تسمح لمدير المتجر بتخصيص طرق التعامل المختلفة مع العملاء. نعرض في الدرس القادم عمليات الضبط اللازمة لإدارة المتجر بشكل كامل والتحكم بكافة خياراته الممكنة. اقرأ أيضًا الخطوات الابتدائية لإنشاء متجرك الإلكتروني: عنوان المتجر وحجز النطاق (Domain) كيف تستخدم شركات التجارة الإلكترونية واجهات متعددة لإدارة مجموعات مختلفة من العملاء استخدام التخصيص Personalization لزيادة متوسط قيمة الطلب AOV ومعدلات التحويل في المتاجر الإلكترونية
  22. تتيح معظم المتصفحات تثبيت تطبيق صفحات الويب التقدميّة PWA والترويج له من داخل واجهات التطبيق مباشرًة، مما يُسهّل عملية تثبيت التطبيق (إضافته إلى الشاشة الرئيسة Add to Home Screen) سواًء على الجوّال أو على سطح المكتب. يؤدي تثبيت التطبيق إلى إضافته للمُشغّل launcher وبالتالي تشغيله مثل أي تطبيق آخر. يُمكن لمطور التطبيق تخصيص تسلسل خطوات تثبيته مباشرًة داخل التطبيق وذلك إضافًة لسلوك التثبيت المتوفر في المتصفح. من الأفضل الآخذ بعين الاعتبار لاستخدامات التطبيق PWA قبل التخطيط لترويج تثبيته promote install. فمن أجل التطبيقات التي يُشغلّها المستخدمون عدة مرات في الأسبوع، سيكون من المريح لهم تشغيل التطبيق من الشاشة الرئيسية للجوّال أو من قائمة ابدأ Start menu في نظام تشغيل سطح المكتب. أما بالنسبة لتطبيقات الإنتاج والترفيه، فسيكون من الأنسب تشغيلها في وضع ملء الشاشة بعد إزالة أشرطة أدوات المتصفح للاستفادة من كامل المساحة الممكنة وذلك باستخدام أحد الوضعين: المستقل standalone أو الحد الأدنى لواجهة المستخدم minimal-ui. يُبين الشكل التالي زر التثبيت Install App في التطبيق Spotify مثلًا: اقتراح تثبيت تطبيق الويب التقدمي لتوضيح إمكانية تثبيت تطبيق PWA وتوفير تسلسل مخصص لخطوات التثبيت من داخل التطبيق: استمع لحدث "قبل طلب التثبيت" beforeinstallprompt. احفظ الحدث beforeinstallprompt لاستخدامه لاحقًا في تشغيل خطوات التثبيت. أعلم المستخدم بإمكانية تثبيت التطبيق ووفر زر أو عنصر آخر لتبدأ منه خطوات التثبيت. ملاحظة: أُزيل كل من الحدث beforeinstallprompt والحدث appinstalled من توصيف ملف بيان التطبيق manifest file إلى ملف حضانة بيان الويب (وهو ملف يحوي المواصفات غير المعتمدة لغاية الآن بشكل نهائي). التزم فريق تطوير المتصفح Chrome بدعم هذه الأحداث وعدم إزالتها أو توقيفها، كما يواصل فريق التطوير Web DevRel من Google التوصية باستخدامها لتوفير تجربة تثبيت مخصصة. الاستماع لحدث "قبل طلب التثبيت" إذا كان التطبيق يحترم معايير التثبيت المطلوبة، فسيشغّل المستعرض حدث "قبل طلب التثبيت" beforeinstallprompt. يجب حفظ مرجع لهذا الحدث وتحديث واجهة المستخدم لتدل على إمكانية التثبيت: // ‫تهيئة المتغير deferredPrompt للاستخدام اللاحق كي يعرض المتصفح طلب التثبيت للمستخدم let deferredPrompt; window.addEventListener('beforeinstallprompt', (e) => { // منع شريط المعلومات الصغير من الظهور على الجوّال e.preventDefault(); // حفظ الحدث لتشغيله لاحقًا deferredPrompt = e; // تعديل واجهة المستخدم لإعلامه بإمكانية تثبيت التطبيق showInstallPromotion(); // يُمكن بشكل خياري تشغيل حدث التحليل لإعلامه بأنه عُرض للمستخدم ترويج للتطبيق console.log(`'beforeinstallprompt' event was fired.`); }); ملاحظة: يوجد العديد من النماذج المختلفة التي يُمكن استخدامها لإعلام المستخدم بإمكانية تثبيت التطبيق وتوفير تسلسل خطوات التثبيت داخل التطبيق. من النماذج الشهيرة وضع زر في الترويسة header أو عنصر في قائمة التنقل navigation menu أو عنصر في تغذية المحتوى content feed. خطوات التثبيت من داخل التطبيق يُمكن إتاحة التثبيت من داخل التطبيق بتوفير زر أو أي عنصر واجهة آخر بحيث تبدأ خطوات التثبيت عند النقر عليه، وعندها يجب استدعاء التابع "طلب" prompt على الحدث "قبل طلب التثبيت" beforeinstallprompt المحفوظ في المتغير deferredPrompt، والذي يُظهر مربع حوار منبثق شرطي طالبًا من المستخدم تأكيد رغبته بتثبيت التطبيق. buttonInstall.addEventListener('click', async () => { // إخفاء ترويج تثبيت التطبيق hideInstallPromotion(); // إظهار طلب التثبيت deferredPrompt.prompt(); // انتظار تجاوب المستخدم مع الطلب const { outcome } = await deferredPrompt.userChoice; // إرسال حدث تحليل خيارات المستخدم بشكل اختياري console.log(`User response to the install prompt: ${outcome}`); // إزالة الطلب المُستخدّم إذ لا يُمكن استخدامه ثانيًة deferredPrompt = null; }); تُعدّ الخاصية "خيار المستخدم" userChoice بمثابة وعد promise يتحقق حال اختار المستخدم رفض أو قبول التثبيت. يُمكن استدعاء التابع prompt على الحدث المؤجل مرة واحدة، أما إذا رفض المستخدم الطلب فيجب الانتظار حتى تشغيل الحدث beforeinstallprompt مرًة أخرى (بعد تحقيق الوعد userChoice مباشرًة). التحقق من تثبيت تطبيق الويب التقدمي يُمكن استخدام الوعد "خيار المستخدم" userChoice لتحديد فيما إذا ثبّت المستخدم التطبيق من داخل واجهته، أما إذا كان التثبيت من شريط العنوان أو من أي مكون في المتصفح فلن يُساعد هذا الوعد بأي شيء وعندها يجب الاستماع للحدث appinstalled الذي يُطلق عندما يُثبت التطبيق دون النظر لآلية التثبيت. window.addEventListener('appinstalled', () => { // إخفاء ترويج تثبيت التطبيق hideInstallPromotion(); // مسح المتغير ليُزال في مرحلة التنظيف deferredPrompt = null; // إضافة حدث التحليل للإعلام عن تثبيت ناجح بشكل اختياري console.log('PWA was installed'); }); الكشف عن آلية فتح التطبيق يُحدّد استعلام الوسائط لخاصية "نمط العرض" display-mode من الأنماط CSS طريقة فتح التطبيق وذلك إما في تبويب المتصفح أو كتطبيق مُثبّت، وبالتالي يُمكن تطبيق أنماط styles مختلفة وفق كيفية فتح التطبيق. مثلًا: يجب إخفاء زر التثبيت وتوفير زر الرجوع Back عند الفتح كتطبيق منفصل. تتبع آلية فتح التطبيق يُمكن استخدام التابع matchMedia لاختبار استعلام الوسائط display-mode لتتبع كيفية فتح التطبيق من قبل المستخدمين. بما أن المتصفح Safari على iOS لا يدعم ذلك حتى الآن، فيجب اختبار قيمة الراية navigator.standalone والتي تكون صحيحة إذا كان المتصفح يعمل بوضع "المستقل" standalone. function getPWADisplayMode() { const isStandalone = window.matchMedia('(display-mode: standalone)').matches; if (document.referrer.startsWith('android-app://')) { return 'twa'; } else if (navigator.standalone || isStandalone) { return 'standalone'; } return 'browser'; } تتبع تغيير وضع العرض يُمكن الاستماع لتغيرات قيمة استعلام الوسائط display-mode لمعرفة فيما إذا انتقل المستخدم من الوضع المستقل standalone إلى وضع تبويب المتصفح browser tab. window.matchMedia('(display-mode: standalone)').addEventListener('change', (evt) => { let displayMode = 'browser'; if (evt.matches) { displayMode = 'standalone'; } // إعلام التحليل بتغيير العرض console.log('DISPLAY_MODE_CHANGED', displayMode); }); تحديث واجهة المستخدم وفق نمط العرض الحالي يُمكن تطبيق ألوان خلفية مختلفة عند فتح التطبيق كأي تطبيق مثبّت باستخدام تنسيق CSS شرطي: @media all and (display-mode: standalone) { body { background-color: yellow; } } تحديث أيقونة واسم التطبيق يُمكن استخدام ملف بيان الويب لتحديث أيقونة واسم التطبيق. للمزيد يُمكن العودة إلى كيف يعالج المتصفح تحديثات ملف بيان الويب. ترجمة -وبتصرف- للمقال How to provide your own in-app install experience للمؤلف Pete LePage. اقرأ أيضًا مدخل إلى تطبيقات الويب التقدمية PWA تشغيل تطبيقات الويب التقدمية PWA في وضع انقطاع الاتصال شرح ملف البيان manifest لتطبيق الويب التقدمي PWA نماذج اقتراحات تثبيت تطبيقات الويب التقدمية PWA
  23. تحوي خيارات القائمة "واجهة المتجر" من "قائمة التحكم بالمتجر" Navigation جميع روابط الصفحات التي تسمح لمدير المتجر بإدارة بيانات الصفحات المختلفة (واجهة المتجر) التي يتعامل معها زوار وعملاء المتجر. نعرض في هذا الدرس عمليات إدارة الأقسام والمنتجات في المتجر. ونعرض في الدرس التالي جميع بقية الخيارات الممكنة. ملاحظة: يأتي أوبن كارت التي ثبتناها في المقال الأول السابق من السلسلة مع مجموعة تعليمية من البيانات المُدخلة مُسبقًا، ويُمكن، بالطبع، حذفها أو تعطيلها بسهولة. سنُحافظ على هذه البيانات ونزيد عليها في أمثلتنا التعليمية التالية. هذا المقال جزء من سلسلة تعريفية بلوحة تحكم متجر أوبن كارت، إليك فهرس مقالات كامل السلسلة: مدخل إلى متجر أوبن كارت وكيفية تثبيته إدارة الأقسام والمنتجات في متجر أوبن كارت التعرف على إعدادات واجهة متجر أوبن كارت تعلم كيفية ضبط متجر أوبن كارت شرح الإضافات والقوالب في لوحة تحكم متجر أوبن كارت نظرة على خيارات التسويق التي يوفرها متجر أوبن كارت التقارير والإحصائيات: نافذة على أداء متجر أوبن كارت إعدادات الدفع والشحن في متجر أوبن كارت الأقسام Categories في متجر أوبن كارت يجب أولًا تصنيف منتجات المتجر ضمن أقسام (فئات) Categories لنتمكن لاحقًا من إضافة المنتجات إلى المتجر تحت الأقسام المختلفة. يُمكن أن يحوي القسم الواحد على أقسام فرعية وهكذا دواليك أي أن الأقسام، في نهاية المطاف، تُرتّب في هرميات مُتعدّدة. تظهر رؤوس هذه الهرميات (الأقسام الأساسية) للعميل في الشريط العلوي من واجهة المتجر: مثلًا: سنضيف، فيما يلي، قسمًا جديدًا باسم "الكتب" ونضع فيه قسمين فرعيين "علوم الحاسوب" و "روايات". كما سنضيف لقسم "علوم الحاسوب" قسمين فرعيين "الذكاء الاصطناعي" و "الخوارزميات". تظهر الأقسام للعميل في القائمة الرئيسية العليا من واجهة المتجر، كما تظهر على اليمين في صفحة كل قسم: ننصح قبل إضافة الأقسام في المتجر بمعاينة الأقسام الموجودة على المواقع الشهيرة مثل "سوق" وموقع "أمازون"، إذ يكون لهذه المواقع الكبيرة سنوات من الخبرة في كيفية تقسيم المنتجات، كما أن العميل الذي يستخدم المتجر سيجد أن تقسيم الأقسام مشابه لما هو معتاد عليه مما يُسهّل عليه الوصول للمنتجات بشكل أسرع. استعراض الأقسام من "واجهة المتجر"، ننقر الخيار "الأقسام" لفتح صفحة "الأقسام": يُمكن النقر على الترويسة "اسم القسم" لترتيب الأقسام أبجديًا وفق اسم القسم تصاعديًا أو تنازليًا (بإعادة النقر في كل مرة) كما يُمكن النقر على "ترتيب الفرز" لترتيب الأقسام وفق قيمة ترتيب الفرز. توضع الإشارة (>) بين القسم الأساسي والقسم الفرعي التابع له. مثلًا: يُحدّد العمود "ترتيب الفرز" ترتيب ظهور الأقسام في قائمة الأقسام سواءً في القائمة الرئيسية للموقع أو في قائمة الأقسام التي تظهر يمين صفحة المنتجات. يُمكن حذف أو تعديل أو إضافة قسم باستخدام الأزرار الموافقة كما يُبين الشكل التالي: إنشاء قسم جديد ننقر بالزر الأيمن على زر الإضافة (+) أعلى الصفحة لفتح صفحة قسم جديد. تتألف صفحة القسم من أربعة تبويبات نعرضها فيما يلي. التبويب "عام" General يحوي هذا التبويب تبويب للغة العربية وتبويب للغة الإنكليزية. ملاحظة: الحقول التي يكون بجانبها نجمة حمراء هي حقول واجبة الإدخال أي لا يُمكن تركها فارغة. تذكر، يكون لكل نتيجة من نتائج بحث محركات البحث عنوان Title عليه رابط للمقال ووصف Description تحت العنوان، مما يعني ضرورة إدخال عنوان ووصف للصفحات التي نريد لمحركات البحث إظهارها في نتائجها الأمر الذي يساعد في تحسين ظهور صفحاتك وعرضها على صفحة نتائج محركات البحث. يحوي التبويب "عام" الحقول التالية: اسم القسم Category Name: يجب إدخال اسم القسم. الوصف Description: يُمكن إدخال وصف تعريفي للقسم. عنوان ميتا تاج Meta Tag Title: وهو العنوان الذي سيظهر لصفحة القسم في نتائج محركات البحث وفي علامات تبويب المتصفح وعند مشاركة صفحة القسم على وسائل التواصل الاجتماعي. وهو حقل واجب الإدخال وطوله الأعظمي 255 حرف. يجب أن يكون هذا العنوان فريدًا لكل قسم ويُستحسن أن يكون طوله بين 50-60 حرف، ومبتا Meta تعني البيانات الوصفية التي تصف الشيء وهنا تصف صفحة المتجر. وصف ميتا تاج Meta Tag Description: وهو الوصف التعريفي القصير الذي يظهر لصفحة القسم في نتائج البحث. يجب أن يكون الوصف التعريفي جذابًا لتشجيع المستخدم على النقر للدخول إلى صفحة القسم في المتجر. كلمات ميتا تاج Meta Tag Keywords: وهي الكلمات الرئيسية التي تصف صفحة القسم ويجب فصلها بفواصل أجنبية (,). تُساعد هذه الحقول محركات البحث في الوصول إلى الصفحة المعنية إذ أنها تُعلّم محرك البحث بمضمون الصفحة. التبويب "بيانات" Data يحوي هذا التبويب الحقول التالية: القسم الأصلي Parent Category: يُمكن إنشاء قسم (ندعوه قسم فرعي) تحت قسم آخر (ندعوه قسم أساسي). يُعرض القسم في قائمة الأقسام بالشكل: "قسم أساسي > قسم فرعي". في حال ترك هذا الحقل فارغًا، يكون القسم الجديد قسمًا أساسيًا. مثلًا: لوضع قسم "علوم الحاسوب" تحت قسم "كتب"، يجب إدخال "كتب" في حقل "القسم الأصلي": ملاحظة: يُمكن البدء بالكتابة (حرف أو أكثر من اسم القسم الرئيسي) ضمن الحقل الموافق لفتح قائمة الاختيار لانتقاء قسم ما منها. المرشحات Filters: يُمكن اختيار مجموعة من المرشحات للقسم (سنشرحها في الدرس الثالث). المتاجر Stores: يُمكن اختيار مجموعة المتاجر المطلوب إظهار هذا القسم فيها في حال إدارة الموقع لأكثر من متجر. يُترك هذا الحقل فارغًا في حالة المتجر الوحيد. صورة Image: يُمكن اختيار صورة للقسم. ملاحظة: يؤدي تحرير أي حقل "صورة" إلى فتح واجهة إدارة الصور التالية والتي تسمح بإنشاء مجلدات لتنظيم الصور المحفوظة فيها. كما تسمح برفع أي صورة إلى الموقع: نُنشئ مثلًا مجلد "كتب" بداخله مجلدين فرعيين: ثم ننتقل إلى المجلد "حاسوب" ونرفع عدد من الصور لأغلفة الكتب المختلفة فيه: العرض في القائمة العلوية Top: يؤدي تحديد صندوق الاختيار إلى عرض القسم في القائمة العليا التي تظهر في كل صفحة في واجهة المتجر. أما إذا لم يتم التحديد فلا يظهر القسم في هذه القائمة. لاحظ أنه لا يُمكن إظهار قسم فرعي في القائمة العليا. عدد الأعمدة Columns: يُحدّد هذا الحقل عدد الأقسام الفرعية التي تُعرض عند اختيار القسم الرئيسي. يجب الانتباه إلى عدم وضع قيمة كبيرة في هذا الحقل كي لا تغطي قائمة الأقسام الفرعية الصفحة عند فتحها. ترتيب الفرز Sort Order: يُحدّد هذا الرقم ترتيب ظهور القسم في قائمة الأقسام. الحالة Status: يؤدي اختيار القيمة "تمكين" إلى ظهور القسم في واجهة المتجر أما في حال اختيار القيمة "تعطيل"، فلا يظهر القسم للعميل. التبويب "روابط السيو" SEO يحوي هذا التبويب حقل كلمات السيو لكل من اللغتين العربية والإنكليزية، وهو حقل غير إلزامي إلا أنه ضروري في حال الرغبة أن تكون صفحة القسم صديقة لمحركات البحث بمعنى أن يُستبدل الرابط الافتراضي للقسم برابط آخر يحوي كلمات السيو مما يؤدي إلى مساعدة محركات البحث في الوصول للصفحة. مثلًا: إذا أدخلنا للقسم "كتب" كلمات السيو التالية: سيكون رابط صفحة قسم الكتب عند فتح القسم "كتب": ‏ Opencart/الأقسام-كتب عوضًا عن الرابط الافتراضي لها والذي يكون مثلًا: /opencart/index.php?route=product/category&path=59 ملاحظات: يجب وضع إشارة (-) بين الكلمات (أي لا توضع فراغات بينها). يجب وضع كلمات فريدة لكل قسم. إذا وضعت نفس الكلمات لأكثر من قسم، سيؤدي ذلك إلى خطأ إذ ستُستخدم لقسم واحد فقط. يجب القيام بما يلي للسماح باستخدام روابط السيو: أولًا: تحديد الخيار "نعم" للحقل "استخدام روابط الـ SEO" من تبويب "السيرفر" في صفحة "الإعدادات" والتي نصل إليها من خيار "الضبط" من "لوحة التحكم" ثم "الإعدادات" ثم تحرير المتجر الحالي كما يُبين الشكل الآتي. ثانيًا: تعديل اسم الملف الموجود في المجلد الرئيسي للمتجر من htaccess.txt إلى htaccess.. التبويب "التصميم" Design يُمكن ربط صفحة القسم بتخطيط مُجهز مُسبقًا أو يمكن تركها بدون أي تخطيط ليكون لها التخطيط الافتراضي. يُمكن الوصول إلى "تصميم" من "لوحة التحكم" ثم "صفحات" لإعداد التصميم المطلوب (للمزيد يُمكن العودة إلى الدرس الرابع). حذف قسم يُمكن تحديد قسم (بتحديد المربع الموجود يمين اسم القسم) ومن ثم حذفه بالنقر على زر الحذف الأحمر أعلى الصفحة ومن ثم تأكيد الحذف في النافذة المنبثقة لزر الحذف. المنتجات Products في متجر أوبن كارت تُعدّ المنتجات المحور الرئيسي للمتجر ومصدر الرزق لأصحابه. يؤدي النقر على خيار "المنتجات" ضمن "واجهة المتجر" إلى فتح واجهة معاينة المنتجات المتاحة في المتجر كما يُبين الشكل التالي: نسخ المنتجات وتعديلها وحذفها تسمح الأزرار أعلى جدول المنتجات بإضافة أو نسخ (تكرار) أو حذف منتج: يُظهر كل سطر في جدول المنتجات البيانات التالية للمنتج: الصورة Image اسم المنتج Product Name النوع Model السعر Price الكمية Quantity الحالة Status تحرير edit يُمكن تعديل بيانات أي منتج بالنقر على زر التحرير الأزرق الموجود يسار سطر المنتج. يُمكن استخدام المرشح (الفلتر) في الجهة اليسرى من الصفحة للوصول لمنتج/منتجات معينة وفق عوامل التصفية المختلفة (اسم المنتج، النوع، السعر، الكمية، الحالة) مما يُساعد مدير المتجر في الوصول إلى منتج معين بسرعة. يُمكن تحديد منتج أو أكثر وذلك بتحديد الصندوق الصغير على يمين اسم المنتج ومن ثم: الحذف Delete باستخدام زر الحذف الأحمر الموجود أعلى يسار الصفحة. يؤدي الحذف إلى إزالة كامل معلومات المنتج. النسخ Copy باستخدام زر النسخ أعلى يسار الصفحة. يؤدي النسخ إلى إضافة نسخة جديدة أخرى من المنتج لها نفس بيانات المنتج. يُمكن حذف كل المنتجات (مثلًا: سنحتاج لحذف كل المنتجات التي تأتي مع أوبن كارت في البداية كأمثلة تعليمية) كما يلي: تحديد جميع المنتجات عن طريق اختيار صندوق التحديد في ترويسة جدول المنتجات مما يؤدي إلى تحديد جميع صناديق التحديد لأسطر الجدول. النقر على زر الحذف الأحمر أعلى يسار جدول المنتجات. تأكيد عملية الحذف في النافذة المنبثقة لزر الحذف. إضافة منتج جديد يجب قبل البدء بإضافة منتجات جديدة الانتهاء من إضافة الأقسام التي ستتبع لها هذه المنتجات. ننقر على الزر (+) لإضافة منتج جديد. تحتوي واجهة المنتج على 12 تبويبًا نعرضها فيما يلي: التبويب "عام" General يحوي التبويب "عام" الحقول التالية: اسم المنتج Product Name: وهي خانة إلزامية للاسم الرئيسي للمنتج. تفاصيل Description: يُمكن كتابة جميع المعلومات الأساسية عن المنتج. عنوان ميتا تاغ Meta Tag Title: وهو العنوان الذي سيظهر لصفحة المنتج في نتائج بحث محركات البحث وفي علامات تبويب المتصفح وعند مشاركة صفحة المنتج على وسائل التواصل الاجتماعي. وهو حقل واجب الإدخال وطوله الأعظمي 255 حرف. يجب أن يكون هذا العنوان فريد لكل منتج ويُستحسن أن يكون طوله بين 50-60 حرف. وصف ميتا تاج Meta Tag Description: وهو الوصف التعريفي القصير الذي يظهر لصفحة المنتج في نتائج بحث محركات البحث. يجب أن يكون الوصف التعريفي جذابًا لتشجيع المستخدم على النقر للوصول إلى صفحة المنتج في المتجر. كلمات ميتا تاج Meta Tag Keywords: وهي الكلمات الرئيسية التي تصف صفحة المنتج لمحركات البحث ويجب فصلها بفواصل. تُساعد هذه الحقول محركات البحث في الوصول إلى الصفحة المعنية إذ تُعلّم محرك البحث بمضمون الصفحة. الكلمات الدليلية Product Tags: وهي الكلمات الرئيسية التي تصف صفحة المنتج للعميل ويجب فصلها بفواصل. تُساعد هذه الحقول العميل بالوصول للمنتج عند استخدامه لهذه الكلمات في صندوق البحث الموجود في رأس كل صفحة من صفحات المتجر. التبويب "بيانات" Data يحوي هذا التبويب على الحقول التالية: النوع Model: يجب إدخال قيمة تتألف من أحرف وأرقام. SKU (اختصار Stock Keeping Unit): يُمكن إدخال كود ما للمنتج. UPC (اختصار Universal Product Code): يُمكن إدخال الكود العالمي للمنتج (الباركود). EAN (اختصار European Article Number): يُمكن إدخال الباركود الأوروبي للمنتج في حال توفره. JAN (اختصار Japanese Article Number): يُمكن إدخال الباركود الياباني للمنتج في حال توفره. ISBN (اختصار International Standard Book Number): يُمكن إدخال الباركود الدولي للكتب في حال كان المنتج كتابًا. MPN (اختصار International Standard Book Number): يُمكن إدخال رقم القطعة حسب المصنع أو حسب الصانع. المكان Location: مكان وجود المنتج. السعر Price: السعر الأساسي للمنتج بدون ضرائب. نوع الضريبة Tax Class: يُمكن اختيار نوع الضريبة من القائمة الموافقة، وتُعرّف أنواع الضرائب في الصفحة "نوع الضريبة" والتي نصل إليها من "الضبط" ثم "الأوضاع" ثم "الضرائب" ثم "فئات الضريبة". الكمية Quantity: اجمالي الكمية الموجودة من المنتج. أقل كمية Minimum Quantity: الحد الأدنى من الكمية التي يُمكن طلبها من العميل. اخصم من كمية المنتج المتوفرة Subtract Stock: في حالة اختيار "نعم"، سوف تُطرح الكمية التي يطلبها العميل من كمية هذا المنتج. حالة المنتج الغير متوفر: Out of Stock Status: تظهر هذه الحالة للعميل إذا كانت الكمية صفر لإعلامه مثلًا بتاريخ التوفر لاحقًا. لاحظ أنه تُعرّف حالات المنتج من الصفحة "نوع الضريبة" والتي نصل إليها من "الضبط" ثم "الأوضاع" ثم "الضرائب" ثم "وضع حالة التوفر". شحن المنتج Requires Shipping: يُمكن تحديد الخيار "نعم" إذا كان المنتج يتطلب الشحن، وتحديد الخيار "لا" في حالة عدم الحاجة لشحن المنتج أي بيعه من مقر المتجر أو في حالة بيع المنتجات الرقمية مثل الكتب الالكترونية وغيرها. تاريخ التوفر Date Available: وهو تاريخ بداية ظهور المنتج في واجهة المتجر، وفي حالة كتابة التاريخ بعد يوم أو أسبوع فلن يتم عرض المنتج في واجهة المتجر إلا بعد هذا التاريخ المستقبلي. الابعاد (الطول x العرض x الارتفاع) Dimensions: يُمكن كتابة أبعاد المنتج: الطول والعرض والارتفاع. نوع الطول Length Class: يُمكن اختيار وحدة القياس للأبعاد. الوزن Weight: يُمكن ادخال وزن المنتج. نوع الوزن Weight Class: يُمكن اختيار وحدة الوزن. الحالة Status: في حال اختيار الحالة "تمكين" سيظهر المنتج في واجهة المتجر، أما في حال اختيار الحالة "تعطيل" سيتم إخفاء المنتج من واجهة المتجر. ترتيب الفرز Sort Order: يُعطي هذا الرقم ترتيب المنتج في قائمة. الرقم الأصغر يكون في الأعلى. ملاحظة: يُمكن تعريف وحدات قياس المنتج من الصفحة "نوع الطول" وصفحة "نوع الوزن" والتي نصل إليها من "الضبط" ثم "الأوضاع" (تُعدّ الوحدة الافتراضية الوحدة التي أُدخل لها القيمة 1 في حقل "القيمة"): ملاحظة: لا تظهر الحقول في واجهة المتجر للعميل بدءًا من الحقل من SKU إلى حقل مكان وجود المنتج. التبويب "روابط" Links يحوي هذا التبويب الحقول التالية: الشركات Manufacturer: يُمكن اختيار الشركة المُصنعة للمنتج من القائمة الموافقة، ويُمكن تعريف الشركات من صفحة "الشركة" والتي يُمكن فتحها من "واجهة المتجر" ثم "الشركات": الأقسام Categories: يُمكن تحديد قسم أو أكثر للمنتج. سيظهر المنتج للعميل في صفحة القسم في واجهة المتجر. الفلاتر Filters: يُمكن تحديد فلتر أو أكثر للمنتج (نشرح الفلاتر في الدرس الثالث). المتاجر Stores: يُمكن تحديد المتاجر التي تبيع المنتج. يكون الخيار "الافتراضي" محدّدًا في الحالة العامة (متجر واحد). ملفات التنزيل Downloads: يُمكن اختيار الملف الواجب تنزيله وذلك في حال كان المنتج يتضمن لهذا الملف في عملية الشراء. منتجات ذات صلة Related Products: يُمكن إضافة بعض المنتجات لإظهارها في حال اختيار العميل للمنتج (رغبًة بتذكيره بها لحضه على شرائها أيضًا). يُمكن للعميل استعراض منتجات شركة معينة من واجهة المتجر وذلك بفتح رابط "الشركات" تحت "إضافات" في الشريط أسفل الصفحة: يُبين الشكل التالي صفحة "الشركة" في واجهة المتجر: وعند اختيار شركة معينة تظهر صفحة منتجات هذه الشركة: تُضاف الملفات من صفحة "ملفات التنزيل" والتي تُفتح من "واجهة المتجر" ثم "ملفات التنزيل": يُمكن وضع الملف السابق مع كتاب "مقدمة في الذكاء الاصطناعي" مثلًا بالشكل التالي: بالاستعانة برابط "منتجات ذات صلة"، يمكن مثلًا وضع كتاب "تعلم الآلة" في "منتجات ذات صلة" لكتاب "مقدمة في الذكاء الاصطناعي": سيظهر كتاب "تعلم الآلة" في صفحة كتاب " مقدمة في الذكاء الاصطناعي" في واجهة المتجر: تبويب "المواصفات" Attribute يُستخدم تبويب "المواصفات" لإضافة مواصفات معينة للمنتجات. مثلًا: سنضيف للكتب في المتجر المواصفات التالية: عدد صفحات الكتاب ووجود غلاف فني للكتاب أو لا. يجب أولًا إعداد أنواع المواصفات من صفحة "أنواع المواصفات" والتي نصل إليها من "واجهة المتجر" ثم "مواصفات المنتجات" ثم "أنواع المواصفات" مثلًا نضيف "فنية" من أجل الكتب: كما يجب إعداد مواصفات المنتجات من صفحة "مواصفات المنتجات" والتي نصل إليها من "واجهة المتجر" ثم "مواصفات المنتجات" ثم "مواصفات المنتجات" مثلًا نضيف "عدد الصفحات" و "غلاف فني": نقوم الآن من أجل الكتاب "مقدمة في الذكاء الاصطناعي" بإضافة المواصفات التالية في تبويب "المواصفات" للكتاب: سوف تظهر المواصفات للعميل في صفحة الكتاب في واجهة المتجر كما يُبين الشكل التالي: تُستخدم المواصفات أيضًا للمقارنة بين المنتجات. مثلًا: يُمكن للعميل مقارنة المواصفات "الفنية" لبعض الكتب وذلك بإضافة كل كتاب أولًا إلى المقارنة وذلك بالنقر على زر "إضافة للمقارنة" في صفحة كل كتاب: يُمكن بعدها للعميل فتح صفحة "مقارنة المنتجات" إما من الرابط "قائمة المقارنة" والذي يظهر بعد طلب المقارنة: أو من الرابط "مقارنة المنتج" الذي يظهر في قسم الكتب الموافق: تُظهر صفحة مقارنة المنتجات التالية المواصفات التي تم إضافتها للمنتجات إضافًة لمواصفاتها الأساسية: التبويب "خيارات" يسمح التبويب "خيارات" بإضافة خيارات جديدة للمنتجات مثل الألوان والمقاسات مثلًا، مما يُساعد العميل في اختيار المنتج. مثلًا: سنضيف للكتب الخيار: "طباعة الكتاب" (اختيار من قائمة: "طالب" للطباعة بدون تجليد فني، "فنية" للطباعة مع تجليد فني أنيق). يجب أولًا تعريف هذا الخيار في صفحة "خيارات" والتي نصل إليها من "واجهة المتجر" ثم "خيارات المنتجات": نُضيف الخيار "نسخة الكتاب" (اختيار من قائمة: "طالب"، "فنية") كما يلي: يُمكن الآن إضافة هذا الخيار إلى المنتجات. مثلًا: يتوفر لكتاب "مقدمة في الذكاء الاصطناعي" نوعين من النسخ: "طالب" و"فنية". يُمكن القيام بالإعدادات التالية في تبويب "خيارات" للكتاب: يُمكن تغيير كل من السعر والنقاط والوزن حسب كل قيمة من قيم خيارات "نسخة الكتاب". لاحظ مثلًا إنقاص سعر الكتاب في المثال السابق لنسخة "طالب" بـ 10 مع 5 نقاط إضافية للعميل. تظهر هذه الخيارات في صفحة المنتج للعميل في واجهة المتجر: تبويب "المدفوعات المتكررة" Profile يُستخدم هذا التبويب في حال الرغبة بتقسيط ثمن منتج على شكل دفعات دورية. مثلًا: بفرض أننا نريد تقسيط سعر الكتاب على دفعتين وذلك بمعدل دفعة واحدة كل شهر. يجب أولًا تعريف ذلك من صفحة "المدفوعات المتكررة" من "واجهة المتجر" كما يلي (للمزيد من التفاصيل يُرجى العودة إلى فقرة المدفوعات المتكررة في الدرس الثالث): يُمكن بعد ذلك استخدام هذا النوع من المدفوعات في كتاب ما: يُمكن للعميل اختيار طريقة الدفع من القائمة "طريقة الدفع" والتي تظهر له في صفحة الكتاب في واجهة المتجر: التبويب "تخفيض" Discount يسمح هذا التبويب بتعريف تخفيضات على المنتج لكمية معينة ولفترة معينة. مثلًا: بفرض أننا نريد تخفيض السعر ليُصبح 130 في حالة شراء العميل لكتابين على الأقل وذلك خلال فترة معينة وذلك فقط لأول 100 عميل يقومون بالشراء: يحوي هذا التبويب الحقول التالية: مجموعة العميل Customer Group: يُمكن تحديد مجموعة العملاء المستهدفة من التخفيض (يُمكن تعريف مجموعات العملاء المختلفة من "واجهة المتجر" ثم "العملاء"). الكمية Quantity: وهي أقل كمية من المنتج يجب شرائها لتطبيق التخفيض. الأولوية Priority: عدد العملاء الذين يُمكنهم الاستفادة من التخفيض. لن يظهر التخفيض مجددًا بعد هذا العدد من عمليات الشراء. السعر Price: سعر المنتج بعد التخفيض. تاريخ البدء Date Start: تاريخ بداية تطبيق التخفيض. تاريخ الانتهاء Date End: تاريخ نهاية تطبيق التخفيض. (في حال لم يتم تحديد هذه التواريخ يكون التخفيض دائم). ملاحظة: يظهر التخفيض للعميل بعد إضافته للمنتج إلى سلة الشراء في واجهة المتجر: تبويب "العروض المميزة" Special يكون لهذا التبويب نفس حقول التبويب السابق عدا حقل الكمية. مثلًا: تظهر العروض للعميل في صفحة "العروض المميزة" في واجهة المتجر: يُمكن للعميل فتح صفحة "العروض المميزة" من الرابط "العروض المميزة" أسفل واجهة المتجر: تبويب "الصور" Image يسمح هذا التبويب بإدارة صور المنتج. تبويب "نقاط المكافآت" Reward Points يسمح هذا التبويب بتعريف النقاط الممنوحة للعميل في حال شراء المنتج، كما يسمح بتحديد رصيد النقاط ليتمكن العميل من الحصول على المنتج مجانًا. مثلًا: يُبين الشكل التالي حالة منتج يمنح العميل 100 نقطة عند شرائه لهذا المنتج. كما يُمكن للعميل الحصول على المنتج مجانًا إذا كان لديه رصيد 400 نقطة (بمعنى آخر يمكن للعميل شراء أربع كميات من هذا المنتج والحصول على الكمية الخامسة مجانًا). بالطبع، لا يشترط أن يتم تجميع النقاط عند شراء هذا المنتج فقط، بل يمكنه تجميع نقاط عند شراء منتجات أخرى. تبويب "روابط السيو" SEO يحوي هذا التبويب الحقل "كلمات السيو" لكل من اللغتين العربية والإنكليزية. وهو حقل غير إلزامي إلا أنه ضروري في حال الرغبة أن تكون صفحة المنتج صديقة لمحركات البحث بمعنى أن يُستبدل الرابط الافتراضي للمنتج برابط آخر يحوي كلمات السيو مما يؤدي إلى مساعدة محركات البحث في الوصول للصفحة. التبويب "تصميم" Design يُمكن ربط صفحة المنتج بتخطيط مُجهز مُسبقا أو يمكن تركها بدون أي تخطيط ليكون لها التخطيط الافتراضي. خاتمة استعرضنا في هذا الدرس المرحلة الأولى من إدارة المتجر وهي تعريف المنتجات وأقسامها. تُعدّ هذه المرحلة هامة جدًا إذ أن المنتجات هي مصدر الرزق للمتجر ويلعب حُسن تبويبها في أقسام دورًا هامًا في سهولة وصول العميل إليها. كما أن حُسن انتقاء قيم حقول المنتجات (مثل كلمات السيو وكلمات الميتا تاغ) يُساهم في وصول العملاء إلى صفحات منتجات المتجر من خلال محركات البحث. نتابع في الدرس الثالث شرح عمليات إعدادات واجهة المتجر. اقرأ أيضًا الدليل الشامل لأشهر أنظمة إنشاء وإدارة المتاجر الإلكترونية أساسيات تمويل المتاجر الإلكترونية منصات التجارة الإلكترونية العربية بالموازنة مع المنصات الأجنبية
  24. يهدف الدرس الأول من سلسلة دروس حول أوبن كارت إلى التعريف بمتجر أوبن كارت OpenCart وعرض خطوات التنزيل والتثبيت، إذ تهدف هذه السلسلة إلى التعريف بلوحة تحكم متجر أوبن كارت وأغلب القوائم والخيارات فيها وذلك للتمكن من إدارة المتجر إدارة صحيحة، لذا ستجدنا نمر على القوائم بلوحة التحكم بالترتيب ونشرحها ونوضحها ونبين كيف ضبط الخيارات والإعدادات فيها. هذا المقال جزء من سلسلة تعريفية بلوحة تحكم متجر أوبن كارت، إليك فهرس مقالات كامل السلسلة: مدخل إلى متجر أوبن كارت وكيفية تثبيته إدارة الأقسام والمنتجات في متجر أوبن كارت التعرف على إعدادات واجهة متجر أوبن كارت تعلم كيفية ضبط متجر أوبن كارت شرح الإضافات والقوالب في لوحة تحكم متجر أوبن كارت نظرة على خيارات التسويق التي يوفرها متجر أوبن كارت التقارير والإحصائيات: نافذة على أداء متجر أوبن كارت إعدادات الدفع والشحن في متجر أوبن كارت ما هو أوبن كارت OpenCart هو منصة تطوير مواقع تجارة إلكترونية eCommerce تتميز بما يلي: مجانية: أي لن يُكلّف بناء موقع التجارة الإلكترونية (المتجر) فلسًا واحدًا. سهلة الاستخدام: يُمكن استخدامها من قبل شرائح واسعة من المطورين بدءًا من المطورين ذوي المعرفة الأساسية بمبادئ الويب وانتهاءً بمطوري الويب المحترفين. مفتوحة المصدر: أي أن المنصة هي حصيلة عمل مجموعة من الأشخاص الذين يتبرعون بوقتهم في بناء المنصة وتحسينها، كما أن الشيفرة البرمجية متوفرة للجميع. الاستضافة الذاتية: يُمكن استضافة الموقع على خادم ويب مناسب. أي أن العمليات الإدارية مثل الاستضافة والصيانة والإدارة والأمن تقع على عاتق المطور نفسه وذلك على عكس الحلول من النمط البرمجيات كخدمة SaaS والتي توفر قسمًا كبيرًا من هذه الخدمات (مثل منصة تطوير مواقع التجارة الإلكترونية Shopify) إلا أنها تُعطي، مقابل ذلك، قدرًا أقل من المرونة والتحكم. الإدارة السهلة: يُمكن إنشاء وإدارة عدد غير محدود من المنتجات بشكل بسيط وسهل. الخيارات المتعدّدة: يتوفر عدد كبير من خيارات الدفع والشحن. تعدد المتاجر: يُمكن إدارة عدة متاجر في نفس الموقع. تعدد اللغات والعملات: يُمكن استخدام أكثر من لغة وعملة في الموقع. المساعدة في التسويق: يتوفر عدد من أدوات التسويق الهامة. تحسين محركات البحث: يوجد العديد من الخيارات لتوفير المعلومات المناسبة لمحركات البحث بهدف تحسين ترتيب ظهور صفحات الموقع في محركات البحث. إمكانية التوسع: يُمكن إضافة الكثير من المكونات الإضافية المجانية أو المدفوعة الثمن. أساسيات في تطوير واستضافة مواقع الويب نبدأ أولًا بعرض بعض المفاهيم الأساسية التي يجب فهمها قبل البدء بتطوير موقع ويب وإتاحته للعموم بعدها. الاستضافة على الويب يجب استضافة أي موقع ويب على خادم ويب web server لإتاحة هذا الموقع للعموم. يُقدّم خادم الويب مجموعة من الخدمات المختلفة مثل توفير جميع البرمجيات اللازمة لعمل الموقع بشكل صحيح وتوفير مساحة التخزين الكافية لبيانات الموقع المختلفة. يوفر خادم الويب لوحة تحكم تسمح لمدير الموقع بتنفيذ جميع العمليات الإدارية اللازمة للموقع مثل تحميل الملفات وإنشاء قواعد البيانات وتعريف المستخدمين وغير ذلك من العمليات اللازمة. الموقع المستضاف hosted والموقع ذو الاستضافة الذاتية self-hosted موقع الويب المُستضاف هو موقع مبني باستخدام أدوات إنشاء مواقع الويب مثل شوبيفاي Shopify أو WordPress.com، إذ تعمل هذه الأدوات بمبدأ البرمجيات كخدمة SaaS وتوفر حلًا من النوع "الكل في واحد" إذ أنها توفر برامج تطوير موقع الويب إضافًة إلى الاستضافة على خوادم مخصصة. يكون التخصيص مقيدًا باستخدام أدوات ونماذج الأداة الموفرة حصرًا، كما يكون الوصول إلى الشيفرة البرمجية محدودًا جدًا. أما الموقع ذو الاستضافة الذاتية فهو موقع مبني بأدوات إنشاء المواقع مثل أوبن كارت OpenCart ووردبريس WordPress، والتي هي برمجيات مفتوحة المصدر، مما يعني أنه يُمكن تنزيلها ثم تعديلها حسب الحاجة. أي أن البرنامج مجاني إلا أنه يجب فتح حساب مع مضيف ما لمواقع الويب website host من أجل وضع ملفات الموقع عليه وشراء نطاق domain (العنوان URL لموقع الويب) من مُسجّل المجالات domain registrar. يُشبّه الكثيرون الفرق بين النوع الأول والثاني كالفرق بين استئجار منزل أو تملك هذا المنزل. الاستضافة الذاتية لأوبن كارت يتمتع أوبن كارت بميزة الاستضافة الذاتية self-hosted أي أن مطور الموقع هو المسؤول عن جميع عمليات التطوير والصيانة وإيجاد الاستضافة المناسبة وإدارة الموقع وغيرها من المهام. يُمكن أحيانًا أن تُعدّ هذه الميزة سلبية لاسيما للأشخاص ذوي الخبرة القليلة جدًا في مجالات تطوير الويب. إلا أنها تُعدّ إيجابية للأشخاص الذين يحبون التحكم بكل شيء في الموقع. يجب أن يوفر خادم الويب Apache ونظام إدارة قواعد البيانات MySQL لتشغيل أوبن كارت على هذا الخادم. للمزيد من التفاصيل، ارجع إلى قسم "منصات المتاجر الإلكترونية" من مقال منصات التجارة الإلكترونية العربية بالموازنة مع المنصات الأجنبية. استضافة أوبن كارت محليًا من الأسهل أن نقوم بتطوير موقع التجارة الإلكترونية على الحاسوب المحلي أولًا واختباره بشكل كامل، ومن ثم استضافة الموقع المطور على خادم ما على الويب. يجب إذًا تجهيز الحاسوب المحلي الذي نعمل عليه ليعمل كخادم ويب، أي يجب عمليًا تشغيل برنامج الإدارة أباتشي Apache عليه، إضافًة إلى نظام إدارة قواعد البيانات MySQL. نبدأ أولًا بالتذكير ببعض الأمور الأساسية في عالم مواقع الويب. برنامج خادم الوب Web Server هو برنامج يوضع على خادم server لاستضافة صفحات مواقع الويب، يُعالج هذا البرنامج الطلبات الواردة إليه من المستخدمين على الشبكة -باستخدام البروتوكول HTTP (اختصارًا إلى Hyper Text Transfer Protocol)- ويقوم بتزويد هؤلاء المستخدمين بناتج المعالجة على شكل صفحات HTML كي تتمكن المستعرضات Browsers من عرضها كما يُبين الشكل التالي: من أشهر برامج مخدّمات الويب برنامج أباتشي Apache المفتوح المصدر وبرنامج IIS (اختصارًا إلى Internet Information Server) من مايكروسوفت Microsoft. أباتشي Apache هو برنامج خادم الويب الأكثر استخدامًا في العالم (حوالي 67% من خوادم الويب) ويتميز بأنه مفتوح المصدر ومجاني الاستخدام، ولذلك، يُمكن أن تُقدّم شركات الاستضافة المستندة إلى أباتشي استضافة بتكاليف أقل. يدعم أباتشي منصات التشغيل المختلفة مثل ويندوز ولينكس وماك ويُمكن لأباتشي استضافة المواقع التي تستخدم لغات البرمجة من طرف الخادم مثل php. للمزيد من المعلومات يُمكن الرجوع لقسم الخوادم في أكاديمية حسوب ومقال أفضل 5 خوادم ويب مفتوحة المصدر للاطلاع على خوادم الويب مفتوحة المصدر. حزمة التطبيقات XAMPP هي حزمة تطبيقات مجانية ومفتوحة المصدر تتضمن برنامج خادم الوب أباتشي Apache ونظام إدارة قواعد البيانات MySQL وغيرها، إذ تسهل هذه الحزمة ضبط خادم ويب متكامل وتشغيله على الحاسوب محليًا وذلك بخطوات بسيطة سريعة. لغة البرمجة php هي لغة برمجة مفتوحة المصدر صُممت لبرمجة وتطوير تطبيقات الويب، ويمكنك معرفة المزيد عنها بالرجوع إلى توثيق لغة PHP العربي في موسوعة حسوب. تجهيز الحاسوب المحلي لاستضافة أوبن كارت سنثبت متجر أوبن كارت على خادم نجهزه محليًا على الحاسوب بغرض التطوير والتجريب، ويمكنك بعدها عند اكتماله نقله إلى خادم إنتاجي على الإنترنت تضبطه أنت أو رفعه على استضافة متكاملة وجاهزة تستأجرها مع نطاق مثلًا. تنزيل حزمة التطبيقات XAMPP يجب أولًا تنزيل حزمة التطبيقات XAMPP من الموقع الرسمي مثلًا. بعد الانتهاء من التنزيل، نحصل على ملف تنفيذي يكون له الاسم التالي مثلًا: xampp-windows-x64-7.3.31-2-VC15-installer.exe يجب تثبيت الحزمة (النقر المزدوج على اسم الملف التنفيذي السابق ومتابعة خطوات التثبيت)، وبعد انتهاء التثبيت، يُمكن تشغيل XAMPP Control Panel: يؤدي النقر على الزر Start على يمين الخيار Apache إلى تشغيل مخدم الويب، وعلى الزر Start على يمين الخيار MySQL إلى تشغيل نظام إدارة قواعد البيانات. إذا نجح التشغيل تظهر الخيارات باللون الأخضر كما يُبين الشكل التالي: ملاحظة: إن لم يعمل أباتشي على البوابة الافتراضية 80، يُمكن إسناد رقم بوابة (منفذ) أخرى له (عادةً 8080) كما يلي: انقر زر الإعدادات Config الخاص بأباتشي واختر الخيار الأول Apache(httpd.conf)‎ لفتح ملف الإعدادات بأي محرر نصوص. ابحث عن الرقم 80 واستبدل كل ظهور له في الملف بـ 8080 (أو أي رقم منفذ آخر). احفظ التعديلات ثم عاود النقر على زر التشغيل start. إنشاء قاعدة البيانات يُمكنك فتح نظام إدارة قواعد البيانات MySQL عن طريق كتابة الرابط التالي في شريط العنوان في المتصفح: http://localhost:8080/phpmyadmin/ أو بالنقر على زر الإدارة Admin على يمين الخيار MySQL في لوحة التحكم XMAPP. (قد تحتاج لضبط رقم البوابة المناسبة في localhost). يُبين الشكل التالي الواجهة الرئيسية لنظام إدارة قواعد البيانات MySQL: يُمكن إنشاء قاعدة بيانات جديدة، ولندعوها store مثلًا: تُخزّن جميع بيانات موقع التجارة الإلكترونية في هذه القاعدة. تنزيل النسخة العربية من أوبن كارت يُمكن تنزيل النسخة العربية من أوبن كارت من الموقع الرسمي. يُطلب أولًا التسجيل في الموقع قبل تنزيل الملف. بعد التنزيل، نحصل على الملف المضغوط التالي: opencartArabicV3037.zip يجب فك الضغط، ومن ثم وضع جميع الملفات الناتجة في مجلد جديد يُمكن تسميته opencart مثلًا. يجب وضع هذا المجلد في المجلد التالي: C:\xampp\htdocs (يحوي هذا المجلد عادًة مجلدات فرعية، يحوي كل منها ملفات موقع ويب معين). يُمكن فتح رابط خطوات تثبيت أوبن كارت من أي متصفح لديك: http://localhost:8080/opencart/install/index.php وتعديل اللغة إلى العربية ثم اتباع خطوات التثبيت الأربع التالية: الخطوة الأولى: الموافقة على الرخصة يجب الموافقة أولًا على رخصة الاستخدام ثم النقر على الزر "متابعة": الخطوة الثانية: ضبط الإعدادات يقوم أوبن كارت بالتحقق من جميع إعدادات المخدم اللازمة له وفي حال وجود أي مشكلة يقوم بالإعلام عنها: نجد، على الأغلب، أن ملفات الإعدادات التالية غير موجودة كما يُبين الشكل التالي: لحل هذه المشكلة يجب تغيير اسم ملف الإعدادات من config-dist.php إلى config.php الموجود في المجلد: C:\xampp\httdocs\opencart وتغيير اسم ملف الإعدادات من config-dist.php إلى config.php الموجود في المجلد: C:\xampp\httdocs\opencart\admin للتأكد من صحة العمل يُمكن إعادة تحميل الصفحة السابقة (F5): الخطوة الثالثة: ضبط إعدادات قاعدة البيانات يجب إدخال اسم قاعدة البيانات التي أنشأناها سابقًا store في حقل "قاعدة البيانات": يجب إدخال اسم لمستخدم الإدارة (مدير النظام) وكلمة سر والبريد الإلكتروني: إذا ظهرت الواجهة التالية فهذا يعني انتهاء عملية التثبيت بنجاح: لاحظ الرسالة التحذيرية الظاهرة والتي تطلب حذف مجلد التثبيت بهدف منع إعادة التثبيت بالخطأ لاحقًا مما قد يؤدي إلى فقد بيانات المتجر. يُدعى هذا المجلد install ويوجد في مجلد المتجر (سميناه opencart في خطوة التثبيت). إتمام تثبيت متجر أوبن كارت يُمكن الآن الدخول كمدير إلى لوحة تحكم متجر أوبن كارت بعد تثبيته وذلك عن طريق الرابط: http://localhost:8080/opencart/admin/ (يجب طبعًا تشغيل أباتشي و MySQL قبلها) يظهر أول مرة التنبيه التالي والذي يطلب تخزين البيانات في مجلد خارج المجلد الرئيسي للمتجر (المجلد storage): يقوم "النقل التلقائي" بوضع المجلد storage ضمن C:\xampp ويُمكن اختيار مجلد أخر عن طريق "نقل يدوي": تظهر لوحة التحكم الأساسية لأوبن كارت: يطلب أوبن كارت حذف مجلد التنصيب install الموجود ضمن المجلد opencart: بعد إتمام كل ما سبق، يُمكن البدء باستخدام لوحة تحكم أوبن كارت والبدء بإدارة المتجر الإلكتروني عن طريق الرابط: http://localhost:8080/opencart/admin يُمكن أيضًا الدخول كعميل للمتجر عن طريق الرابط: http://localhost:8080/opencart وتصفح المنتجات (المدخلة لأهداف تعليمية) في الموقع: خاتمة استعرضنا في هذا الدرس خطوات تثبيت وتشغيل أوبن كارت مما يُنشئ المتجر الافتراضي والذي يُمكن الدخول له كعميل للتعرف على واجهاته المختلفة واستعراض المنتجات الافتراضية الموجودة فيه، كما يُمكن الدخول كمدير للمتجر والبدء بتعريف المنتجات وتبويبها في أقسام كما سنعرض في الدرس التالي. اقرأ أيضًا أنواع المتاجر الإلكترونية ونماذج إيراداتها 12 قاعدة بسيطة لتحسين معدلات التحويل إلى مواقع التجارة الإلكترونية واقع التجارة الإلكترونية في العالم العربي والعوامل المؤثرة فيها
  25. تشترك معظم التطبيقات الشهيرة مثل مُساعد جوجل Google Assistant وتطبيق الدردشة سلاك Slack وتطبيق اللقاءات الافتراضية زووم Zoom بأنها تُقدّم خدمات محدودة جدًا في وضع انقطاع الاتصال، أي أنه يُمكن تشغيلها والدخول إليها ومعاينة بعض الواجهات فيها على الرغم من انقطاع الاتصال. تُبين اللقطات التالية أن تطبيقات المنصات الخاصة تعرض شيئًا ما في وضع انقطاع الاتصال. مثلًا اللقطة التالية للمُساعد Google Assistant: أما اللقطة التالية لتطبيق سلاك Slack: واللقطة التالية لتطبيق زووم Zoom: على النقيض من ذلك، لا نحصل على شيء على الويب عند انقطاع الاتصال. مثلًا، قد يُظهر المتصفح Chrome اللعبة البسيطة dino على أنظمة التشغيل iOS: وعلى أنظمة التشغيل macOS: سنتعلم في هذا المقال كيفية إنشاء صفحة احتياطية لوضع انقطاع الاتصال وإضافتها إلى تطبيقات الويب التقدمية PWA. إنشاء صفحة احتياطية باستخدام عامل خدمة مخصص من المناسب تخصيص سلوك صفحات الويب التقدميّة في حال انقطاع الاتصال لاسيما أنه أصبح بالإمكان توفير تجربة استخدام مخصصة باستخدام عامل خدمة service worker وواجهة برمجة التطبيقات ذات التخزين المؤقت Cache Storage API . يُمكن عادًة إنشاء صفحة احتياطية بسيطة تُبين للمستخدم أنه في وضع انقطاع الاتصال، إلا أنه يُمكن أيضًا إيجاد حلول إبداعية أجمل. لنلقي نظرة مثلًا على موقع الحجز trivago والذي يوفر في صفحته الاحتياطية لعبة متاهة مسلية للمستخدم خلال انقطاع الاتصال مع زر لتجريب إعادة الاتصال Reconnect وعدّاد تنازلي لإظهار الزمن المتبقي لإعادة محاولة الاتصال تلقائيًا كما يُبين الشكل التالي: تسجيل عامل الخدمة لإنشاء الصفحة الاحتياطية، يجب أولًا تسجيل عامل خدمة في الصفحة الأساسية كما تُبين الشيفرة التالية والتي تُنفّذ عند تحميل التطبيق: window.addEventListener("load", () => { if ("serviceWorker" in navigator) { navigator.serviceWorker.register("service-worker.js"); } }); شيفرة عامل الخدمة نعرض فيما يلي مثالًا عن شيفرة عامل الخدمة والتي قد تبدو للوهلة الأولى معقدة قليلًا ولذا أُضيفت بعض التعليقات المُساعدّة. تكمن الفكرة بالتخزين المؤقت المسبق لملف ندعوه offline.html والذي يعرضه المتصفح في حال فشل طلبات التنقل navigation فقط، وفي بقية الحالات يتابع المتصفح معالجاته الاعتيادية. /* معلومات رخصة الاستخدام Copyright 2015, 2019, 2020, 2021 Google LLC. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // (1) // يُمكن إضافة أي تعليق مناسب لمنقح الصياغة // eslint-disable-next-line no-unused-vars const OFFLINE_VERSION = 1; const CACHE_NAME = "offline"; يُمكن تخصيص مُحدّد موارد URL مختلف إذا دعت الحاجة // const OFFLINE_URL = "offline.html"; self.addEventListener("install", (event) => { event.waitUntil( (async () => { const cache = await caches.open(CACHE_NAME); // (2) await cache.add(new Request(OFFLINE_URL, { cache: "reload" })); })() ); إرغام عامل الخدمة المنتظر ليصبح العامل النشط // self.skipWaiting(); }); self.addEventListener("activate", (event) => { event.waitUntil( (async () => { // السماح بالتنقل قبل التحميل إذا كان ذلك مدعومًا // See https://developers.google.com/web/updates/2017/02/navigation-preload if ("navigationPreload" in self.registration) { await self.registration.navigationPreload.enable(); } })() ); // الطلب من عامل الخدمة أن يتحكم بالصفحة فورًا self.clients.claim(); }); self.addEventListener("fetch", (event) => { إذا كان الطلب لصفحة HTML نستدعي event.respondWith// if (event.request.mode === "navigate") { event.respondWith( (async () => { try { نحاول أولًا استخدام جواب التنقل قبل التحميل إذا كان مدعومًا // const preloadResponse = await event.preloadResponse; if (preloadResponse) { return preloadResponse; } تجريب الشبكة أولًا // const networkResponse = await fetch(event.request); return networkResponse; } catch (error) { // (3) console.log("Fetch failed; returning offline page instead.", error); const cache = await caches.open(CACHE_NAME); const cachedResponse = await cache.match(OFFLINE_URL); return cachedResponse; } })() ); } // (4) }); (1) تؤدي زيادة قيمة المتغير OFFLINE_VERSION إلى تنشيط حدث التثبيت وتحديث الموارد المخبئة سابقًا عبر الشبكة، المتغير مُعرّف عمدًا مع أنه غير مستخدم. (2) يؤدي ضبط {cache: 'reload'‎} في الطلب الجديد إلى استيفاء الطلب HTTP من الشبكة وليس من الذاكرة المؤقتة. (3) رُفع استثناء يُنشّط الالتقاط catch والذي يكون على الأغلب بسبب خطأ في الشبكة، ولن تُستدعى catch إذا أعادت fetch جواب HTTP صالح، مع كود الجواب محصور بين 4xx - 5xx. (4) إذا كان شرط التعليمة if خاطئًا فلن يقاطع معالج الجلب fetch الطلب، يُمكن أن يُستدعى التابع event.respondWith في حال وجود معالجات جلب أخرى مسجلة، إذا لم يستدع أي معالج جلب التابع event.respondWith فعندها يعالج المتصفح الطلب كما لو أنه لا يوجد عامل خدمة. الصفحة الاحتياطية لوضع انقطاع الاتصال يُعدّ ملف الصفحة الاحتياطية offline.html المكان المناسب لإظهار بعض الإبداع لجذب المستخدم وإبراز العلامة التجارية للمنتج مثلًا، حيث يُمكن تكييف هذا الملف مع الاحتياجات المطلوبة. يُبين المثال التالي الحد الأدنى الممكن القيام به كإظهار زر إعادة التحميل، إضافًة لمحاولات إعادة التحميل الآلية والتي تعتمد على حدث الاتصال online وعلى اقتراع خادم منتظم regular server polling. يجب تخزين جميع الموارد التي تتطلبها الصفحة الاحتياطية لوضع انقطاع الاتصال. من الحلول المُمكنة لذلك تضمين كل شيء وبذا تُصبح الصفحة الاحتياطية حاوية لنفسها، وهو ما يُبينه المثال التالي: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>You are offline</title> <!-- Inline the page's stylesheet. --> <style> body { font-family: helvetica, arial, sans-serif; margin: 2em; } h1 { font-style: italic; color: #373fff; } p { margin-block: 1rem; } button { display: block; } </style> </head> <body> <h1>You are offline</h1> <p>Click the button below to try reloading.</p> <button type="button">⤾ Reload</button> <!-- Inline the page's JavaScript file. --> <script> // ميزة إعادة التحميل اليدوي document.querySelector("button").addEventListener("click", () => { window.location.reload(); }); //(1) window.addEventListener('online', () => { window.location.reload(); }); //(2) async function checkNetworkAndReload() { try { const response = await fetch('.'); // التحقق من الحصول على جواب صالح من الخادم if (response.status >= 200 && response.status < 500) { window.location.reload(); return; } } catch { // تجاهل إذ لا يُمكن الاتصال مع الخادم } window.setTimeout(checkNetworkAndReload, 2500); } checkNetworkAndReload(); </script> </body> </html> حيث أن: (1) متابعة تغييرات حالة الشبكة وإعادة التحميل عند انقطاع الاتصال حيث ينشط المعالج التالي في حالة انقطاع الاتصال كليًا. (2) إعادة تحميل الصفحة إذا كان الخادم متجاوبًا حيث ينشط المعالج التالي في حال انقطاع الاتصال عن الجهاز أو عدم تجاوب الخادم بشكل صحيح. مثال توضيحي يُمكن معاينة الصفحة الاحتياطية في المثال والموضح لقطة منه أدناه. كما يُمكن الحصول على الشيفرة المصدرية الموافقة من المستودع Glitch. يُمكن، بعد الانتهاء من إنشاء الصفحة الاحتياطية لوضع عدم الاتصال، تحقيق إمكانية تثبيت التطبيق بإضافة بيان تطبيق الويب واختيار استراتيجية التثبيت. كما يُمكن، للسهولة، استخدام مكتبات Workbox.js والتي توفر الشيفرة اللازمة لإنشاء الصفحة الاحتياطية. ترجمة -وبتصرف- للمقال Create an offline fallback page للمؤلفين: Thomas Steiner و Pete LePage. اقرأ أيضًا ما هي تطبيقات الويب التقدمية ولماذا يجب على المصممين الاهتمام بها؟ استئناف رفع الملفات بعد فقدان الاتصال في جافاسكربت 3 أخطاء شائعة عند رفع الملفات باستخدام بروتوكول FTP وكيفية إصلاحها أنظمة التشغيل للمبرمجين
×
×
  • أضف...