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

Sam Ahw

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

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

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

  • عدد الأيام التي تصدر بها

    16

كل منشورات العضو Sam Ahw

  1. سؤالك كان عن البحث من خلال Google API أي الوصول إلى نتائج محرك البحث نفسه، باستخدام API ستحصل على النتائج التي تحصل عليها عادةً عند كتابة أي نص ضمن محرك البحث لن يعيد لك قيمة boolean
  2. يمكنك استخدام Programmable Search Engine المقدّمة من جوجل وإضافتها لموقعك، سيتم البحث عن النصوص التي يتم إدخالها وإحضار النتائج من محرك بحث جوجل ضمن موقعك. ويوجد من ضمنها حلول مجانية وأخرى مدفوعة حسب الخصائص التي ترغب بها، يمكنك الاطلاع على كافة التفاصيل وخطوات إضافتها من التوثيق الرسمي بالبحث عن المصطلح Google Programmable Search Engine
  3. FileWriter هو تمثيل للمحارف ويستخدم لكتابة الأحرف بغض النظر عن ترميزها. يستخدم FileWriter داخليًا مجموعة الأحرف الافتراضية لنظام التشغيل الأساسي ليتم تحويل الأحرف إلى بايت وكتابتها على القرص الصلب. يوجد تشابه بين كل من FileWriter و PrintWriter من حيث: كل منهما هو امتداد أو extend من الصف Writer عبارة عم تمثيل للأحرف حيث يتم تحويل الحرف إلى بايت باستخدام مجموعة الأحرف الافتراضية default charset الاختلافات: يرمي FileWriter استثناء من نوع IOException في حال حدوث أي خطأ عند الإدخال والإخراج. أما توابع printWriter فلا تقوم بإلقاء أي استثناء عند حدول أخطاء عند التعامل مع الإدخال والإخراج، بدلاً من ذلك يتم استخدام علامة منطقية boolean والتي يمكن الحصول عليها من خلال استخدام التابع checkError يحوي printWriter على باني Constructor اختياري يمكنك استخدامه لتسهيل عمليات الاستدعاء لدوال معيّنة، أما هذا الباني فهو غير موجود ضمن FileWriter عند الكتابة على الملفات، يحوي FileWriter أيضاً على باني اختياري يسمح له بالإضافة على ملف موجود مسبقاً من خلال التابع write. أما FileOutputStream هو صف فرعي من الصف OutputStream، ويعتبر كتدفق للبيانات الخام (bytes) لنقل البيانات إلى الملفات وحفظها. لكتابة البيانات الأولية ضمن الملفات يكفي استخدام FileOutputStream، أما عند الحاجة لكتابة البيانات المحرفية فيفضل استخدام FileWriter لمزيد من التفاصيل والأمثلة العملية يمكنك الاطلاع على الروابط التالية:
  4. في حال كنت تقصد موقع أكاديمية حسوب، نعم بالتأكيد يمكنك استخدام المتصفح ضمن هاتفك المحمول فالموقع يعمل بشكل ممتاز على جميع الأجهزة ويمكنك متابعة الدروس والمقالات من هاتفك.
  5. من النافذة help ، قم بالضغط على Edit Custom VM options ثم قم بإضافة التالي: -Dconsole.encoding=UTF-8 -Dfile.encoding=UTF-8 في حال لم يتم حل المشكلة، قم بالضغط على زر الإعدادات Settings ثم Editor واختر File Encodings ثم Project Encoding وتأكد من أن الترميز الموجود هو UTF-8. ويوجد اختصار للوصول إلى الترميز السابق من الزاوية السفلى على اليمين ضمن نافذة IntelliJ ستجد اسم الترميز المستخدم حالياً. ويعتبر برنامج VS Code أفضل من IntelliJ من ناحية دعم اللغة العربية بشكل عام.
  6. يمكنك تمرير البيانات ضمن طلب GET من خلال query parameters أو POST من خلال ajax ضمن الحقل data: $.ajax({ url: "/companies", // العنوان type: "get", // نوع الطلب data: { variable: 'value', companyId: CompanyId, companyName: name, ..... }, success: function(response) { }, error: function(xhr) { } }); من جهة الخادم، يوجد عدّة طرق للوصول للبيانات من خلال الطلب request نفسه: public function ajaxRequest(Request $request) { $input = $request->all(); Log::info($input); return response()->json(['success'=>'تم استلام البيانات بنجاح']); } أما بالنسبة للعلاقات many to many، فأقترح عليك قراءة التوثيق الرسمي في لارافيل فالأمثلة كثيرة ويمكنك الاستفادة منها وتجربتها بنفسك، مثال عن جلب البيانات بهذا النوع من العلاقات: $companies = Company::whereHas('owners', function($q) use($ownerIds) { $q->whereIn('id', $ownerIds); })->get(); حيث يتم حقن قائمة بمعرّفات id لحسابات من جدول ما، مع جدول آخر بقاعدة البيانات يدعى Company ويتم المرور على السجلات والتأكد من علاقة الربط من خلال ID. ربما إن شاركت نسخة لارافل التي تستخدمها مع بنية قاعدة البيانات لديك وأجزاء من الشيفرات البرمجية لمشروعك والبيانات التي تريد الاستعلام عنها سنتمكن من إعطائك أمثلة أدق.
  7. استخدام refresh token اختياري وليس إجباري، يعتمد على آلية عمل تطبيقك أو موقعك. في حال كانت مدة انتهاء صلاحية access token قصيرة، يفضّل استخدامه لتحسين تجربة المستخدم وعدم إجباره على إعادة عملية تسجيل الدخول خلال فترات زمنية قصيرة. أما في حال كانت المدّة طويلة لشهر أو أكثر يمكنك الاستغناء عنه ولن يؤثر ذلك على آلية التحقق والتوثيق.
  8. يمكنك إنشاء وتوقيع JWT من طرف الخادم لديك لطلب JWT جديد من خادم جوجل، وبعد الحصول على JWT من خادم جوجل. أما بالنسبة لـ refresh token فيجب عليك وضع الخيار access_type وإعطائه القيمة offline ليتم الرد بـ refresh token على طلب التحقق كالتالي (مثال باستخدام node.js): const authorizationUrl = oauth2Client.generateAuthUrl({ access_type: 'offline', scope: scopes, include_granted_scopes: true }); وعند انتهاء مدة صلاحية access token في الطلب، يتم إعطائك refresh token مباشرةً من قبل خادم جوجل لتستخدمه وتخزّنه في تطبيقك (مثال باستخدام مكتبة oauth2Client): oauth2Client.on('tokens', (tokens) => { if (tokens.refresh_token) { // هنا نضع الشيفرة البرمجية المسؤولة عن تخزين الرمز } }); يمكنك الاطلاع على مزيد من التفاصيل حول آلية عمل refresh token في خوادم جوجل من خلال التوثيق الرسمي لـ Google Identity قد تختلف طريقة تطبيق الآلية السابقة حسب لغات البرمجة التي تستخدمها وأين تستخدم آلية توثيق جوجل من خلال خادم الويب أم من طرف المستخدم بشكل مباشر.
  9. بسبب طبيعة لغة جافاسكريبت الديناميكية فهي بشكل افتراضي لا تدعم أنماط الواجهات كما هو الحال ببقية لغات البرمجة، نعم إن الصف أو Class أصبح موجوداً في النسخ المتقدمة منها ولكن مازال هنالك بعض الحدود عند الحاجة لاستخدام بعض الأنماط المتعارف عليها بلغات البرمجة ومنها الواجهات. ولكن يمكنك البدء باستخدام Typescript، فهي معدّة لهذه الاستخدامات وتدعم جميع خصائص جافاسكريبت بالإضافة إلى إعطائها المزيد من القوة من حيث أنماط البيانات واستخدامات الشيفرة البرمجية المفصلّة والواضحة. فيمكنك ببساطة استخدام الواجهة في typescript كالتالي: interface Person { type: PersonType; name?: string; age?: number; } function printPerson(opts: Person) { // ... }
  10. يمكنك تصفح المواقع الموجودة على الانترنت وملاحظة الألوان التي يتم استخدامها معاً، كما يوجد العديد من المواقع التي تقدّم تركيبات من الألوان جاهزة للاستخدام مثل: colorhunt و coolors و adobe colors وغيرها ستجد الكثير في حال قمت بالبحث عن كلمة color palette في أي محرك بحث. الخبرة في اختيار الألوان والتنسيقات المناسبة تراكمية مثل خبرتك في البرمجة، مع تطبيقك للمزيد من المشاريع ستصل لمرحلة تمكنك من اختيار الألوان المناسبة بسهولة.
  11. في حال لم يكن لديك خبرة في اختيار الألوان المتناسقة يمكنك البحث على الانترنت عن تدرجات اللون الذي ترغب به عن طريق كتابة رمز اللون متبوعاً بـ shares أو gradient أو من خلال موقع أدوبي adobe colors أرجو منك في المرة القادمة كتابة سؤال واضح حتى نستطيع مساعدتك مباشرةً ونفهم المقصود من السؤال.
  12. يوجد أربعة أنواع رئيسية للتدريج في CSS: التدريج الخطي Linear Gradients - التدريج الدائري Radial Gradients - التدريج المخروطي Conic Gradients - التدريج المتكرر Repeating Gradients أكثر الأنواع استخداماً هي التدريج الخطي linear-gradient: background: linear-gradient(<direction>?, <color-stop-1>, <color-stop-2>, ...); direction: جهة التدريج color-stop-1: لون بداية التدريج color-stop-2: لون نهاية التدريج مع إضافة أي ألوان لمراحل تدريج ضمنية مثال: background-color: linear-gradient(to left, #fd4370, blue); أو التدريج الدائري radial-gradient: background: radial-gradient(circle farthest-corner at top left, red, blue); يمكنك الاطلاع على مزيد من التفاصيل حول خصائص التدريج وكيفية التحكّم بالمتغيرات من خلال المقالة التالية:
  13. من صورة النتيجة غير واضح وجود كلمة Scroll now للتأكد من النتيجة يجب عليك إزالة لون الخلفية أو تغيير لون النص ليظهر بشكل واضح، ولكن بشكل عام يوجد العديد من الطرق لتوسيط العناصر والنصوص في CSS، وبما أن العنصر الذي ترغب بتوسيطه عنصر نصي فقط يمكنك إضافة الخاصية text-align إلى هذا العنصر كالتالي: .center { text-align: center; } <section class="container_scroll"> <h1 class="big_scroll center">Scroll Now</h1> <h1 class="scroll"></h1> </section> يمكنك الاطلاع على مزيد من الطرق من هذه المقالات والأسئلة:
  14. CRUD هي اختصار للعمليات التي تتم على البيانات: Create, Read, Update, Delete (إنشاء، قراءة، تعديل، حذف) والمفهوم عام حيث يمكن أن يتم على مصفوفات وبيانات ثابتة في طرف المستخدم لإظهارها والتحكّم بها ضمن واجهة المستخدم وأيضاً من الممكن أن يتم من طرف خادم الويب على قاعدة البيانات والجداول التي يتم التعامل معها في التطبيق أو المشروع. إتقان التعامل مع البيانات سواء كان من طرف المستخدم أو الخادم هو أمر أساسي لأي مبرمج بغض النظر عن التقنيات ولغات البرمجة التي يتعامل معها. وبالنسبة لمطوري واجهات المستخدم front-end غير مطلوب منه التعامل المباشر مع قواعد البيانات (أي تنفيذ استعلامات SQL مثلاً). حيث تعتمد واجهات المستخدم على التخاطب مع خادم الويب فقط وبالتالي لا يوجد تواصل مباشر مع طبقة البيانات. ولكن معرفة أساسيات CRUD ستسهّل على مبرمج واجهات المستخدم كتابة طلبات HTTP وتمرير البيانات اللازمة ليتم التعامل معها بشكل صحيح لاحقاً.
  15. BOM هي اختصار لـ Browser Object Model (نموذج كائن المتصفح): وهي عبارة عن جميع الأغراض الموجودة ضمن النافذة window في المتصفح مثل navigator, history, screen, location, document. أما DOM وهي Document Object Model (نموذج كائن المستند) فهي على مستوى العقد الموجودة ضمن المستند أو صفحة الويب. لذلك كل من DOM و BOM هي مفاهيم خاصة بطرف المستخدم front-end من HTML و جافاسكريبت، ولا علاقة لطرف الخادم أو back-end بها. لمزيد من التفاصيل يمكنك الاطلاع على المصادر التالية:
  16. يتم تخزين التاريخ في MongoDB بشكل افتراضي بنمط Date أو مايعرف بـ ISO Format وكذلك الأمر بالنسبة لـ mongoose في حال كنت تستخدمها. بما يشمل التاريخ والتوقيت أما +00:00 فهي تشير إلى توقيت UTC وهو النمط المناسب لتجنب مشاكل اختلاف التوقيت بين منطقة وأخرى بين المستخدمين. يمكنك الإبقاء على نمط البيانات من نوع Date وإجراء عملية التحويل على مستوى التطبيق عند جلب القيم من خلال تابع التابع dateToString كالتالي: db.dateTest.aggregate( [{ $project: { dateBirth: { $dateToString: { format: “%Y-%m-%d”, date: “$dateBirth” } }, }} ]) //النتيجة { "dateBith" : "2020-09-16" } إذا أردت تخزين التاريخ فقط، يمكنك تغيير نوع الحقل dateBirth إلى سلسلة نصية string وإجراء بعض العمليات على مستوى التطبيق عند الحفظ واستعادة القيم، كما يمكنك تحويله إلى غرض Object وتخزين كل واحدة كخاصية من هذا الغرض، مثال: dateBirth: { type: Object } dateBirth: {year: 1988, month: 12, day: 8} وتخزين التاريخ بهذه الطريقة سيتيح سهولة عند استعادة البيانات لاحقاً وستتمكن من فلترة النتائج حسب تاريخ معيّن دون الحاجة لكتابة المزيد من الشيفرات البرمجية والعمليات الحسابية.
  17. لم تقم بتطبيق التعديلات إذاً. أرفق لك ملفات المشروع وصورة عن النتيجة to-do-list.zip
  18. قم بتعديل الكود الموجود ضمن التابع "getArrayOfTasksFromLocalStorageAndReturnItInDom" ليتم المرور على المحتوى التصي الموجود في العناصر الأبناء والتأكد من عدم وجوده مسبقاً قبل إضافته، بذلك ستتجنب التكرار ويصبح الكود كالتالي: function getArrayOfTasksFromLocalStorageAndReturnItInDom() { arrayOfTasks.forEach((task) => { if ( (document.documentElement.textContent || document.documentElement.innerText).indexOf(task.title) == -1 ) { let div = document.createElement("div"); div.className = "task"; div.appendChild(document.createTextNode(task.title)); tasksDiv.prepend(div); } }); } تأكد من أن تقوم بحذف محتوى local storage بعد إجراء التعديلات من نافذة المطور ضمن المتصفح.
  19. قم بتطبيق النصائح التي ذكرتها ولك، والأهم إزالة إعادة تعريف المتغيّر ضمن التوابع: function getArrayOfTasksFromLocalStorageAndReturnItInDom() { let arrayOfTasks = JSON.parse(localStorage.getItem("arrayOfTasks")); //سبق وعرّفت هذا المتغيّر في أعلى الصفحة arrayOfTasks.forEach((task) => { let div = document.createElement("div"); div.className = "task"; div.appendChild(document.createTextNode(task.title)); tasksDiv.prepend(div); }); } وستحصل على النتيجة كما في الصورة المرفقة. أما بالنسبة بتابع إظهار المهمات، فيجب عليك أيضاً إضافة شرط معيّن كي لا يتم تكرار المهمات وإعادة الحلقة من جديد عند كل عملية إضافة.
  20. يمكنك ذكر الأجزاء التي تحدث فيها مشاكل مع كتابة رسائل الخطأ التي تواجهك وذلك سيساعدنا أكثر على الإجابة على سؤالك. أما بالنسبة للفشل فهذا هو طريق البرمجة، لا يمكنك إنهاء مشروع كامل بجلسة واحدة، ستحاول مراراً وتكراراً وستتعرف في كل مرة على مشاكل جديدة وطرق حل جديدة، ولكن أرى من مشروعك أنك قمت بتطبيق بعض الآليات بشكل صحيح مثل استخدام local storage والتعامل مع المصفوفات. من بعض الملاحظات التي وجدتها هي أنك قمت بتعريف متغيّر arrayOfTasks في بداية الشيفرة البرمجية باستخدام let، ومع ذلك تقوم بإعادة تعريفه من جديد ضمن التوابع، وهذا خطأ كون المتغيّر مسؤول عن التعامل مع البيانات في local storage: let arrayOfTasks; function getArrayOfTasksFromLocalStorageAndReturnItInDom() { let arrayOfTasks = JSON.parse(localStorage.getItem("arrayOfTasks")); arrayOfTasks.forEach((task) => { let div = document.createElement("div"); div.className = "task"; div.appendChild(document.createTextNode(task.title)); tasksDiv.prepend(div); }); } يمكنك استخدام var في بداية الملف والوصول إلى المتغيّر ضمن التوابع لاحقاً. كما لاحظت أنه عند تحميل الصفحة لا يتم استعادة البيانات مع العلم أنها محفوظة ضمن local storage، لذلك يمكنك تغيير الكود الموجود هنا ليصبح كالتالي: if (window.localStorage.length > 0) { arrayOfTasks = JSON.parse(window.localStorage.getItem("arrayOfTasks")); // هنا يتم فقط حفظ البيانات ضمن المتحول دون إظهارها getArrayOfTasksFromLocalStorageAndReturnItInDom(); // يمكنك استدعاء التابع الموجود لديك وسيقوم بإظهارها على الشاشة } else { arrayOfTasks = []; } كما أنصحك بالابتعاد عن تسمية التوابع الطويلة "getArrayOfTasksFromLocalStorageAndReturnItInDom" التي قد تسبب لك أخطاء إملائية عند إعادة كتابة اسم التابع لاحقاً في أماكن مختلفة في الشيفرة البرمجية، ويمكنك مثلاً استبدال الاسم بـ: "getTasksArray" ووضع تعليق بجانب التابع يشرح عمله فذلك أفضل بكثير. وبقية الخصائص أراها تعمل بشكل سليم كما أن تنسيق الصفحة لديك ممتاز ومتجاوب مع جميع الشاشات، تابع المشروع وحاول إضافة آلية الحذف والبحث عن عنوان مهمّة محددة.
  21. التعامل مع التخزين المحلي Local Storage بسيط ويتم من خلال زوج من القيم (key/value): لحفظ البيانات، يتم استخدام التابع setItem ونمرر له متغيّرين من نمط string، المفتاح key و البيانات التي نرغب بتخزينها: localStorage.setItem(key, value); //مثال localStorage.setItem('username', 'Tom'); أما استعادة البيانات المخزنة تتم من خلال التابع getItem ونمرر له المفتاح السابق: const myUsername = localStorage.getItem('username'); console.log(myUsername); // سيتم طباعة Tom لحذف بيانات محددة (مفتاح معيّن) نستخدم التابع التالي: localStorage.removeItem('username'); لحذف كافة البيانات المحفوظة ضمن local storage نستخدم التابع التالي: localStorage.clear(); ملاحظة: يمكننا تخزين القيم بشكل سلاسل نصية string فقط. وفي حال كان لديك أنماط أخرى من البيانات ترغب بتخزينها يجب عليك تحويلها إلى سلسلة نصية عند التخزين واستعادة نمطها الأساسي عند جلب القيم، مثال: var testObject = { 'one': 1, 'two': 2, 'three': 3 }; //عند حفظ القيم يجب تحويلها إلى سلسلة نصية localStorage.setItem('testObject', JSON.stringify(testObject)); var retrievedObject = localStorage.getItem('testObject'); //سيتم استعادة القيم على شكل نص //بعدها يمكننا تحويل القيمة التي استعدناها إلى غرض JSON.parse(retrievedObject) كمبرمج ستجد العديد من الأسئلة أو المشاكل التي قد تواجهك أثناء تطوير مشاريعك، وإذا قمت بالبحث عنها ستجد كمية كبيرة من الإجابات والشروحات ضمن أكاديمية حسوب أو على الانترنت بشكل عام:
  22. إن SQL ليس برنامج بحد ذاته بل هو اختصار لكلمة: Structured Query Language أي لغة الاستعلام العلائقية، وتفيد في استعلام البيانات المحفوظة ضمن قواعد البيانات. مثال: SELECT * FROM Customers; //Customers تقوم بجلب جميع الحقول داخل جدول أما بالنسبة لبرامج المحاسبة، نعم فالعديد من البرامج مبنية باستخدام SQL وغيرها، ولكن يجب عليك الأخذ بعين الاعتبار أن تعمل على توفير واجهات استخدام أيضاً، (الواجهات التي تتفاعل معها مثل الأزرار، حقول النص،...إلخ) ليستطيع المستخدم التحكّم بالبيانات وإجراء الاستعلامات من واجهات بسيطة بدلاً أن يقوم بكتابة استعلامات طويلة في كل مرة. وهنا نجد أن الفرق بين برنامج اكسل و SQL، أن اكسل يتيح لك واجهة جاهزة للتعامل مع البيانات ضمن الخلايا التي تراها على الشاشة، أما SQL فستحتاج لإنشاء مخطط لقواعد البيانات والجداول التي ترغب بحفظ البيانات فيها، ثم تعلّم الاستعلامات وكيفية استخدامها ودمجها مع البرمجة لإنشاء تطبيقات ومواقع ويب كاملة. يمكنك الاطلاع على أساسيات SQL لأخذ فكرة أوضح قبل البدء بتعلّمها والتطبيق العملي من هنا
  23. في كل مرة تقوم بوضع قيم داخل المتحولين state و answers سيتم إزالة المحتويات السابقة ضمن هذه المتغيّرات ووضع قيم جديدة، لذلك تجد فقط أنه تم حفظ آخر قيمة موجودة في هذه المتغيّرات. والسبب واضح ويعود لنوع المتغيّرين state و answers، فلا يمكنك في البرمجة حفظ أكثر من قيمة ضمن متغيّر ذو قيمة وحيدة أو String مثلاً. var myvar = "hello"; myvar = "example"; hello فقط ولن يتم الاحتفاظ بالقيمة example سيصبح محتوى المتغيّر لذلك يجب عليك مراجعة أنماط البيانات في لغة البرمجة التي تحاول تطبيق هذه الآلية فيها والتعرّف على أنماط البيانات التي تقبل أكثر من قيمة على سبيل المثال: المصفوفات Arrays والأغراض Objects وغيرها. var myvar = ["value1","value2","value3"]; عندها ستتمكن من الوصول إلى جميع القيم المخزنة ضمن المصفوفة كما يجب عليك عندها تعلّم كيفية تمرير هذه القيم إلى طرف خادم الويب، فبمعظم الأحيان سيتم تحويلها إلى سلسلة نصية String وبالتالي يجب عليك إعادة تحويلها إلى نمط المصدر من طرف الخادم وإجراء بعض العمليات عليها وإعادة حفظها في النمط الملائم لجداول MySQL لديك.
  24. لقد أخبرتك في التعليق أنه لا يمكنك وضع 6 عناصر بنفس السطر وانتظار الحصول على مسافة بينها، فالعدد كبير ولن يتسع في سطر واحد لذلك سيتم تضييق المسافة بينها كلما زدت عدد العناصر. حاول وضع كل 3 عناصر ضمن div كما أشرت لك في التعليق
  25. في حال كنت تقصد المسافة بين العناصر، flex-wrap لن تضيف أي مسافة. الحل السريع هو باستخدام خاصية justify-content على العنصر الأب الحاوي هذه العناصر: <div class="parent"> <div>...</div> <div>...</div> <div>...</div> </div> .parent { display: flex; justify-content: space-between; } ولكن يجب عليك الانتباه إلى عدد العناصر بأن يكون متناسب مع أحجام الشاشات، كلما زاد عدد العناصر قلّت المسافة بينها لذلك يمكنك فصل الأسطر عن بعضها أي تجميع كل 3 مكونات بوسم div أب. وبالتالي ستتموضع كل 3 عناصر أسفل بعضها البعض. كما يمكنك استخدام space-evenly في حال أردت المسافة متساوية حتى مع اعتبار الهوامش: .parent{ justify-content: space-evenly; }
×
×
  • أضف...