-
المساهمات
5129 -
تاريخ الانضمام
-
تاريخ آخر زيارة
-
عدد الأيام التي تصدر بها
51
نوع المحتوى
ريادة الأعمال
البرمجة
التصميم
DevOps
التسويق والمبيعات
العمل الحر
البرامج والتطبيقات
آخر التحديثات
قصص نجاح
أسئلة وأجوبة
كتب
دورات
كل منشورات العضو Adnane Kadri
-
لاحظ أنك لا تقوم بإرسال أي متغيرات بالمسميات id و type في تحضيرك للطلب POST . فمن المفروض أن يتم تعريف الـ id الخاص بالمورد ضمن نموذج المدخلات ومن ثم إرساله ضمن طلب الـ POST حتى يتم قراءة البيانات من الطلب وتحديث المورد المقصود . مثال عملي : تعريف الـ id كحقل مخفي في نموذج المدخلات : <input type="hidden" value="ضع الايدي هنا" name="supplier_id"/> قراءة المتغير على هذا النحو : var id = $(".spplier_id").val(); إرساله مع باقي المتغيرات في البيانات الممررة عبر الطلب : data:{ "id": id, } و نفس الشيء بالنسبة لـ type . فأرى أنك تقوم بتمرير كامل المتغيرات ما عداهما . ثم سيتم إستقبال الطلب و معالجته بشكل عادي .
- 6 اجابة
-
- 1
-
و هذا لأن الطلب 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]; } } } سيجعل الكود أقصر , أنظف و أسهل قراءة .
- 6 اجابة
-
- 1
-
نعم يمكنك ذلك عن طريق الإستعانة بمفهوم المسترجعات والمعدلات (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 يمكنك القراءة أكثر عن الموضوع من هنا .
- 2 اجابة
-
- 2
-
هذا الأمر لا يقتصر على فلاتر أو غيره , فكل بوابات الدفع تقدم إما واجهة تطبيق برمجية جاهزة API أو مكتبة SDK يسهل ربطها , دمجها و التعامل معها بأي إطار عمل أو منصة أو أي لغة كانت . و إختيار بوابة الدفع عموما يكون إنطلاقا من إحتياجات أو إختيار عميلك بالدرجة الأولى , ولأسباب أخرى بدرجة ثانية (من مثل المنطقة و الدول المدعومة و العمولات المخصومة على كل تحويل و العروض المتوفرة .. إلخ ) . أما عن بوابات الدفع التي تقبل إشتراك فردي (أشخاص و شركات) لا تشترط و لا تطلب أي سجل تجاري , رقم ضريبي أو بطاقة ضريبية فنذكر من بين أفضلها : بوابة دفع بيبال Paypal, بحيث توفر SDK سهل الإستخدام و الربط و خصوصا مع لغات و منصات الواجهة الأمامية من مثل فلاتر .أؤمن أنها الأفضل في كثير في الحالات , كما توفر أيضا حساب تجريبي (sandbox account) لتجربة التطبيق على مستوى التطوير . باي فورت PayFort, وهي أحد أحد أبرز بوابات الدفع الإلكتروني الرائدة في الشرق الأوسط تم إنشاءها بالإمارات و استحوذت عليها شركة أمازون الان و قد تم تغيير إسمها إلى Amazon Payment Services, تقوم بتوفير API سهل الربط مع تطبيقك . سكريل Skrill, و هي بوابة غنية عن التعريف توفر أيضا واجهة برمجية سهلة الربط . بوابة تتو تشيك أوت 2checkout , و هي واحدة من أكثر البوابات شيوعا , توفر أيضا API سهل الإستخدام بتوثيق مفصل , (قد كنت اخترتها للعديد من العملاء ممن سبق لي التعامل معهم) . للربط مع فلاتر قد تحتاج القراءة أكثر عن قنوات المنصة .
- 1 جواب
-
- 1
-
تحسين محركات البحث هو مجال شاسع و من المجحف تلخيصه في مقال واحد , وتنقسم الإستراتيجيات إلى قسمين: على الصفحة، وخارج الصفحة 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 طبعا تحسين ظهور موقعك لن يكون آنيا و إنما هي عملية تحتاج صبر , وقت و متابعة دائمة .
- 5 اجابة
-
- 2
-
يمكن القول أنها فقط عبارة عن كنية أو إسم مختصر للمستودع البعيد 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 فالأمور ببساطة هي اختصارات و اصطلاحات اعتادت عليها الأوساط البرمجية لا أكثر .
- 2 اجابة
-
- 2
-
قد قمت بتفحص مستودعك على الـغيت هب و لا أرى إلا 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 . الان يمكنك التصفح إلى المسار الموصوف و سيتم عمل الصفحة بشكل عادي , و تأكد أن تقوم بمسح الملفات المؤقتة في حالة لم تعمل من المرة الأولى .
- 4 اجابة
-
- 1
-
غرض تمرير بيانات في المسار هو لجعل الصفحة تظهر بشكل ديناميكي غير ثابت , ولفعل هذا في مكتبة 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 هنا.
- 1 جواب
-
- 1
-
يبدو أن المشكلة في الوصول إلى الـ 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 و هكذا .
- 2 اجابة
-
- 1
-
يظهر من الصورة أنك تقومين بفتح مشروع الـ 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" }, و الان يمكنك طباعة الأمر و التصفح إلى المسار الموصوف بعد نجاح البناء , و إستعراض مشروعك بشكل عادي .
- 3 اجابة
-
- 2
-
يمكننا إستغلال ميزة قواعد البيانات العلائقية لتحقيق الغرض بمنطق مشابه للتالي : لنقم بإنشاء جدول للمواضيع بقاعدة البيانات و ليكن topics . نقوم بإنشاء جدول للصور و ليحتوي على مفتاح أجنبي كعمود : topic_id , يمثل عمود الـ id بجدول المواضيع . فتكون العلاقة بين جدول المواضيع و الصور one to many . طباعة وتنفيذ إستعلام لجلب الصور ذات موضوع محدد على هذا النحو : SELECT * FROM PHOTOS WHERE topic_id = 'YOUR_TOPIC_ID_HERE'; و سيسهل عرضها مباشرة عن طريق الفلاتر .
- 3 اجابة
-
- 1
-
للمشكلة عدة أسباب محتملة .ولكن الأرجح أنها قد تكون بسبب إستعمال 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 لنفس لواحق الملفات كذا مرة لا مرة واحدة .
-
يمكنك معاملة Role كأي Laravel Class ثان , و ليكن في العلم أنه توجد علاقة one To Many بين الدور \App\Models\Role::class و الأذونات \App\Models\Permission::class . يمكنك الوصول إلى الأذونات الخاصة بدور محدد عن طريق : <?php Role::where('name', 'admin')->first()->permissions;
- 4 اجابة
-
- 1
-
تحديث تحقيقا لنفس الغرض يمكنك جلب الأذونات الخاصة بمستخدم ما عن طريق إستعمال الدالة allPermissions على هذا النحو : <?php dd($user->allPermissions()); سيتم إعادة مجموعة Illuminate\Database\Eloquent\Collection بجميع الأذونات المتعلقة بمستخدم ما , و يمكنك تصفية المجموعات بحسب دور Role معين .
- 4 اجابة
-
- 1
-
سيكون عليك بناء نموذج إدخال و الواجهة الخلفية للبرنامج حتى يتم ذلك بشكل سليم . يمكنك تطبيق العملية وفق الخطوتين التاليتين : بناء نموذج إدخال البيانات على هذا النحو : <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; ثم يمكنك إدراج القيمة المتحصل عليها بقاعدة البيانات مثل ما هو موصوف في المثال الأول .
- 1 جواب
-
- 2
-
يمكنك إما حذف , إخفاء , تعطيل أو حتى إزالة التفاعلية من الزر بعد إستيفاء الغرض منه ( عرض الفيديو ) لتجنب المشكل من الأساس . يمكنك ذلك عن طريق التعديل إلى أحد الأكواد : <!-- حذف الزر --> <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>
- 6 اجابة
-
- 1
-
إن كنت تقصد تطبيق طريقة الكود الأول في طريقة وضع الفيديو من الكود الثاني (أي إظهار الفيديو بعد الضغط على الزر في كلتا الحالتين , الأولى و الثانية ) فيمكنك ذلك عن طريق : إنشاء الزر و إضافة حدث عند الضغط عليه : <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>
- 6 اجابة
-
- 1
-
أظن أن قصدك "وضع الكود الثاني و الثالث بداخل الأول" (و هذا تحقيقا للغرض المطلوب). لا حاجة لذلك , يمكنك فصل كل الدوال بحسب المهمة و من ثم إستدعاءهم في دالة واحدة . بداية يمكنك تبسيط العملية أكثر عن طريق التالي : قم بوضع كل الأكواد الأول و الثاني و الثالث بداخل دوال على هذا النحو (وهذا بحسب مبدأ فصل الإهتمامات) : 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(); }); }); ملاحظات : الكثير من الأكواد غير واضحة المهمة في الأكواد التي أرفقتها و لا يظهر بالنسبة لي أي ترابط بين الكود الثاني و الأكواد الأخرى , و رغم ذلك قد قمت بتضيمنها في الأكواد التي وصفتها لك (يمكن لأن ذلك راجع إلى غياب باقي عناصر الصفحة ) . يمكنك تتبع نفس المنطق لكتابة دالة تجمع عمل كل الدوال المعرفة (ألف دالة تقوم بألف مهمة أفضل من دالة تقوم بألف مهمة) , سيكون الكود أفضل قراءة و أكثر وضوحا.
- 6 اجابة
-
- 1
-
لا يمكنك طباعة كل المتغيرات مرة واحدة , عوضا عن ذلك يجب تمرير اسم المتغير لتتم القراءة بشكل صحيح أثناء البناء , و ببساطة هذا ﻷن متصفح الواجهة الأمامية نفسه ليس له أي وصول لملف البيئة فالعملية تخص الخادم وحده و لذلك أثناء البناء يتم إستبدال أي متغير معرف على هذا النحو : process.env.MY_VAR بقيمته الفعلية و يتم البناء بشكل عادي . في حين أن المتغير : process.env يتم تجاهله بطبيعة الحال و يتم إعادة كائن فارغ عن طريقه . فعوضا عن طباعة كل المتغيرات يمكنك فقط طباعة المتغير الذي تحتاج و إستعماله بشكل عادي .
- 2 اجابة
-
- 1
-
لما لا تقوم فقط بتحميله تزامنيا ثم تضمينه بالصفحة ؟ 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); }
- 2 اجابة
-
- 1
-
يمكنك تضمين 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" }
-
يمكنك استبدال المسار الأخير (تأكد أنه الأخير دوما) على هذا النحو : <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
-
هل يمكنك ذكر نوع محرر النصوص الذي تستخدمه ؟ أو على الأقل إرفاق صورة لذلك
-
و هذا هو دور مطوري الواجهة الخلفية و قواعد البيانات . فهم المسؤولون عن جعل عملية إضافة المنتجات ( أو أي نوع اخر من المدخلات ) في قاعدة البيانات و التحكم بها عملية بسيطة من خلال واجهة إدخال يهتم مطور الواجهة الأمامية بتصميمها . يستعملون لإدارة قواعدة البيانات أشياء من مثل MySQL , MongoDB , Oracle , SQLServer , Redis .. الخ . أو ربما بعض اليات التخزين المؤقتة من مثل varnish , Memcached , redis .. الخ . و يحتاجون على الأقل للغة برمجة لهندسة الواجهة الخلفية و تولي كل الأشياء التي تحدث على مستوى الخادم . لغات من مثل Java , Python , Ruby , Php , .net .. الخ . فالمواقع من مثل مثالك لا تكتمل إلا بجزئيها و واجهتيها , الأمامية و الخلفية .