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

Adnane Kadri

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

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

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

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

    51

كل منشورات العضو Adnane Kadri

  1. لاحظ أنك لا تقوم بإرسال أي متغيرات بالمسميات id و type في تحضيرك للطلب POST . فمن المفروض أن يتم تعريف الـ id الخاص بالمورد ضمن نموذج المدخلات ومن ثم إرساله ضمن طلب الـ POST حتى يتم قراءة البيانات من الطلب وتحديث المورد المقصود . مثال عملي : تعريف الـ id كحقل مخفي في نموذج المدخلات : <input type="hidden" value="ضع الايدي هنا" name="supplier_id"/> قراءة المتغير على هذا النحو : var id = $(".spplier_id").val(); إرساله مع باقي المتغيرات في البيانات الممررة عبر الطلب : data:{ "id": id, } و نفس الشيء بالنسبة لـ type . فأرى أنك تقوم بتمرير كامل المتغيرات ما عداهما . ثم سيتم إستقبال الطلب و معالجته بشكل عادي .
  2. و هذا لأن الطلب POST فارغ و لا توجد به أي متغيرات بالمسميات id و index في الحالة الإفتراضية . لحل المشكلة يمكنك إعطاءها أي قيم إفتراضية على هذا النحو : <?php $id = $_POST['id'] ?? null; $type = $_POST['type'] ?? null; أو تمريرها داخل الشرط مثل ما اقترح @بلال زيادة فتكون معرفة في حالة طلبات الـ POST فقط . كما أنه يمكن إختصار الكثير من الأكواد المكررة المطولة لديك . أمثلة عن ذلك : تعريف المتغيرات من text1 حتى text19 و المتغيرات من check1 حتى check7: var texts = []; var checks = []; for (var i = 1; i < 20; ++i) { texts[i] = $(".text-"+i).val(); if(i < 8) { checks[i] = $(".check-" + i).prop("checked"); } } ملفات تعريف الارتباط : // حذف ملفات تعريف الارتباط بعد نجاح الطلب success: function(data) { if (data == "done") { for(var i = 1 ;i < 20; i++) { deleteCookie("text" + i); if(i < 8) { deleteCookie("check" + i); } } } } // تعريف ملفات الارتباط for(var i = 1 ;i < 20; i++) { document.cookie = "text"+ i +"=" + texts[i + 1] + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; if(i < 8) { document.cookie = "check"+ i +"=" + checks[i + 1] + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; } } ثم إرسال المصفوفتين texts و checks عبر الطلب عوضا عن كل المتغيرات فتتم المعالجة على هذا النحو : <?php if ($type == "supp") { for($i = 1;$i < 20 ;$i++) { ${"text".$i} = $_POST['texts'][$i]; if($i < 8) { ${"check".$i} = $_POST['checks'][$i]; } } } سيجعل الكود أقصر , أنظف و أسهل قراءة .
  3. نعم يمكنك ذلك عن طريق الإستعانة بمفهوم المسترجعات والمعدلات (Accessors & Mutators) في لارافال . مثال عملي عن ذلك : نقوم بتعريف معدل جديد بملف مودل المستخدمين على هذا النحو : <?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * Get the user's type. * * @param string $value * @return void */ public function getTypeAttribute($value) { if($value == 0 ) return 'admin'; return 'user'; } } لاحظ كيفية تعريف المعدل : get | {attr} | Attribute attr => capitialized يمكنك القراءة أكثر عن الموضوع من هنا .
  4. هذا الأمر لا يقتصر على فلاتر أو غيره , فكل بوابات الدفع تقدم إما واجهة تطبيق برمجية جاهزة API أو مكتبة SDK يسهل ربطها , دمجها و التعامل معها بأي إطار عمل أو منصة أو أي لغة كانت . و إختيار بوابة الدفع عموما يكون إنطلاقا من إحتياجات أو إختيار عميلك بالدرجة الأولى , ولأسباب أخرى بدرجة ثانية (من مثل المنطقة و الدول المدعومة و العمولات المخصومة على كل تحويل و العروض المتوفرة .. إلخ ) . أما عن بوابات الدفع التي تقبل إشتراك فردي (أشخاص و شركات) لا تشترط و لا تطلب أي سجل تجاري , رقم ضريبي أو بطاقة ضريبية فنذكر من بين أفضلها : بوابة دفع بيبال Paypal, بحيث توفر SDK سهل الإستخدام و الربط و خصوصا مع لغات و منصات الواجهة الأمامية من مثل فلاتر .أؤمن أنها الأفضل في كثير في الحالات , كما توفر أيضا حساب تجريبي (sandbox account) لتجربة التطبيق على مستوى التطوير . باي فورت PayFort, وهي أحد أحد أبرز بوابات الدفع الإلكتروني الرائدة في الشرق الأوسط تم إنشاءها بالإمارات و استحوذت عليها شركة أمازون الان و قد تم تغيير إسمها إلى Amazon Payment Services, تقوم بتوفير API سهل الربط مع تطبيقك . سكريل Skrill, و هي بوابة غنية عن التعريف توفر أيضا واجهة برمجية سهلة الربط . بوابة تتو تشيك أوت 2checkout , و هي واحدة من أكثر البوابات شيوعا , توفر أيضا API سهل الإستخدام بتوثيق مفصل , (قد كنت اخترتها للعديد من العملاء ممن سبق لي التعامل معهم) . للربط مع فلاتر قد تحتاج القراءة أكثر عن قنوات المنصة .
  5. تحسين محركات البحث هو مجال شاسع و من المجحف تلخيصه في مقال واحد , وتنقسم الإستراتيجيات إلى قسمين: على الصفحة، وخارج الصفحة on-page & Off-Page . نذكر من بينها : على الصفحة: شاملة كل العمليات التي يتم القيام بها داخل الموقع نفسه , من تعديل أكواد و إلتزام بنمط معين من كتابة الكود و غيرها . أمثلة : إضافة كلمات مفتاحية و وصف الموقع و أكواد الميتا تاج meta tags ومتابعتها . إضافة عناوين للوسوم الخاصة بالصور داخل الموقع . (alt) . إضافة صفحة robots.txt التي من شأنها توجيه محركات البحث إلى الصفحات المطلوب أرشفتها و تلك الأخرى الممنوعة أو حتى حظر بعد الصفحات . إضافة صفحة خريطة الموقع sitemap.xml و تحديثها بشكل مستمر إن كان الموقع ديناميكي غير ثابت . سكربتات و أكواد الأنماط و النماذج schemas.org لصفحات الموقع لإظهارها بشكل أكثر إحترافية (يمكنك التفصل في الموضوع أكثر من هنا ). محتوى الصفحة , لا بد أن يكون فريدا و غير مأخوذ من أية مواقع أخرى . إضافة الموقع إلى Google Search Console و متابعة الموقع . تقسيم المحتوى إلى عناوين فرعية (headings). خارج الصفحة: شاملة كل العمليات التي تقوم بها خارج الموقع لكسب ثقة محركات البحث، مثل الروابط الخارجية و الـ back linking (ينبغي القراءة في هذا الموضوع بشكل أكثر حيث أن محركات البحث و خصوصا غوغل تعتبر العملية غير شرعية ولو تم كشف ذلك سيتم حظر الموقع نهائيا من الأرشفة , و ذلك لأن منطق محركات البحث هو في أن شيوع موقع يعني تناقل رابطه بين المواقع و هو أمر يجب أن يقوم به زوار و رواد الموقع لا ملاكه أو أصحابه ) . كما يمكنك الإستعانة بهاته المنصات لتحسين ظهور مواقعك و منصاتك : إضافة غوغل كروم lighthouse . Google Search Console . تحليلات غوغل . منصة و أدوات SEMrush لتحسين محركات البحث . أدوات Screaming Frog طبعا تحسين ظهور موقعك لن يكون آنيا و إنما هي عملية تحتاج صبر , وقت و متابعة دائمة .
  6. يمكن القول أنها فقط عبارة عن كنية أو إسم مختصر للمستودع البعيد Remote Repo الذي تم استنساخ المشروع منه . فهو يستخدم بدلا عن عنوان الـ URL للمستودع الأصلي و بالتالي يسهل الرجوع إليه و يكون عوضا عن طباعة هذا كل مرة : git push git@github.com:USERNAME/REPOSITORY-NAME.git YOUR-BRANCH يمكن فقط تنفيذ الأمر بهذا : git push origin YOUR-BRANCH ( طبعا يكون هذا بعد تسجيل المستودع البعيد في حالة إنشاء مشروع جديد . ويكون معينا افتراضيا عن طريق الـ git عند استنساخ مستودع ما . ) طبعا يمكن إعادة تعيين هذا فهو إعداد افتراضي و ليس إلزاما , عن طريق هذا الأمر : git remote rename origin something_else كما يتم تعريفه في مشروع محلي جديد كالتالي : git remote add origin git@github.com:USERNAME/REPOSITORY-NAME.git ليس بالضرورة أن يتم تخصيص branch في حالة ما كان يوجد branch واحد على المستودع البعيد , وليكن master مثلا , يكون الأمر السابق عوضا و بدلا عن الأمر التالي : git push origin master فالأمور ببساطة هي اختصارات و اصطلاحات اعتادت عليها الأوساط البرمجية لا أكثر .
  7. قد قمت بتفحص مستودعك على الـغيت هب و لا أرى إلا branch واحد ليس به أي ملفات github-pages من مثل : index.md , __config.yml أو مجلد docs أو index.html أو readme.md . فحل المشكلة ببساطة هو حذف البيئة التي تستخدمها و إعادة إنشاء صفحات غيت هب من جديد بطريقة صحيحة ( و يستحسن أن تكون في branch جديد غير الـ master ) . أولا : يجب عليك حذف البيئة التي تستخدمها . يمكنك ذلك عن طريق التصفح إلى : الإعدادات settings . البيئات Environments . اضغط على زر الحذف و قم بتأكيد حذف البيئة . ثانيا : الان يمكنك إنشاء صفحة غيت هب جديدة , و احرص على إتباع الخطوات : قم بالتصفح إلى الإعدادات settings. يمكنك النزول إلى قسم صفحات غيت هب ( إن لم يظهر أي نمموذج إدخال قم بالضغط على check it out here فيتم نقلك إلى نموذج الإدخال). إحرص على عدم تعيين أي branch و قم بوضع المصدر source كـ none , هذا سيقوم تلقائيا بإنشاء branch خاصة بصفحات غيت هب و سيعطى الإسم gh-pages تلقائيا . قم بإختيار ثيم ثم قم بعمل commit عن طريق تحديد الثيم و من ثم زر commit . الان يمكنك التصفح إلى المسار الموصوف و سيتم عمل الصفحة بشكل عادي , و تأكد أن تقوم بمسح الملفات المؤقتة في حالة لم تعمل من المرة الأولى .
  8. غرض تمرير بيانات في المسار هو لجعل الصفحة تظهر بشكل ديناميكي غير ثابت , ولفعل هذا في مكتبة gatspy ستحتاج الواجهة createPage لبناء أي صفحات ديناميكية و متغيرة (مثل صفحات البروفايل أو صفحة المنتج أو المقالة و غيرها) , في حين أن كل الصفحات الثابتة تبنى و تصدر بطريقة عادية بداخل src/pages . مثال عملي : بداخل ملف gatsby-node.js نقوم بتصدير الثابت createPages على هذا النحو : export const createPages = ({ actions }) => { const { createPage } = actions; createPage({ // تعريف المسار path: '/users/YOURID', // تعريف المكون المعاد في المسار component: YourRelatedComponent, // إرسال بيانات مخصصة للمكون context: { userID: 'YOURID', }, }); }; ثم يمكنك الوصول للبيانات الممررة بشكل عادي . إقرأ أكثر عن إنشاء و تعديل الصفحات في Gatspy هنا.
  9. يبدو أن المشكلة في الوصول إلى الـ loader بداخل مجلد الـ node_modules . تأكد أن تقوم بإعادة تثبيت url-loader عن طريق الأمر : npm install url-loader --save-dev ثم قم بإعادة البناء . و أيضا , قم بالتأكد أنك تقوم بتمرير اللاحقة loader- لكل الـ loaders المعنية على هذا النحو : loaders: [ { test: /\.css$/, loader: "style-loader!css-loader" }, ] و ذلك عوضا عن : loaders: [ { test: /\.css$/, loader: "style!css" }, ] هذا سيقوم بتجنب مشكلة إعتبار style أو css مثلا (دون لاحقة) كالـ module المعني بالعملية في حين أن القائم بالعملية هي الموديلات css-loader و url-loader و هكذا .
  10. يظهر من الصورة أنك تقومين بفتح مشروع الـ webpack عن طريق ملف الـ index بداخل مجلد dist . و هذا في الغالب سيؤدي بكل مسارات الملفات من الشكل main.css/ التي قد قمت بتضمينها تظهر على هذا النحو بعد البناء : file:///main.css و بالتالي فهي غير قابلة للوصول من الأساس و لو قمت بفتح الـ console ستجدين خطأ يخبرك أن الملفات غير موجودة . فالحل هو فتح المشروع عن طريق طباعة الأمر : npm run serve الذي سيقوم بدوره بطباعة التالي : Project is running at http://localhost:9000/ webpack output is served from / Content not from webpack is served from /path/to/some/path/project/dist wait until bundle finished: / Compiled successfully. بعد البناء بنجاح يمكنك التصفح إلى المسار الموصوف على هذا النحو : http://localhost:9000/ و سيتم إظهار كل الملفات شاملة ملفات التنسيق و السكربتات بشكل صحيح . ملاحظات : في حالة ما لم يعمل الأمر بشكل صحيح و قمت بمواجهة خطأ من هذا النوع : missing script: serve فتأكدي أن تقومي بتسجيل الأمر و إضافته إلى كائن scripts بملف package.json على هذا النحو : "scripts": { "serve": "webpack serve --mode development" }, و الان يمكنك طباعة الأمر و التصفح إلى المسار الموصوف بعد نجاح البناء , و إستعراض مشروعك بشكل عادي .
  11. هل يمكنك إرفاق ملف إعداد webpack حتى يمكننا تشخيص المشكلة بشكل أفضل ؟
  12. يمكننا إستغلال ميزة قواعد البيانات العلائقية لتحقيق الغرض بمنطق مشابه للتالي : لنقم بإنشاء جدول للمواضيع بقاعدة البيانات و ليكن topics . نقوم بإنشاء جدول للصور و ليحتوي على مفتاح أجنبي كعمود : topic_id , يمثل عمود الـ id بجدول المواضيع . فتكون العلاقة بين جدول المواضيع و الصور one to many . طباعة وتنفيذ إستعلام لجلب الصور ذات موضوع محدد على هذا النحو : SELECT * FROM PHOTOS WHERE topic_id = 'YOUR_TOPIC_ID_HERE'; و سيسهل عرضها مباشرة عن طريق الفلاتر .
  13. للمشكلة عدة أسباب محتملة .ولكن الأرجح أنها قد تكون بسبب إستعمال loader واحد لنفس نوع الملف أكثر من مرة فيتم بناء مسار الصورة أكثر من مرة فيتم كسر المسار . مثال عن ذلك : إن كنت تقوم بتحميل الملفات باللواحق woff , woff2 , eot, ttf , png , svg بإستعمال url-loader ثم تقوم بتحميل الملفات باللواحق jpeg , jpg , gif , png , svg بإستعمال url-loader ضمن كائن loader جديد فسيتم كسر مسارات الصور بالصيغ png و svg ولن تظهر في المتصفح . loaders: [ .. { test: /\.(jpe?g|gif|png|svg)$/i, loader: 'url-loader', }, { test: /\.(png|woff|woff2|eot|ttf|svg)$/, loader: 'url-loader' } .. ], الحل : تحميل الملفات من نفس النوع مرة واحدة , بحذف الملفات ذات اللواحق png , svg المكررة فيكون : loaders: [ .. { test: /\.(jpe?g|gif|png|svg)$/i, loader: 'url-loader', }, { test: /\.(woff|woff2|eot|ttf)$/, loader: 'url-loader' } .. ], ملاحظة : ليس بالضرورة أن يكون url-loader , المهم في الإحتمال هو أن يكون قد تم إستعمال نفس الـ loader لنفس لواحق الملفات كذا مرة لا مرة واحدة .
  14. يمكنك معاملة Role كأي Laravel Class ثان , و ليكن في العلم أنه توجد علاقة one To Many بين الدور \App\Models\Role::class و الأذونات \App\Models\Permission::class . يمكنك الوصول إلى الأذونات الخاصة بدور محدد عن طريق : <?php Role::where('name', 'admin')->first()->permissions;
  15. تحديث تحقيقا لنفس الغرض يمكنك جلب الأذونات الخاصة بمستخدم ما عن طريق إستعمال الدالة allPermissions على هذا النحو : <?php dd($user->allPermissions()); سيتم إعادة مجموعة Illuminate\Database\Eloquent\Collection بجميع الأذونات المتعلقة بمستخدم ما , و يمكنك تصفية المجموعات بحسب دور Role معين .
  16. سيكون عليك بناء نموذج إدخال و الواجهة الخلفية للبرنامج حتى يتم ذلك بشكل سليم . يمكنك تطبيق العملية وفق الخطوتين التاليتين : بناء نموذج إدخال البيانات على هذا النحو : <form action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>" method="POST"> <input type="checkbox" name="myCheckBox"/> <input type="hidden" name="idRelated" value="قم بوضع معرف العنصر المراد تغييره هنا"/> <button type="submit">submit</button> </form> بناء الواجهة الخلفية للبرنامج : <?php if($_SERVER["REQUEST_METHOD"] == "POST"){ // إنشاء إتصال بقواعد البيانات و التحقق منه $servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDB"; $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die("فشل الإتصال : " . $conn->connect_error); } // تحضير الإستعلام و تنفيذه $checked = isset($_POST['myCheckbox']) ? 1 : 0; $sql = "UPDATE YourTable SET my_column='".$checked."' WHERE id=".$_POST["idRelated"]; if ($conn->query($sql) === TRUE) { echo "تم تحديث العنصر"; } else { echo "حدث خطأ : " . $conn->error; } $conn->close(); }) فيكون الكود كاملا كالتالي : <?php if($_SERVER["REQUEST_METHOD"] == "POST"){ // إنشاء إتصال بقواعد البيانات و التحقق منه $servername = "localhost"; $username = "username"; $password = "password"; $dbname = "myDB"; $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die("فشل الإتصال : " . $conn->connect_error); } // تحضير الإستعلام و تنفيذه $checked = isset($_POST['myCheckbox']) ? 1 : 0; $sql = "UPDATE YourTable SET my_column='".$checked."' WHERE id=".$_POST["idRelated"]; if ($conn->query($sql) === TRUE) { echo "تم تحديث العنصر"; } else { echo "حدث خطأ : " . $conn->error; } $conn->close(); }) ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>UPDATE ITEM</title> </head> <body> <form action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>" method="POST"> <input type="checkbox" name="myCheckBox"/> <input type="hidden" name="idRelated" value="قم بوضع معرف العنصر المراد تغييره هنا"/> <button type="submit">submit</button> </form> </body> </html> و هذا هو الشكل الأبسط و منطق العملية . يمكنك فعل الأمر عن طريق طلبات Ajax أو تضمين الكود و منطق العملية بصفحة أو نموذج إدخال اخر. الأمر فقط هو في التحقق من تحديد الـ checkbox من عدمه , العملية تبسط في : <?php $checked = null; if(isset($_POST['myCheckbox'])) { $checked = 1; } else() { $checked = 0; } // كتابة مختصرة $checked = isset($_POST['myCheckbox']) ? 1 : 0; ثم يمكنك إدراج القيمة المتحصل عليها بقاعدة البيانات مثل ما هو موصوف في المثال الأول .
  17. يمكنك إما حذف , إخفاء , تعطيل أو حتى إزالة التفاعلية من الزر بعد إستيفاء الغرض منه ( عرض الفيديو ) لتجنب المشكل من الأساس . يمكنك ذلك عن طريق التعديل إلى أحد الأكواد : <!-- حذف الزر --> <button onclick="launchVideo();$(this).remove();">افتح الفيديو</button> <!-- إخفاء الزر --> <button onclick="launchVideo();$(this).hide();">افتح الفيديو</button> <!-- تعطيل الزر --> <button onclick="launchVideo();$(this).attr('disabled', true);">افتح الفيديو</button> <!-- إلغاء تفاعلية الزر --> <button onclick="launchVideo();$(this).attr('onclick', '');">افتح الفيديو</button>
  18. إن كنت تقصد تطبيق طريقة الكود الأول في طريقة وضع الفيديو من الكود الثاني (أي إظهار الفيديو بعد الضغط على الزر في كلتا الحالتين , الأولى و الثانية ) فيمكنك ذلك عن طريق : إنشاء الزر و إضافة حدث عند الضغط عليه : <button onclick="launchVideo();">افتح الفيديو</button> إنشاء عنصر الفيديو و تضمينه بالصفحة : <div class="videoyoutube"><div class="video-responsive"><div class="video-youtube loader lazyload" data-src="//player.vimeo.com/video/90429499"></div></div></div> تعريف الدالة المسؤولة عن بدء الفيديو على هذا النحو : function launchVideo() { $(".video-youtube") .each(function(){ var iframe = '<iframe class="video-youtube loader" src="'+$(this).data("src")+'" allowfullscreen="allowfullscreen" height="281" width="500"></iframe>'; $(this).replaceWith(iframe); }); } فيكون الكود كاملا على هذا النحو : <button onclick="launchVideo();">افتح الفيديو</button> <div class="videoyoutube"> <div class="video-responsive"> <div class="video-youtube loader lazyload" data-src="//player.vimeo.com/video/90429499"> </div> </div> </div> <script> function launchVideo() { $(".video-youtube") .each(function(){ var iframe = '<iframe class="video-youtube loader" src="'+$(this).data("src")+'" allowfullscreen="allowfullscreen" height="281" width="500"></iframe>'; $(this).replaceWith(iframe); }); } </script> هذا سيقوم بتضمين الفيديو بعد الضغط على الزر فقط . بنفس الطريقة فم بإضافة الزر المسؤول عن ملئ الشاشة أسفل عنصر الفيديو : <div id="demo-element"> <button id="go-button" style="background-position: 0% 100%, 100% 0%, 0px 0px, 0px 0px; background-repeat: no-repeat; border-radius: 8px; display: inline-block; font: 25px calibri, Tajawal, sans-serif; padding: 10px 20px; position: relative; text-decoration: none; text-shadow: rgba(255, 255, 255, 0.4) 1px 1px 0px; vertical-align: baseline; white-space: nowrap;">افتح الفيديو في كامل الشاشة</button> </div> ثم قم بإضافة التفاعلية الخاصة بالزر بعد الضغط على تشغيل الفيديو (الموصوفة في التعليق السابق) . ربما قد تحتاج بعض التنسيقات الإضافية . فيكون الكود كاملا مشابها للتالي : <style> #go-button{ background-position: 0% 100%, 100% 0%, 0px 0px, 0px 0px; background-repeat: no-repeat; border-radius: 8px; display: inline-block; font: 25px calibri, Tajawal, sans-serif; padding: 10px 20px; position: relative; text-decoration: none; text-shadow: rgba(255, 255, 255, 0.4) 1px 1px 0px; vertical-align: baseline; white-space: nowrap; } </style> <button onclick="launchVideo();">افتح الفيديو</button> <div class="videoyoutube"> <div class="video-responsive"> <div class="video-youtube loader lazyload" data-src="//player.vimeo.com/video/90429499"> </div> </div> </div> <div id="demo-element"> <button id="go-button">افتح الفيديو في كامل الشاشة</button> </div> <script> // قم ببدء الفيديو function launchVideo() { $(".video-youtube") .each(function(){ var iframe = '<iframe class="video-youtube loader" src="'+$(this).data("src")+'" allowfullscreen="allowfullscreen" height="281" width="500"></iframe>'; $(this).replaceWith(iframe); }); // إضافة تفاعلية لزر ملئ الشاشة setEventForGoButton(); // إضافة تفاعلية لنص الزر handleFullScreen(); } function handleFullScreen() { $(document).on('fullscreenchange webkitfullscreenchange mozfullscreenchange MSFullscreenChange', function() { if(IsFullScreenCurrently()) { $("#demo-element span").text('opn'); $("#go-button").text('bak'); } else { $("#demo-element span").text('bak'); $("#go-button").text('opn'); } }); } function setEventForGoButton() { $("#go-button").on('click', function() { if(IsFullScreenCurrently()) GoOutFullscreen(); else GoInFullscreen($("#demo-element").get(0)); }); } function GoInFullscreen(element) { if(element.requestFullscreen) element.requestFullscreen(); else if(element.mozRequestFullScreen) element.mozRequestFullScreen(); else if(element.webkitRequestFullscreen) element.webkitRequestFullscreen(); else if(element.msRequestFullscreen) element.msRequestFullscreen(); } function GoOutFullscreen() { if(document.exitFullscreen) document.exitFullscreen(); else if(document.mozCancelFullScreen) document.mozCancelFullScreen(); else if(document.webkitExitFullscreen) document.webkitExitFullscreen(); else if(document.msExitFullscreen) document.msExitFullscreen(); } function IsFullScreenCurrently() { var full_screen_element = document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement || null; if(full_screen_element === null) return false; else return true; } </script>
  19. أظن أن قصدك "وضع الكود الثاني و الثالث بداخل الأول" (و هذا تحقيقا للغرض المطلوب). لا حاجة لذلك , يمكنك فصل كل الدوال بحسب المهمة و من ثم إستدعاءهم في دالة واحدة . بداية يمكنك تبسيط العملية أكثر عن طريق التالي : قم بوضع كل الأكواد الأول و الثاني و الثالث بداخل دوال على هذا النحو (وهذا بحسب مبدأ فصل الإهتمامات) : function openVideoFile() { if(!$('#iframe').length) { $('#iframeHolder').html('<iframe id="iframe" src="//player.vimeo.com/video/90429499" width="700" height="450"></iframe>'); } } و : function putVideoInPage() { setTimeout(function(){$(".video-youtube").each(function(){$(this).replaceWith('<iframe class="video-youtube loader" src="'+$(this).data("src")+'" allowfullscreen="allowfullscreen" height="281" width="500"></iframe>')})},5e3); } و : function GoInFullscreen(element) { if(element.requestFullscreen) element.requestFullscreen(); else if(element.mozRequestFullScreen) element.mozRequestFullScreen(); else if(element.webkitRequestFullscreen) element.webkitRequestFullscreen(); else if(element.msRequestFullscreen) element.msRequestFullscreen(); } function GoOutFullscreen() { if(document.exitFullscreen) document.exitFullscreen(); else if(document.mozCancelFullScreen) document.mozCancelFullScreen(); else if(document.webkitExitFullscreen) document.webkitExitFullscreen(); else if(document.msExitFullscreen) document.msExitFullscreen(); } function IsFullScreenCurrently() { var full_screen_element = document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement || null; if(full_screen_element === null) return false; else return true; } و : function setEventForGoButton() { $("#go-button").on('click', function() { if(IsFullScreenCurrently()) GoOutFullscreen(); else GoInFullscreen($("#demo-element").get(0)); }); } و : function handleFullScreen() { $(document).on('fullscreenchange webkitfullscreenchange mozfullscreenchange MSFullscreenChange', function() { if(IsFullScreenCurrently()) { $("#demo-element span").text('opn'); $("#go-button").text('bak'); } else { $("#demo-element span").text('bak'); $("#go-button").text('opn'); } }); } ثم يمكنك دمج و إستدعاء كل الدوال بعد الضغط على زر تشغيل الفيديو على هذا النحو : $(function(){ $('#button').click(function(){ // تضمين الفيديو في الصفحة openVideoFile(); // وضع رابط فيديو بصفحة النشر بدون وضع اكواد فريم putVideoInPage(); // إضافة التفاعلية لزر ملئ الشاشة setEventForGoButton(); // تغيير النصوص بحسب وضع ملئ الشاشة // #demo-element span النصوص المعرفة بـ handleFullScreen(); }); }); ملاحظات : الكثير من الأكواد غير واضحة المهمة في الأكواد التي أرفقتها و لا يظهر بالنسبة لي أي ترابط بين الكود الثاني و الأكواد الأخرى , و رغم ذلك قد قمت بتضيمنها في الأكواد التي وصفتها لك (يمكن لأن ذلك راجع إلى غياب باقي عناصر الصفحة ) . يمكنك تتبع نفس المنطق لكتابة دالة تجمع عمل كل الدوال المعرفة (ألف دالة تقوم بألف مهمة أفضل من دالة تقوم بألف مهمة) , سيكون الكود أفضل قراءة و أكثر وضوحا.
  20. لا يمكنك طباعة كل المتغيرات مرة واحدة , عوضا عن ذلك يجب تمرير اسم المتغير لتتم القراءة بشكل صحيح أثناء البناء , و ببساطة هذا ﻷن متصفح الواجهة الأمامية نفسه ليس له أي وصول لملف البيئة فالعملية تخص الخادم وحده و لذلك أثناء البناء يتم إستبدال أي متغير معرف على هذا النحو : process.env.MY_VAR بقيمته الفعلية و يتم البناء بشكل عادي . في حين أن المتغير : process.env يتم تجاهله بطبيعة الحال و يتم إعادة كائن فارغ عن طريقه . فعوضا عن طباعة كل المتغيرات يمكنك فقط طباعة المتغير الذي تحتاج و إستعماله بشكل عادي .
  21. لما لا تقوم فقط بتحميله تزامنيا ثم تضمينه بالصفحة ؟ componentDidMount() { // script إنشاء عنصر بوسم const script = document.createElement("script"); // تعريف المسار أو الرابط script.src = "/path/to/my_scripts.js"; // تفعيل التزامن و الوصول اليه script.async = true; script.onload = () => this.scriptLoaded(); // تضمينه في البودي document.body.appendChild(script); }
  22. يمكنك تضمين useLocation من @reach/router و من ثم قراءة القيمة على هذا النحو : import * as React from 'react'; import { useLocation } from '@reach/router'; const Current = () => { const location = useLocation(); console.log(location); }; سيتم طباعة كائن يسهل قراءة الخواص منه على هذا النحو : { pathname: "/", href: "http://localhost:8000/", origin: "http://localhost:8000" }
  23. يمكنك استبدال المسار الأخير (تأكد أنه الأخير دوما) على هذا النحو : <Route component = {NotFound} /> // هذا <Redirect to="/" /> // بهذا سيتم تتبع كل المسارات التي تختلف عن المسارات التي هي ما قبل هذا المسار و بدل عرض مكون react سيعاد توجيه المستخدم إلى الصفحة الرئيسية . و يمكنك عمل ذلك عن طريق مكتبة Gatspy على هذا النحو : ليكن في العلم أن صفحة 404 المنشئة من طرف المكتبة تكون بـ src/pages/404.jsx أو src/pages/404.js يمكنك تعديلها على هذا النحو لتقوم بنفس المهمة : import React from 'react' import { navigate } from 'gatsby' const NotFoundPage = () => { return navigate('/') } export default NotFoundPage
  24. هل يمكنك ذكر نوع محرر النصوص الذي تستخدمه ؟ أو على الأقل إرفاق صورة لذلك
  25. و هذا هو دور مطوري الواجهة الخلفية و قواعد البيانات . فهم المسؤولون عن جعل عملية إضافة المنتجات ( أو أي نوع اخر من المدخلات ) في قاعدة البيانات و التحكم بها عملية بسيطة من خلال واجهة إدخال يهتم مطور الواجهة الأمامية بتصميمها . يستعملون لإدارة قواعدة البيانات أشياء من مثل MySQL , MongoDB , Oracle , SQLServer , Redis .. الخ . أو ربما بعض اليات التخزين المؤقتة من مثل varnish , Memcached , redis .. الخ . و يحتاجون على الأقل للغة برمجة لهندسة الواجهة الخلفية و تولي كل الأشياء التي تحدث على مستوى الخادم . لغات من مثل Java , Python , Ruby , Php , .net .. الخ . فالمواقع من مثل مثالك لا تكتمل إلا بجزئيها و واجهتيها , الأمامية و الخلفية .
×
×
  • أضف...