Detecting if the user is online with JavaScript
عندك شات أبلكيشن وعاوز تضيف فيه feature اذا كان الشخص أونلاين ولا بأسهل طريقة ؟
هنستخدم ال navigator.onLine web api
window.addEventListener('load', () => {
const status = navigator.onLine;
});
وهنا ال status هترجع boolean value
بس خلي بالك دا هيبقي عظيم ك أول load لل page
بس لو الnetwork status اتغيرت هنا الحل انك تعمل Subscribe لل offline and online events
عشان ت listen ع أي تغيير و ت update Status
window.addEventListener('offline', (e) => {
console.log('offline');
});
window.addEventListener('online', (e) => {
console.log('online');
});
عندك شات أبلكيشن وعاوز تضيف فيه feature اذا كان الشخص أونلاين ولا بأسهل طريقة ؟
هنستخدم ال navigator.onLine web api
window.addEventListener('load', () => {
const status = navigator.onLine;
});
وهنا ال status هترجع boolean value
بس خلي بالك دا هيبقي عظيم ك أول load لل page
بس لو الnetwork status اتغيرت هنا الحل انك تعمل Subscribe لل offline and online events
عشان ت listen ع أي تغيير و ت update Status
window.addEventListener('offline', (e) => {
console.log('offline');
});
window.addEventListener('online', (e) => {
console.log('online');
});
❤3👍2
Removing Object Properties in Js
فيه أكتر من طريقة عشان أقدر أحقق دا ؟
عندي اتنين object والهدف بتاعي إني أخليهم similar
let object1 = {
a: "hello",
b: "world",
c: "!!!",
};
let object2 = {
a: "hello",
b: "world",
};
عشان أحقق الهدف بكل بساطة ه delete the c property
ودي الطرق اللي هنجربها عشان نحقق الهدف بالترتيب ، والترتيب دا هيوصلنا لحاجة أهم من الهدف
- هجرب إني أعمل set c to undefined
- هستخدم ال delete operator
- هستخدم ال proxy built in object عن طريق إني هعمل deleted c property through a Proxy object
- فاكر ال MUTATION إتكلمنا عليها قبل كدا هجرب إني أتجنبه عن طريفق اني أستخدم object destructuring
- هستخدم JSON.stringify and JSON.parse
- rely on Lodash
يبقي هنجرب كل دول بالترتيب ونشوف هنوصل لإيه
//I Set c To undefined
أول طريقة دي بالرغم من سطحيتها إلا أني هجربها لسبب ما تعال نعرفه مع بعض
لو قلتلك تعال ن
console.log(object1.d); // undefined
عشان مفيش عندي property إسمها d أصلا طب م تيجي نجرب ن Set c ل undefined
object1.c = undefined;
الoutput بقي ؟
let object1 = {
a: "hello",
b: "world",
c: undefined,
};
زي م انت شايف ال c هتفضل موجودة جوا ال object1 رغم ان قيمتها undefined
الapproach دا مش بيعمل actually delete إنما بيغير القيمة بتاعة ال property نتأكد بحاجة بسيطة
const propertyExists =object1.hasOwnProperty("c");
console.log(propertyExists); // true
طب لو بجرب access property مش موجودة أصلا زي object1.d
مش المفروض ت throw an error زي accessing a non-existing variable بيجيب ايرور زي دا
// Uncaught ReferenceError: اسم المتغير اللي مش موجود is not defined
طب ليه لما بأكسس object1.d بيجيب ليا undefined ؟
الإجابة بكل بساطة هي انك تفهم ازاي الReferenceError بيbehaves وإيه هو أصلا ؟
A reference is a resolved name binding that indicates where a value is stored. It consists of three components: a base value, the referenced name, and a strict reference flag.
عشان نفهم الكلام دا تعال نطبقه ع مثال لو عندك object of user وجواه name property
فال user.name reference دي ال baseValue بتاعتها ال user Object وال referenced name is the string, name وال strict reference flag دي بتبقي boolean value حسب انت في ال ٍstrict mode ولا لا
ال Variables بقي بت behave بطريقة مختلفة تماما لإنها معندهاش parent object ف بتكون ال base value هي قيمة ال environment record ف انت ال base value دي بيحصلها assigned كل مرة الكود بيتنفذ
ف عشان كدا لما بتحاول تaccess أي حاجة ملهاش base value ال JavaScript هتديك ReferenceError ومع ذلك لو ال base value موجودة بس referenced name مبيعملش point لقيمة موجودة
ال , JavaScript بكل بساطة هت assign ال value ل undefined
ودا من ال ECMAScript Specification
“The Undefined type has exactly one value, called undefined. Any variable that has not been assigned a value has the value undefined.”
—————————————————
تاني طريقة وهيdelete Operator
ودي هتمسح ال property فعلا بس فيه بعض التحفظات لازم تأخدها ف الإعتبار قبل م تستخدمها
أول تحفظ انك لو بتستخدمها مع ال array
const movies = ["Interstellar", "Top Gun", "6 underground", "V for Vendetta"];
فيه أكتر من طريقة عشان أقدر أحقق دا ؟
عندي اتنين object والهدف بتاعي إني أخليهم similar
let object1 = {
a: "hello",
b: "world",
c: "!!!",
};
let object2 = {
a: "hello",
b: "world",
};
عشان أحقق الهدف بكل بساطة ه delete the c property
ودي الطرق اللي هنجربها عشان نحقق الهدف بالترتيب ، والترتيب دا هيوصلنا لحاجة أهم من الهدف
- هجرب إني أعمل set c to undefined
- هستخدم ال delete operator
- هستخدم ال proxy built in object عن طريق إني هعمل deleted c property through a Proxy object
- فاكر ال MUTATION إتكلمنا عليها قبل كدا هجرب إني أتجنبه عن طريفق اني أستخدم object destructuring
- هستخدم JSON.stringify and JSON.parse
- rely on Lodash
يبقي هنجرب كل دول بالترتيب ونشوف هنوصل لإيه
//I Set c To undefined
أول طريقة دي بالرغم من سطحيتها إلا أني هجربها لسبب ما تعال نعرفه مع بعض
لو قلتلك تعال ن
console.log(object1.d); // undefined
عشان مفيش عندي property إسمها d أصلا طب م تيجي نجرب ن Set c ل undefined
object1.c = undefined;
الoutput بقي ؟
let object1 = {
a: "hello",
b: "world",
c: undefined,
};
زي م انت شايف ال c هتفضل موجودة جوا ال object1 رغم ان قيمتها undefined
الapproach دا مش بيعمل actually delete إنما بيغير القيمة بتاعة ال property نتأكد بحاجة بسيطة
const propertyExists =object1.hasOwnProperty("c");
console.log(propertyExists); // true
طب لو بجرب access property مش موجودة أصلا زي object1.d
مش المفروض ت throw an error زي accessing a non-existing variable بيجيب ايرور زي دا
// Uncaught ReferenceError: اسم المتغير اللي مش موجود is not defined
طب ليه لما بأكسس object1.d بيجيب ليا undefined ؟
الإجابة بكل بساطة هي انك تفهم ازاي الReferenceError بيbehaves وإيه هو أصلا ؟
A reference is a resolved name binding that indicates where a value is stored. It consists of three components: a base value, the referenced name, and a strict reference flag.
عشان نفهم الكلام دا تعال نطبقه ع مثال لو عندك object of user وجواه name property
فال user.name reference دي ال baseValue بتاعتها ال user Object وال referenced name is the string, name وال strict reference flag دي بتبقي boolean value حسب انت في ال ٍstrict mode ولا لا
ال Variables بقي بت behave بطريقة مختلفة تماما لإنها معندهاش parent object ف بتكون ال base value هي قيمة ال environment record ف انت ال base value دي بيحصلها assigned كل مرة الكود بيتنفذ
ف عشان كدا لما بتحاول تaccess أي حاجة ملهاش base value ال JavaScript هتديك ReferenceError ومع ذلك لو ال base value موجودة بس referenced name مبيعملش point لقيمة موجودة
ال , JavaScript بكل بساطة هت assign ال value ل undefined
ودا من ال ECMAScript Specification
“The Undefined type has exactly one value, called undefined. Any variable that has not been assigned a value has the value undefined.”
—————————————————
تاني طريقة وهيdelete Operator
ودي هتمسح ال property فعلا بس فيه بعض التحفظات لازم تأخدها ف الإعتبار قبل م تستخدمها
أول تحفظ انك لو بتستخدمها مع ال array
const movies = ["Interstellar", "Top Gun", "6 underground", "V for Vendetta"];
👏3❤1
delete movies[2];
console.log(movies) //["Interstellar", "Top Gun", empty , "V for Vendetta"];
هتلاقي بكل بساطة ان هي بتسيب مكانه فاضي ودا unexpected behavior هيسببلك مشاكل لو بتستخدم بعض ال properties كlength
console.log(movies.length); // 4
ألتحفظ التاني وهو
const user = {
name: "Zezo",
birthday: {day: 2, month: 11},
};
لو حاولت انك delete ال birthday property هتشتغل كويس بس فيه misconception هنا مهم جدا وهو انك لما تعمل كدا دا frees up the memory allocated for the object ودا مبيحصلش
ليه بقي ؟ ببساطة كلنا عارفين ان ال JavaScript بت behave بشكل مختلف مع ال Objects مقارنة ب primitive values (e.g., numbers, strings, and booleans) بالذات ازاي بيتم تخزينهم ف الميموري
يعني لو انت بت Assign variable ب variable تاني ف الاتنين مش هيكونوا related ببعض وهيكونوا كل واحد منهم له independent space in memory
ع عكس لما بت Assign object ب object تاني وبعدين تعدل property في ال onbject دا بتلاقيها اتعدلت ف الاتنين واتأثرت عشان كل اللي بتعمله انك duplicating its reference
و Under the hood, JavaScript looks at the actual object in memory and performs the change, and both references point to the changed object
طبعا الكلام دا انت عارفه دلوقتي نقدر نفهم ازاي delete operator doesn’t free space in memory
بص ي سيدي العملية اللي لغات البرمجة بت free memory بيها اسمها garbage collection
في ال JavaScript العملية دي بتتم مع الobject لما ميكونش فيه أي حاجة بت reference له "is not needed anymore"
عشان كدا using the delete operator مش هخيكون مناسب معايا ف بعض لالحالات وكمان ف بعض التحفظات ان هي بت impact on performance
console.log(movies) //["Interstellar", "Top Gun", empty , "V for Vendetta"];
هتلاقي بكل بساطة ان هي بتسيب مكانه فاضي ودا unexpected behavior هيسببلك مشاكل لو بتستخدم بعض ال properties كlength
console.log(movies.length); // 4
ألتحفظ التاني وهو
const user = {
name: "Zezo",
birthday: {day: 2, month: 11},
};
لو حاولت انك delete ال birthday property هتشتغل كويس بس فيه misconception هنا مهم جدا وهو انك لما تعمل كدا دا frees up the memory allocated for the object ودا مبيحصلش
ليه بقي ؟ ببساطة كلنا عارفين ان ال JavaScript بت behave بشكل مختلف مع ال Objects مقارنة ب primitive values (e.g., numbers, strings, and booleans) بالذات ازاي بيتم تخزينهم ف الميموري
يعني لو انت بت Assign variable ب variable تاني ف الاتنين مش هيكونوا related ببعض وهيكونوا كل واحد منهم له independent space in memory
ع عكس لما بت Assign object ب object تاني وبعدين تعدل property في ال onbject دا بتلاقيها اتعدلت ف الاتنين واتأثرت عشان كل اللي بتعمله انك duplicating its reference
و Under the hood, JavaScript looks at the actual object in memory and performs the change, and both references point to the changed object
طبعا الكلام دا انت عارفه دلوقتي نقدر نفهم ازاي delete operator doesn’t free space in memory
بص ي سيدي العملية اللي لغات البرمجة بت free memory بيها اسمها garbage collection
في ال JavaScript العملية دي بتتم مع الobject لما ميكونش فيه أي حاجة بت reference له "is not needed anymore"
عشان كدا using the delete operator مش هخيكون مناسب معايا ف بعض لالحالات وكمان ف بعض التحفظات ان هي بت impact on performance
👏5❤1
تالت طريقة وهي Deleted The Property Through A Proxy Object
ايه هو ال proxy الأول
A proxy is a way to insert some middle logic between an object’s common operations, like getting, setting, defining, and, deleting properties.
حلو ؟ ال Proxy بيأخد اتنين parameters
target: The object from where we want to create a proxy.
handler: An object containing the middle logic for the operations.
يعني ببساطة بتديلها الobject وتديلها ال logic اللي عاوز تطبقه
جوا ال handler احنا بنعرف methodes لأي operations وبنسميها traps ليه بقي ؟
because they intercept the original operation and perform a custom change
والنتيجة هتكون ان constructor هي return a Proxy object
واللي هيكون identical لل target بس with the added middle logic
تعال نبص ع مثال ؟
const user = {
name : "zezo",
age: 24,
};
const handler = {
get(target, property) {
return
},
};
const userProxy = new Proxy(user, handler);
console.log(userProxy.name); // user's breed is zezo
console.log(userProxy.age); // user's age is 24
في المثل دا ال handler عمل modifies لل getting operation عشان ت return a custom value
طب لو عاوز أ modifie ال Deleting operation ؟
const handler = {
deleteProperty(target, property) {
console.log(Deleting property: ${property});
},
};
هتحط دي جوا ال handler ف لو جيت
const userProxy = new Proxy(user, handler);
delete userProxy.name; // Deleting property: name
هتلاقي دا ال output ولو جيت ت
console.log(userProxy) // { name : "zezo", age: 24,};
متمسحتش !
عشان إحنا ببساطة بدلنا الdelete operator’s default behavior بcustom behavior
اي اللي ييجي يلعب دور مهم هنا ؟ بقي Reflect
اي ال reflect دي؟
Reflect is a global object with a collection of all the internal methods of an object. Its methods can be used as normal operations anywhere, but it’s meant to be used inside a proxy.
بص هنستفيد من Reflect ازاي ف مثالنا
const handler = {
deleteProperty(target, property) {
console.log(Deleting property: ${property});
return Reflect.deleteProperty(target, property);
},
};
const userProxy = new Proxy(user, handler);
delete userProxy.name; // Deleting property: name
في حاجة مهمة هنا لازم أنوه ليها ؟
في بعض ال built in objects زي Math, Date, and JSON وغيرهم مقدرش أ delete منهم عشان ببساطة هما “non-configurable” object properties
يعني مينفعش أعملهم reassign or delete
ايه هو ال proxy الأول
A proxy is a way to insert some middle logic between an object’s common operations, like getting, setting, defining, and, deleting properties.
حلو ؟ ال Proxy بيأخد اتنين parameters
target: The object from where we want to create a proxy.
handler: An object containing the middle logic for the operations.
يعني ببساطة بتديلها الobject وتديلها ال logic اللي عاوز تطبقه
جوا ال handler احنا بنعرف methodes لأي operations وبنسميها traps ليه بقي ؟
because they intercept the original operation and perform a custom change
والنتيجة هتكون ان constructor هي return a Proxy object
واللي هيكون identical لل target بس with the added middle logic
تعال نبص ع مثال ؟
const user = {
name : "zezo",
age: 24,
};
const handler = {
get(target, property) {
return
user's ${property} is ${target[property]}
;},
};
const userProxy = new Proxy(user, handler);
console.log(userProxy.name); // user's breed is zezo
console.log(userProxy.age); // user's age is 24
في المثل دا ال handler عمل modifies لل getting operation عشان ت return a custom value
طب لو عاوز أ modifie ال Deleting operation ؟
const handler = {
deleteProperty(target, property) {
console.log(Deleting property: ${property});
},
};
هتحط دي جوا ال handler ف لو جيت
const userProxy = new Proxy(user, handler);
delete userProxy.name; // Deleting property: name
هتلاقي دا ال output ولو جيت ت
console.log(userProxy) // { name : "zezo", age: 24,};
متمسحتش !
عشان إحنا ببساطة بدلنا الdelete operator’s default behavior بcustom behavior
اي اللي ييجي يلعب دور مهم هنا ؟ بقي Reflect
اي ال reflect دي؟
Reflect is a global object with a collection of all the internal methods of an object. Its methods can be used as normal operations anywhere, but it’s meant to be used inside a proxy.
بص هنستفيد من Reflect ازاي ف مثالنا
const handler = {
deleteProperty(target, property) {
console.log(Deleting property: ${property});
return Reflect.deleteProperty(target, property);
},
};
const userProxy = new Proxy(user, handler);
delete userProxy.name; // Deleting property: name
في حاجة مهمة هنا لازم أنوه ليها ؟
في بعض ال built in objects زي Math, Date, and JSON وغيرهم مقدرش أ delete منهم عشان ببساطة هما “non-configurable” object properties
يعني مينفعش أعملهم reassign or delete
❤5👍1
إزاي تحسن ال preformance بتاع الwebsite بتاعك وتقلل من وقت تحميله لزاوره ، وكمان تقلل ال load ع السيرفر بتاعك ؟
تعال أقولك ع تريكاية
تسمع عن ال http Caching أو ال
Http cache control
يعني إيه بقي ؟
بص هو عبارة عن إنك بتحفظ نسخة من الملفات ال static (الصور ، ملفات css ، ملفات js ) في ال Caching memory بتاعة المتصفح ،
طب دي إيه الفايدة منها ، وبتحصل إزاي أصلا ؟
في أول زيارة لليوز للموقع الbrowser بيحمل كل الfiles اللازمة من السيرفر ، وهو بيحملها بيحفظ نسخة منها في الcache عنده ، ف بالتالي أي زيارة مستقبلية ، الbrowser بيعمل check بسيط كدا الأول ، بيشوف الملفات اللي عنده في الcache صلاحيتها valid ولا ،
يعني إي صلاحيتها valid ، الصلاحية دي إنت اللي بتحطها ك developer في إعدادات ال Caching في فايل ف السيرفر بتاعك زي م هتشوف دلوقتي إزاي ، نرجع لل browser بعد م عمل الcheck ولقاه valid ، بيستخدمها بدل م يروح يحملها تاني من السيرفر !
دا بيقلل من ال requests اللي رايحة للسيرفر ويخلي موقعك كزيارة يحمل بشكل أسرع ، طب الملفات دي بتتخزن فين زي م قلت فوق كل متصفح فيه مساحة معينة مخصصة للملفات دي اسمها ذاكرة التخزين المؤقت أو ال Caching ..
طب لما هو حلو كدا وبسمسم ليه مش كل المواقع بتعمله ، هقولك لإنه ليه عيوب
لو الملفات اللي عندك ف ال cache دي اتغيرت عن اللي ف السيرفر أو حصل تعديلات ف الموقع بتاعك ، المستخدم هيشوف نسخة قديمة من الموقع بناءًا ع الملفات اللي متخزنه عنده في الcache لحد م صلاحية الملفات دي او الوقت اللي انت مديهولها كصلاحية يخلص ، العيب التاني انك بتستهلك resources من مساحة ومتصفح اللي بيزور موقعك
طب ازاي بقي أعمل الprocess دي كلها ، تعال أقولك ، لو انت الموقع بتاعك ع سيرفر apache ف الصورة رقم 1 هي اللي انت هتعمله
هتروح ع ال root بتاع الwebsite بتاعك وتكتب في ملف ال
.htaccess
اللي موجود ف الصورة رقم 1
طب أنا محتاج أفهم دا عبارة عن إيه بص هشرحلك كام حاجة وإنت هتفهم من خلالها عندك مثلا ال
max-age
بتحدد المدة الزمنية (بالثواني) اللي المتصفح يحتفظ خلالها بالملف في ال cache بتاعه
no-cache
بيجبر المتصفح على التحقق من صحة الملف مع السيرفر قبل استخدام النسخة المخزنة.
no-store:
بيمنع المتصفح من تخزين الملف في ذاكرة التخزين المؤقت
ExpiresByType
بتحدد مدة التخزين المؤقت لكل نوع من الملفات ، على سبيل المثال:
الصور (jpg, jpeg, gif, png): تخزين لمدة سنة (access plus 1 year)
طب لو السيرفر بتاعك Nginx
هتفتح ال path دا ع سيرفرك
/etc/nginx/nginx.conf
وهتحط فيه اللي ف صورة رقم 2
هنا نيجي بقي للخطوة بتاعة إزاي أتاكد أن الcaching شغال في الموقع بتاعي
هتفتح الموقع بتاعك بعدين تفتح ال developer tools =>
(Ctrl+Shift+I)
هتخش ع ال network tab حمل الصفحة بتاعة موقعك
بعد م يظهر كل الfiles اللي اتعملها load حدد أي static file زي أي صورة ،
وبص ع جزء ال headers
هتلاقي تفاصيل الcaching ف الجزء الخاص بـ Response Headers
هتشوف Cache-Control header مع القيم اللي حددتها في ملف .htaccess
تعال أقولك ع تريكاية
تسمع عن ال http Caching أو ال
Http cache control
يعني إيه بقي ؟
بص هو عبارة عن إنك بتحفظ نسخة من الملفات ال static (الصور ، ملفات css ، ملفات js ) في ال Caching memory بتاعة المتصفح ،
طب دي إيه الفايدة منها ، وبتحصل إزاي أصلا ؟
في أول زيارة لليوز للموقع الbrowser بيحمل كل الfiles اللازمة من السيرفر ، وهو بيحملها بيحفظ نسخة منها في الcache عنده ، ف بالتالي أي زيارة مستقبلية ، الbrowser بيعمل check بسيط كدا الأول ، بيشوف الملفات اللي عنده في الcache صلاحيتها valid ولا ،
يعني إي صلاحيتها valid ، الصلاحية دي إنت اللي بتحطها ك developer في إعدادات ال Caching في فايل ف السيرفر بتاعك زي م هتشوف دلوقتي إزاي ، نرجع لل browser بعد م عمل الcheck ولقاه valid ، بيستخدمها بدل م يروح يحملها تاني من السيرفر !
دا بيقلل من ال requests اللي رايحة للسيرفر ويخلي موقعك كزيارة يحمل بشكل أسرع ، طب الملفات دي بتتخزن فين زي م قلت فوق كل متصفح فيه مساحة معينة مخصصة للملفات دي اسمها ذاكرة التخزين المؤقت أو ال Caching ..
طب لما هو حلو كدا وبسمسم ليه مش كل المواقع بتعمله ، هقولك لإنه ليه عيوب
لو الملفات اللي عندك ف ال cache دي اتغيرت عن اللي ف السيرفر أو حصل تعديلات ف الموقع بتاعك ، المستخدم هيشوف نسخة قديمة من الموقع بناءًا ع الملفات اللي متخزنه عنده في الcache لحد م صلاحية الملفات دي او الوقت اللي انت مديهولها كصلاحية يخلص ، العيب التاني انك بتستهلك resources من مساحة ومتصفح اللي بيزور موقعك
طب ازاي بقي أعمل الprocess دي كلها ، تعال أقولك ، لو انت الموقع بتاعك ع سيرفر apache ف الصورة رقم 1 هي اللي انت هتعمله
هتروح ع ال root بتاع الwebsite بتاعك وتكتب في ملف ال
.htaccess
اللي موجود ف الصورة رقم 1
طب أنا محتاج أفهم دا عبارة عن إيه بص هشرحلك كام حاجة وإنت هتفهم من خلالها عندك مثلا ال
max-age
بتحدد المدة الزمنية (بالثواني) اللي المتصفح يحتفظ خلالها بالملف في ال cache بتاعه
no-cache
بيجبر المتصفح على التحقق من صحة الملف مع السيرفر قبل استخدام النسخة المخزنة.
no-store:
بيمنع المتصفح من تخزين الملف في ذاكرة التخزين المؤقت
ExpiresByType
بتحدد مدة التخزين المؤقت لكل نوع من الملفات ، على سبيل المثال:
الصور (jpg, jpeg, gif, png): تخزين لمدة سنة (access plus 1 year)
طب لو السيرفر بتاعك Nginx
هتفتح ال path دا ع سيرفرك
/etc/nginx/nginx.conf
وهتحط فيه اللي ف صورة رقم 2
هنا نيجي بقي للخطوة بتاعة إزاي أتاكد أن الcaching شغال في الموقع بتاعي
هتفتح الموقع بتاعك بعدين تفتح ال developer tools =>
(Ctrl+Shift+I)
هتخش ع ال network tab حمل الصفحة بتاعة موقعك
بعد م يظهر كل الfiles اللي اتعملها load حدد أي static file زي أي صورة ،
وبص ع جزء ال headers
هتلاقي تفاصيل الcaching ف الجزء الخاص بـ Response Headers
هتشوف Cache-Control header مع القيم اللي حددتها في ملف .htaccess
❤7
كنت تصدق إنك تقدر تكتب Logic جوا ال css ؟
تعال هقولك إزاي تعمل كل دول
Conditions (if/then), Loops (for, while), Logical Gates (===, &&, etc.) and Variables.
كأنها لغة برمجة زي ال js ، مع العلم إنها مش لغة برمجة !
نبدأ بال Variables
إسمها في ال css
Custom Properties
:root {
--color: orange;
}
span {
color: var(--color, blue);
}
بتعرف متغير ف ال css عن طريق ال double-dash وبعد كدا بت assign له قيمة ، الكلام دا لازم يحصل جوا css scope بمعني تاني جوا selector لإنك لو عرفت متغير برا ال selector إنت كدا بت break the CSS syntax
طب لو عاوز أعرف متغير في ال global scope بسيطة هتحطه جوا ال
:root selector
طب لو عاوز أعمل ِaccess للمتغيرات دي من ال js ؟
// set --s on :root
document.documentElement.style.setProperty('--s', e.target.value);
// set --s scoped to #myID
const el = document.querySelector('#myID');
el.style.setProperty('--s', e.target.value);
// read variables from an alement
const switch = getComputedStyle(el).getPropertyValue('--s');
نخش بقي علي ال Conditions
بص طريقة كتابتها بتختلف حسب المكان اللي هتسخدمها فيه بمعني إيه ؟
عشان تفهمني لازم تفرق بين حاحتين
إن ال ٍ selector له ال scope الخاص بال element بتاعه وإن الmedia queries ال scope بتاعها بيكون global
مش فاهم ؟ تعال نبص ع المثال دا
<div data-attr="true">This is true</div>
<div data-attr="false">This is false</div>
<div>This is undefined</div>
ودا ال style الخاص بيهم
[data-attr="true"] {
/* if */
}
[data-attr="false"] {
/* elseif */
}
:not([data-attr]) {
/* else */
}
فهمت ؟
بكل بساطة هنا بي
Apply styles conditionally based on element attributes or states. These styles are scoped to the elements that match the selector criteria..
:checked {
/* if */
border: 2px solid blue;
}
:not(:checked) {
/* else */
border: 2px solid gray;
}
دا تطبيق تاني لل Condition في ال media queries
/* Media query for screens wider than 600px */
@media (min-width: 600px) {
.container {
background-color: lightblue;
}
p {
font-size: 20px;
}
}
ف هنا هو بي applies styles only when the viewport width is 600 pixels or wider
تالت حاجة هي ال loops
بص في ال css ال Counters are form of loops
بس فيه هنا Restriction كبير جدا ، وهو إنه مقدرش أستخدم الcounters إلا جوا ال content property
main {
counter-reset: section;
}
section {
counter-increment: section;
}
section > h2::before {
content: "Headline " counter(section) ": ";
}
وهنا اللي بيتم 3 خطوات
1 - initializes a counter named section to 0 when the main element is rendered.
2 - Each time a section element is encountered, the section counter is incremented by 1.
3 - sets the content of the ::before pseudo-element to display the word "Headline" followed by the current value of the section counter and a colon.
طب لو عاوز أطبق فكرة الloop نفسه تطبق في layout متكرر ؟
هنا ييجي دور ال Grid's auto-fill property
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}
This fills the grid with as many elements as it can fit, while scaling them to fill the available space
طول م عندك مساحة هبيأكل منك :"
وطبعا مننساش فكرة ال looped selectors اللي بتستلم منك argument اللي ممن تحطه كمعادلة عشان توصل للelement اللي انت عاوزه ، كبرتوا الموضوع it's just a Css
section:nth-child(2n) {
/* selects every even element */
}
section:nth-child(4n + 2) {
/* selects every fourth, starting from the 2nd */
}
نيجي بقي لأخر حاجة وهي ال Logic Gates
عشان بس نكون ع نور CSS itself does not support logical operations directly
أومال اي اللي بيحصل ؟
احنا بس نقدر نحقق دا عن طريق ان بنعمل combination بين ال CSS variables and calc method
طيب بنستخدم logical operations دي ف إيه ؟ لا دي بتعمل سحر ف الحقيقة ! وبتستخدمها في dynamic theming, conditional styling based on user preferences وممكن كمان تستخدمها في 3D modeling and animating objects
بص حط دي في جوجل وادعيلي
Logical Operations with CSS Variables
تعال هقولك إزاي تعمل كل دول
Conditions (if/then), Loops (for, while), Logical Gates (===, &&, etc.) and Variables.
كأنها لغة برمجة زي ال js ، مع العلم إنها مش لغة برمجة !
نبدأ بال Variables
إسمها في ال css
Custom Properties
:root {
--color: orange;
}
span {
color: var(--color, blue);
}
بتعرف متغير ف ال css عن طريق ال double-dash وبعد كدا بت assign له قيمة ، الكلام دا لازم يحصل جوا css scope بمعني تاني جوا selector لإنك لو عرفت متغير برا ال selector إنت كدا بت break the CSS syntax
طب لو عاوز أعرف متغير في ال global scope بسيطة هتحطه جوا ال
:root selector
طب لو عاوز أعمل ِaccess للمتغيرات دي من ال js ؟
// set --s on :root
document.documentElement.style.setProperty('--s', e.target.value);
// set --s scoped to #myID
const el = document.querySelector('#myID');
el.style.setProperty('--s', e.target.value);
// read variables from an alement
const switch = getComputedStyle(el).getPropertyValue('--s');
نخش بقي علي ال Conditions
بص طريقة كتابتها بتختلف حسب المكان اللي هتسخدمها فيه بمعني إيه ؟
عشان تفهمني لازم تفرق بين حاحتين
إن ال ٍ selector له ال scope الخاص بال element بتاعه وإن الmedia queries ال scope بتاعها بيكون global
مش فاهم ؟ تعال نبص ع المثال دا
<div data-attr="true">This is true</div>
<div data-attr="false">This is false</div>
<div>This is undefined</div>
ودا ال style الخاص بيهم
[data-attr="true"] {
/* if */
}
[data-attr="false"] {
/* elseif */
}
:not([data-attr]) {
/* else */
}
فهمت ؟
بكل بساطة هنا بي
Apply styles conditionally based on element attributes or states. These styles are scoped to the elements that match the selector criteria..
:checked {
/* if */
border: 2px solid blue;
}
:not(:checked) {
/* else */
border: 2px solid gray;
}
دا تطبيق تاني لل Condition في ال media queries
/* Media query for screens wider than 600px */
@media (min-width: 600px) {
.container {
background-color: lightblue;
}
p {
font-size: 20px;
}
}
ف هنا هو بي applies styles only when the viewport width is 600 pixels or wider
تالت حاجة هي ال loops
بص في ال css ال Counters are form of loops
بس فيه هنا Restriction كبير جدا ، وهو إنه مقدرش أستخدم الcounters إلا جوا ال content property
main {
counter-reset: section;
}
section {
counter-increment: section;
}
section > h2::before {
content: "Headline " counter(section) ": ";
}
وهنا اللي بيتم 3 خطوات
1 - initializes a counter named section to 0 when the main element is rendered.
2 - Each time a section element is encountered, the section counter is incremented by 1.
3 - sets the content of the ::before pseudo-element to display the word "Headline" followed by the current value of the section counter and a colon.
طب لو عاوز أطبق فكرة الloop نفسه تطبق في layout متكرر ؟
هنا ييجي دور ال Grid's auto-fill property
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}
This fills the grid with as many elements as it can fit, while scaling them to fill the available space
طول م عندك مساحة هبيأكل منك :"
وطبعا مننساش فكرة ال looped selectors اللي بتستلم منك argument اللي ممن تحطه كمعادلة عشان توصل للelement اللي انت عاوزه ، كبرتوا الموضوع it's just a Css
section:nth-child(2n) {
/* selects every even element */
}
section:nth-child(4n + 2) {
/* selects every fourth, starting from the 2nd */
}
نيجي بقي لأخر حاجة وهي ال Logic Gates
عشان بس نكون ع نور CSS itself does not support logical operations directly
أومال اي اللي بيحصل ؟
احنا بس نقدر نحقق دا عن طريق ان بنعمل combination بين ال CSS variables and calc method
طيب بنستخدم logical operations دي ف إيه ؟ لا دي بتعمل سحر ف الحقيقة ! وبتستخدمها في dynamic theming, conditional styling based on user preferences وممكن كمان تستخدمها في 3D modeling and animating objects
بص حط دي في جوجل وادعيلي
Logical Operations with CSS Variables
❤2
السلام عليكم يا جماعة! 👋
أكيد كلكم سمعتوا عن الوحدات دي VH, DVH, SVH, وLVH
في ال CSS بس إيه الفرق بينهم؟ تعالوا نفك الشفرة مع بعض! 🕵️♂️
أغلبنا كنا بنستخدم وحدة الـ vh
(viewport height)
لكن بدأت المشكلة في شاشات الموبايل وقت الScrolling لإن ال vh مش بتأخد في الإعتبار ظهور شريط العنوان (address bar) أو شريط الأدوات (toolbar)
علشان كده، ظهرت وحدات جديدة وهي:
SVH-LVH-DVH
تعالوا نشرح كل وحدة منهم بالتفصيل مع مثال عملي.
VH
بتقيس نسبة مئوية من ارتفاع الـ viewport،
يعني لو عندك عنصر بارتفاع 50VH، هيكون ارتفاعه نص ارتفاع الـ viewport ، بس المشكلة هنا إنها مش بتاخد في الإعتبار وجود شريط العنوان أو ظهور الكيبورد على الموبايل، فبالتالي ممكن العنصر يتغطى جزئيًا
SVH (Small Viewport Height)
بتمثل 100% من ارتفاع الـ viewport الفعلي، بغض النظر عن وجود شريط العنوان أو الكيبورد ، يعني أي عنصر بارتفاع 100SVH هيغطي كامل ارتفاع الـ viewport حتى لو ظهر شريط العنوان أو الكيبورد من الأخر هحط ف إعتباري ظهورهم وبرضه هظهرلك كل ال content ، ده بيضمن تغطية كاملة و ثابتة للـ viewport.
LVH (Large Viewport Height)
بتمثل أكبر ارتفاع ممكن للـ viewport لما شريط القوائم أو أي واجهة مستخدم تانية تكون مخفية. يعني أي عنصر بارتفاع 100LVH هيملأ كامل ارتفاع الـ viewport في أكبر حجم ممكن ، من الأخر مش هحط ف إعتباري ظهور شريط العنوان أو الكيبورد ، حتي لو هيخفوا جزء من الcontent بتاعي
DVH (Dynamic Viewport Height)
بتتغير ديناميكيًا مع تغير ارتفاع الـ viewport ،مثلاً عند الscrolling على الموبايل، شريط العنوان بيختفي وبيزيد ارتفاع المحتوى، الوحدة دي بتتغير تبعًا لده ، ظهر الtitle bar هحط ف اعتباري ظهوره ، مظهرش ؟ ه scale للحجم الكلي
تقدر تعتبرها مكس بتتغير حسب ال ٍscrolling
مقارنة سريعة:
VH
مثالي للاستخدامات العامة لما تكون مش مهتم بالتغيرات اللي بتحصل في الارتفاع.
DVH
ممتاز للموبايلات والتطبيقات اللي بتتفاعل مع تغييرات الشاشة زي ظهور الكيبورد ، مش مدعوم في كل المتصفحات لسه، فممكن تواجه مشاكل توافق
SVH
بيضمنلك ظهور كامل للـ viewport بشكل ثابت، بغض النظر عن ظهور أي عناصر تانية زي شريط القوائم أو الكيبورد ، جميل في ضمان إن التصميم بتاعك هيبان حتى في أصغر الشاشات
LVH
بيديك أكبر ارتفاع ممكن للـ viewport عند إخفاء ال titlebar أو غيره
مش مناسب لو في toolbar دايمًا ظاهر على الشاشة ، مفيد للعناصر اللي عايزها تتمدد وتملأ أكبر مساحة ممكنة
في النهاية، لازم تختار الوحدة المناسبة لتصميمك واحتياجاتك، مع الإعتبار مزايا وعيوب كل وحدة.
أكيد كلكم سمعتوا عن الوحدات دي VH, DVH, SVH, وLVH
في ال CSS بس إيه الفرق بينهم؟ تعالوا نفك الشفرة مع بعض! 🕵️♂️
أغلبنا كنا بنستخدم وحدة الـ vh
(viewport height)
لكن بدأت المشكلة في شاشات الموبايل وقت الScrolling لإن ال vh مش بتأخد في الإعتبار ظهور شريط العنوان (address bar) أو شريط الأدوات (toolbar)
علشان كده، ظهرت وحدات جديدة وهي:
SVH-LVH-DVH
تعالوا نشرح كل وحدة منهم بالتفصيل مع مثال عملي.
VH
بتقيس نسبة مئوية من ارتفاع الـ viewport،
يعني لو عندك عنصر بارتفاع 50VH، هيكون ارتفاعه نص ارتفاع الـ viewport ، بس المشكلة هنا إنها مش بتاخد في الإعتبار وجود شريط العنوان أو ظهور الكيبورد على الموبايل، فبالتالي ممكن العنصر يتغطى جزئيًا
SVH (Small Viewport Height)
بتمثل 100% من ارتفاع الـ viewport الفعلي، بغض النظر عن وجود شريط العنوان أو الكيبورد ، يعني أي عنصر بارتفاع 100SVH هيغطي كامل ارتفاع الـ viewport حتى لو ظهر شريط العنوان أو الكيبورد من الأخر هحط ف إعتباري ظهورهم وبرضه هظهرلك كل ال content ، ده بيضمن تغطية كاملة و ثابتة للـ viewport.
LVH (Large Viewport Height)
بتمثل أكبر ارتفاع ممكن للـ viewport لما شريط القوائم أو أي واجهة مستخدم تانية تكون مخفية. يعني أي عنصر بارتفاع 100LVH هيملأ كامل ارتفاع الـ viewport في أكبر حجم ممكن ، من الأخر مش هحط ف إعتباري ظهور شريط العنوان أو الكيبورد ، حتي لو هيخفوا جزء من الcontent بتاعي
DVH (Dynamic Viewport Height)
بتتغير ديناميكيًا مع تغير ارتفاع الـ viewport ،مثلاً عند الscrolling على الموبايل، شريط العنوان بيختفي وبيزيد ارتفاع المحتوى، الوحدة دي بتتغير تبعًا لده ، ظهر الtitle bar هحط ف اعتباري ظهوره ، مظهرش ؟ ه scale للحجم الكلي
تقدر تعتبرها مكس بتتغير حسب ال ٍscrolling
مقارنة سريعة:
VH
مثالي للاستخدامات العامة لما تكون مش مهتم بالتغيرات اللي بتحصل في الارتفاع.
DVH
ممتاز للموبايلات والتطبيقات اللي بتتفاعل مع تغييرات الشاشة زي ظهور الكيبورد ، مش مدعوم في كل المتصفحات لسه، فممكن تواجه مشاكل توافق
SVH
بيضمنلك ظهور كامل للـ viewport بشكل ثابت، بغض النظر عن ظهور أي عناصر تانية زي شريط القوائم أو الكيبورد ، جميل في ضمان إن التصميم بتاعك هيبان حتى في أصغر الشاشات
LVH
بيديك أكبر ارتفاع ممكن للـ viewport عند إخفاء ال titlebar أو غيره
مش مناسب لو في toolbar دايمًا ظاهر على الشاشة ، مفيد للعناصر اللي عايزها تتمدد وتملأ أكبر مساحة ممكنة
في النهاية، لازم تختار الوحدة المناسبة لتصميمك واحتياجاتك، مع الإعتبار مزايا وعيوب كل وحدة.
❤4
إمتى ظهر الـ Shadow DOM، وظهر ليه، وأهميته إيه؟
مع تقدم تطوير الويب، بقت التطبيقات بتعتمد على libraries و framewoorks زي React وVue.js. ومع تزايد التعقيد في الـUI components، بقت مشكلة إدارة الـstyles والـscripts جوه الـindividual components بتزيد.
المشكلة
قبل ما يظهر الـShadow DOM، كان عندنا مشكلة كبيرة في الـCSS bleeding. لو عندك component معقد، الـstyles بتاعته كانت ممكن تتداخل مع الـstyles بتاعة مكونات تانية في الصفحة. ده بيخلي الحفاظ على الـstyles بشكل منظم ومستقل لكل component عملية صعبة.
ظهور الـShadow DOM
الـShadow DOM ظهر كجزء من الـWeb Components standard علشان يحل المشكلة دي. الـShadow DOM بيوفر بيئة معزولة لأي component، بحيث الـstyles والـscripts جوه الـcomponent ده ما يتأثروش بأي حاجة تانية في الصفحة.
إزاي بيشتغل؟
الـShadow DOM بيشتغل عن طريق إنشاء شجرة DOM مستقلة لكل component. لما بنستخدم الـShadow DOM، بنقدر نعمل encapsulation للـHTML، CSS، والـJavaScript بتاع الـcomponent ده.
مثال بسيط:
class MyComplexElement extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML =
const button = shadow.querySelector('#myButton');
button.addEventListener('click', () => {
alert('Button inside Shadow DOM clicked!');
});
}
}
customElements.define('my-complex-element', MyComplexElement);
المميزات
Encapsulation
الـstyles جوه الـShadow DOM ما بيأثروش على بقية الصفحة.
Reusability
الـWeb Components بقت أسهل في إعادة الاستخدام.
Maintainability
بقت عملية صيانة الكود أسهل لإن كل component بيبقى مستقل بذاته.
قبل وبعد الـShadow DOM
الـstyles بتتداخل مع بعضها.
صعوبة في إعادة استخدام الكود بدون مشاكل في الـstyles
بعد الـShadow DOM
كل component عنده بيئة معزولة.
سهولة في إعادة استخدام الـWeb Components بدون مشاكل في الـstyles.
الخلاصة
الـShadow DOM قدم حل فعال لمشكلة الـCSS bleeding وخلى إدارة الـWeb Components أسهل وأكتر تنظيماً. مع التقدم في الـWeb standards، بقى الـShadow DOM أداة مهمة خاصة ل (SPAs) والـProgressive Web Apps (PWAs) لأنه بيساعد في تنظيم الكود وتحسين الأداء.
التوافق مع المتصفحات
دعم الـShadow DOM زاد بشكل كبير في السنوات الأخيرة، لكن بعض المتصفحات القديمة قد تحتاج لـpolyfills.
مقارنة بين الـShadow DOM وحلول تانية زي CSS Modules أو CSS-in-JS:
Shadow DOM
بيقدم encapsulation للـstyles والـscripts بشكل مستقل.
CSS Modules
بتوفر scope للـstyles بدون تغييرات في الـDOM.
CSS-in-JS
بتمكنك من كتابة الـstyles جوه JavaScript، مما يديك تحكم أكتر.
مثال عملي أكثر تعقيداً بيوضح كيفية التعامل مع الـevents والـslots في الـShadow DOM
class MyComplexElement extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML =
const button = shadow.querySelector('#myButton');
button.addEventListener('click', () => {
alert('Button inside Shadow DOM clicked!');
});
}
}
customElements.define('my-complex-element', MyComplexElement);
التطورات المستقبلية المتوقعة للـShadow DOM بتتضمن تحسين الـintegration مع تقنيات ويب جديدة، زي دعم أكتر لـAR/VR والـWebAssembly.
ودا مثال إزاي تستخدم ال shadow dom مع react
import React, { useRef, useEffect } from 'react';
function ShadowComponent() {
const hostRef = useRef(null);
useEffect(() => {
const shadow = hostRef.current.attachShadow({ mode: 'open' });
shadow.innerHTML =
}, []);
return <div ref={hostRef}></div>;
}
مع تقدم تطوير الويب، بقت التطبيقات بتعتمد على libraries و framewoorks زي React وVue.js. ومع تزايد التعقيد في الـUI components، بقت مشكلة إدارة الـstyles والـscripts جوه الـindividual components بتزيد.
المشكلة
قبل ما يظهر الـShadow DOM، كان عندنا مشكلة كبيرة في الـCSS bleeding. لو عندك component معقد، الـstyles بتاعته كانت ممكن تتداخل مع الـstyles بتاعة مكونات تانية في الصفحة. ده بيخلي الحفاظ على الـstyles بشكل منظم ومستقل لكل component عملية صعبة.
ظهور الـShadow DOM
الـShadow DOM ظهر كجزء من الـWeb Components standard علشان يحل المشكلة دي. الـShadow DOM بيوفر بيئة معزولة لأي component، بحيث الـstyles والـscripts جوه الـcomponent ده ما يتأثروش بأي حاجة تانية في الصفحة.
إزاي بيشتغل؟
الـShadow DOM بيشتغل عن طريق إنشاء شجرة DOM مستقلة لكل component. لما بنستخدم الـShadow DOM، بنقدر نعمل encapsulation للـHTML، CSS، والـJavaScript بتاع الـcomponent ده.
مثال بسيط:
class MyComplexElement extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML =
<style>
p {
color: green;
}
</style>
<slot name="my-text"></slot>
<button id="myButton">Click me</button>
;const button = shadow.querySelector('#myButton');
button.addEventListener('click', () => {
alert('Button inside Shadow DOM clicked!');
});
}
}
customElements.define('my-complex-element', MyComplexElement);
المميزات
Encapsulation
الـstyles جوه الـShadow DOM ما بيأثروش على بقية الصفحة.
Reusability
الـWeb Components بقت أسهل في إعادة الاستخدام.
Maintainability
بقت عملية صيانة الكود أسهل لإن كل component بيبقى مستقل بذاته.
قبل وبعد الـShadow DOM
الـstyles بتتداخل مع بعضها.
صعوبة في إعادة استخدام الكود بدون مشاكل في الـstyles
بعد الـShadow DOM
كل component عنده بيئة معزولة.
سهولة في إعادة استخدام الـWeb Components بدون مشاكل في الـstyles.
الخلاصة
الـShadow DOM قدم حل فعال لمشكلة الـCSS bleeding وخلى إدارة الـWeb Components أسهل وأكتر تنظيماً. مع التقدم في الـWeb standards، بقى الـShadow DOM أداة مهمة خاصة ل (SPAs) والـProgressive Web Apps (PWAs) لأنه بيساعد في تنظيم الكود وتحسين الأداء.
التوافق مع المتصفحات
دعم الـShadow DOM زاد بشكل كبير في السنوات الأخيرة، لكن بعض المتصفحات القديمة قد تحتاج لـpolyfills.
مقارنة بين الـShadow DOM وحلول تانية زي CSS Modules أو CSS-in-JS:
Shadow DOM
بيقدم encapsulation للـstyles والـscripts بشكل مستقل.
CSS Modules
بتوفر scope للـstyles بدون تغييرات في الـDOM.
CSS-in-JS
بتمكنك من كتابة الـstyles جوه JavaScript، مما يديك تحكم أكتر.
مثال عملي أكثر تعقيداً بيوضح كيفية التعامل مع الـevents والـslots في الـShadow DOM
class MyComplexElement extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML =
<style>
p {
color: green;
}
</style>
<slot name="my-text"></slot>
<button id="myButton">Click me</button>
;const button = shadow.querySelector('#myButton');
button.addEventListener('click', () => {
alert('Button inside Shadow DOM clicked!');
});
}
}
customElements.define('my-complex-element', MyComplexElement);
التطورات المستقبلية المتوقعة للـShadow DOM بتتضمن تحسين الـintegration مع تقنيات ويب جديدة، زي دعم أكتر لـAR/VR والـWebAssembly.
ودا مثال إزاي تستخدم ال shadow dom مع react
import React, { useRef, useEffect } from 'react';
function ShadowComponent() {
const hostRef = useRef(null);
useEffect(() => {
const shadow = hostRef.current.attachShadow({ mode: 'open' });
shadow.innerHTML =
<style>
p { color: blue; }
</style>
<p>This is inside Shadow DOM</p>
;}, []);
return <div ref={hostRef}></div>;
}
❤3👍1
تعال أقولك شوية features جديدة في ال js عشان تبقي جامد جمودة
نبدأ بال Optional Chaining (?.)
الـ Optional Chaining إتضافت في ال ECMAScript 2020. بتسمحلك توصل لقيمة جوا objects متشعبة من غير ما تعمل if conditions كتير. يعني بدل ما تتأكد من وجود كل جزء في Chain تقدر تستخدم الـ Optional Chaining بشكل بسيط:
let streetName = person?.address?.street?.name;
لو الشخص مش موجود أو العنوان مش موجود، الكود مش هيعمل خطأ وهيرجع undefined.
———-
Nullish Coalescing (??)
الـ Nullish Coalescing Operator اتقدمت برضه في ECMAScript 2020. دي بتستخدم علشان ترجع أول قيمة لو مش null أو undefined، وتاني قيمة لو الأولانية null أو undefined. يعني مثلاً:
let name = person?.name ?? 'Unknown';
لو الشخص مش عنده اسم، هيرجع 'Unknown' بدل ما يرجع undefined.
———
BigInt
ده نوع بيانات جديد في JavaScript اسمه BigInt. بيستخدم لتمثيل الأعداد الكبيرة جداً اللي ماينفعش تتعامل معاها بـ Number العادي. يعني ممكن تكتب:
const bigNumber = 12345678901234567890n;
الأعداد دي ممكن تكون أكبر بكتير من أكبر رقم يقدر يتعامل معاه الـ Number العادي وبالمناسبة هي primitive data type
————
globalThis
ده global object جديد في JavaScript اسمه globalThis. بيوفر طريقة للوصول للـ global object بطريقة متوافقة مع كل بيئات JavaScript الحديثة زي المتصفحات و Node.js. يعني بدل ما تكتب window أو global، تقدر تكتب:
console.log(globalThis === window); // true في المتصفح
—————
matchAll()
دي method جديدة على الـ String prototype، اسمها matchAll(). بتديك Iterator بيجيب كل المتطابقات مع Regular Expression في نص، وبتشمل الـ capturing groups. مثال:
const regex = /(\w)(\d)/g;
const str = 'a1b2c3';
for (const match of str.matchAll(regex)) {
console.log(match);
}
الكود ده هيطبع كل المتطابقات زي ['a1', 'b2', 'c3'].
——-
Promise.allSettled()
دي method جديدة في API بتاع Promise، اسمها allSettled(). بترجع promise بيتحل لما كل الـ promises في المصفوفة تتحل سواء كانت تحلت أو ترفضت. مثال:
const promises = [Promise.resolve('a'), Promise.reject('b'), Promise.resolve('c')];
Promise.allSettled(promises).then((results) => console.log(results));
الكود ده هيطبع الحالة بتاعة كل promise سواء كان تحل أو ترفض.
—————
String.prototype.at()
دي method جديدة على الـ String prototype، اسمها at(). بترجع الحرف عند الـ index المحدد، وبتسمح باستخدام مؤشرات سالبة للوصول للحروف من آخر النص. مثال:
const str = 'hello';
console.log(str.at(0)); // 'h'
console.log(str.at(-1)); // 'o'
—————————
Error Cause
الـ Error Cause هي خاصية جديدة في JavaScript بتسمحلك تضيف معلومات عن السبب الأصلي للخطأ لما ترمي (throw) خطأ جديد. الفكرة هي إنك لما يكون عندك خطأ، أحياناً بيكون السبب الأصلي للخطأ خطأ تاني، والخاصية دي بتساعدك تحتفظ بالمعلومات دي ، مثال بسيط
بدون Error Cause
لو ما استخدمتش Error Cause، هيبقى عندك كود زي ده:
try {
// تخيل إن دي دالة بتقرأ ملف
readFile('nonexistentFile.txt');
} catch (originalError) {
throw new Error('Failed to read file');
}
في الحالة دي، الخطأ الجديد "Failed to read file" مش هيحتوي على تفاصيل الخطأ الأصلي.
باستخدام Error Cause
لو استخدمت Error Cause، هيبقى عندك كود زي ده:
try {
// تخيل إن دي دالة بتقرأ ملف
readFile('nonexistentFile.txt');
} catch (originalError) {
throw new Error('Failed to read file', { cause: originalError });
}
إزاي تستخدمها
لما ترمي خطأ جديد، ممكن تضيف الخاصية cause وتحدد الخطأ الأصلي. بعد كده، لما تعمل كاتش (catch) للخطأ، تقدر تطبع أو تستخدم السبب الأصلي للخطأ.
try {
try {
// دي دالة بتعمل حاجة ممكن تفشل
doSomethingRisky();
} catch (originalError) {
throw new Error('Something went wrong', { cause: originalError });
}
} catch (error) {
console.log(error.message); // "Something went wrong"
console.log(error.cause); // يطبع الخطأ الأصلي
}
الفوائد
توفير معلومات إضافية: يساعدك في تتبع أسباب الأخطاء بسهولة أكبر.
تحليل أفضل للأخطاء: لما يكون عندك سلسلة من الأخطاء، تقدر تفهم السياق الكامل للخطأ بسهولة.
تحسين تجربة التطوير: بيخلي عملية الديباجينج (debugging) أسهل وأسرع.
باختصار، الـ Error Cause بتخليك تقدر تضيف سبب إضافي للخطأ بحيث تقدر تتبع الأخطاء بشكل أفضل وتفهمها بشكل أعمق، خصوصاً لما يكون عندك أكتر من مستوى من الخطأ في الكود بتاعك.
نبدأ بال Optional Chaining (?.)
الـ Optional Chaining إتضافت في ال ECMAScript 2020. بتسمحلك توصل لقيمة جوا objects متشعبة من غير ما تعمل if conditions كتير. يعني بدل ما تتأكد من وجود كل جزء في Chain تقدر تستخدم الـ Optional Chaining بشكل بسيط:
let streetName = person?.address?.street?.name;
لو الشخص مش موجود أو العنوان مش موجود، الكود مش هيعمل خطأ وهيرجع undefined.
———-
Nullish Coalescing (??)
الـ Nullish Coalescing Operator اتقدمت برضه في ECMAScript 2020. دي بتستخدم علشان ترجع أول قيمة لو مش null أو undefined، وتاني قيمة لو الأولانية null أو undefined. يعني مثلاً:
let name = person?.name ?? 'Unknown';
لو الشخص مش عنده اسم، هيرجع 'Unknown' بدل ما يرجع undefined.
———
BigInt
ده نوع بيانات جديد في JavaScript اسمه BigInt. بيستخدم لتمثيل الأعداد الكبيرة جداً اللي ماينفعش تتعامل معاها بـ Number العادي. يعني ممكن تكتب:
const bigNumber = 12345678901234567890n;
الأعداد دي ممكن تكون أكبر بكتير من أكبر رقم يقدر يتعامل معاه الـ Number العادي وبالمناسبة هي primitive data type
————
globalThis
ده global object جديد في JavaScript اسمه globalThis. بيوفر طريقة للوصول للـ global object بطريقة متوافقة مع كل بيئات JavaScript الحديثة زي المتصفحات و Node.js. يعني بدل ما تكتب window أو global، تقدر تكتب:
console.log(globalThis === window); // true في المتصفح
—————
matchAll()
دي method جديدة على الـ String prototype، اسمها matchAll(). بتديك Iterator بيجيب كل المتطابقات مع Regular Expression في نص، وبتشمل الـ capturing groups. مثال:
const regex = /(\w)(\d)/g;
const str = 'a1b2c3';
for (const match of str.matchAll(regex)) {
console.log(match);
}
الكود ده هيطبع كل المتطابقات زي ['a1', 'b2', 'c3'].
——-
Promise.allSettled()
دي method جديدة في API بتاع Promise، اسمها allSettled(). بترجع promise بيتحل لما كل الـ promises في المصفوفة تتحل سواء كانت تحلت أو ترفضت. مثال:
const promises = [Promise.resolve('a'), Promise.reject('b'), Promise.resolve('c')];
Promise.allSettled(promises).then((results) => console.log(results));
الكود ده هيطبع الحالة بتاعة كل promise سواء كان تحل أو ترفض.
—————
String.prototype.at()
دي method جديدة على الـ String prototype، اسمها at(). بترجع الحرف عند الـ index المحدد، وبتسمح باستخدام مؤشرات سالبة للوصول للحروف من آخر النص. مثال:
const str = 'hello';
console.log(str.at(0)); // 'h'
console.log(str.at(-1)); // 'o'
—————————
Error Cause
الـ Error Cause هي خاصية جديدة في JavaScript بتسمحلك تضيف معلومات عن السبب الأصلي للخطأ لما ترمي (throw) خطأ جديد. الفكرة هي إنك لما يكون عندك خطأ، أحياناً بيكون السبب الأصلي للخطأ خطأ تاني، والخاصية دي بتساعدك تحتفظ بالمعلومات دي ، مثال بسيط
بدون Error Cause
لو ما استخدمتش Error Cause، هيبقى عندك كود زي ده:
try {
// تخيل إن دي دالة بتقرأ ملف
readFile('nonexistentFile.txt');
} catch (originalError) {
throw new Error('Failed to read file');
}
في الحالة دي، الخطأ الجديد "Failed to read file" مش هيحتوي على تفاصيل الخطأ الأصلي.
باستخدام Error Cause
لو استخدمت Error Cause، هيبقى عندك كود زي ده:
try {
// تخيل إن دي دالة بتقرأ ملف
readFile('nonexistentFile.txt');
} catch (originalError) {
throw new Error('Failed to read file', { cause: originalError });
}
إزاي تستخدمها
لما ترمي خطأ جديد، ممكن تضيف الخاصية cause وتحدد الخطأ الأصلي. بعد كده، لما تعمل كاتش (catch) للخطأ، تقدر تطبع أو تستخدم السبب الأصلي للخطأ.
try {
try {
// دي دالة بتعمل حاجة ممكن تفشل
doSomethingRisky();
} catch (originalError) {
throw new Error('Something went wrong', { cause: originalError });
}
} catch (error) {
console.log(error.message); // "Something went wrong"
console.log(error.cause); // يطبع الخطأ الأصلي
}
الفوائد
توفير معلومات إضافية: يساعدك في تتبع أسباب الأخطاء بسهولة أكبر.
تحليل أفضل للأخطاء: لما يكون عندك سلسلة من الأخطاء، تقدر تفهم السياق الكامل للخطأ بسهولة.
تحسين تجربة التطوير: بيخلي عملية الديباجينج (debugging) أسهل وأسرع.
باختصار، الـ Error Cause بتخليك تقدر تضيف سبب إضافي للخطأ بحيث تقدر تتبع الأخطاء بشكل أفضل وتفهمها بشكل أعمق، خصوصاً لما يكون عندك أكتر من مستوى من الخطأ في الكود بتاعك.
❤1🥰1
عاوز prebuild components وتكون customizable و الFocus فيها كله إنها تساعدك تبني dashboard ؟
وال style بتاعها إتبني علي ال tailwind عرفت ليه fully customizable ؟
خد و إدعيلي ..
https://raw.tremor.so/docs/getting-started/installation
وال style بتاعها إتبني علي ال tailwind عرفت ليه fully customizable ؟
خد و إدعيلي ..
https://raw.tremor.so/docs/getting-started/installation
Tremor – Copy-and-Paste Tailwind CSS UI Components for Charts and Dashboards
Open-source, accessible React UI components styled with Tailwind CSS to build charts and dashboards.
❤2🥰2
زمان قبل 2010، كان مصممي الويب يقدروا يعملوا مواقع تناسب الديسكتوب بس. لحد ما جه Ethan Marcotte وقدم لنا مفهوم الـResponsive Web Design (RWD)، واللي عرفه موقع MDN بأنه طريقة لتصميم الويب عشان يناسب كل الأجهزة. وده خلى الـmedia queries عنصر أساسي في الRWD .
لكن دلوقتي في تحول ناحية حاجة جديدة عرفتها Jen Simmons بـIntrinsic Web Design – اللي بتركز على عمل مكونات بتفهم السياق اللي هي فيه. وContainer Queries هي اللي بتخلي ده ممكن.
مقارنة بين Media Queries و Container Queries في ال CSS
الweb development بيتطور بسرعة، وعشان تواكب التطورات دي لازم تكون فاهم الأدوات الجديدة زي Container Queries وكمان الأدوات التقليدية زي Media Queries. في البوست دا، هنوضح بالتفصيل استخدامات كل أداة، المزايا والعيوب، وازاي تقدر تستفيد منها بأفضل شكل في مشاريعك.
نبدأ بال Media Queries
هي واحدة من أدوات CSS الأساسية اللي بنستخدمها عشان نخلي التصميم responsive ويتغير بناءً على حجم الشاشة أو نوع الجهاز. لما نستخدم Media Queries، بنحدد نقاط معينة (breakpoints) اللي عندها التصميم يتغير.
ال Media Queries
بتسمح لك تعمل تصميم يناسب كل أحجام الشاشات والأجهزة
أغلب مصممي الويب بيكونوا عارفينها ومتعودين عليها
ولكن
مش بتديك تحكم كبير في تعديل العناصر الداخلية لوحدها وركز علي لوحدها دي
لو عندك تصميمات معقدة، ممكن تلاقي نفسك مضطر تكتب كود كتير عشان تغطي كل الحالات
مثال بالكود
@media (max-width: 768px) {
.container {
flex-direction: column;
}
}
نيجي بقي لل Container Queries
جديدة في CSS وبتديك إمكانية تغير التصميم بناءً على حجم الكونتينر اللي العنصر جواه، مش حجم الشاشة. ده بيساعد في تصميم مكونات (components) أكثر مرونة واستقلالية حلو دا عشان ال Reusability
و بتقدر تغير التصميم بناءً على المساحة المتاحة للعنصر بشكل مستقل
ممتازة لتصميمات المكونات اللي بتكون جزء من تصميم أكبر
ولكن
لسه جديدة ومش مدعومة في كل المتصفحات
هتاخد شوية وقت عشان تتعود عليها
شوف بقالك قد إيه بتكتب media queries
مثال بالكود
.header {
container: mysite / inline-size;
}
@container mysite (min-width: 600px) {
.maincard {
grid-template-columns: 1fr 1fr;
}
.item {
background-color: green;
}
}
ركزلي شوية دا ال Syntax
container: [name] / [type];
اسم الكونتينر اللي هتستخدمه في الـContainer Queries
نوع القياس اللي هتستخدمه (inline-size لعرض الكونتينر، block-size لطول الكونتينر)
خاصية inline-size في CSS بتحدد الحجم الأفقي أو الرأسي لكتلة العنصر بناءً على نمط الكتابة المستخدم. لو نمط الكتابة بيكون من اليسار لليمين (مثل اللغة الإنجليزية)، فالـ inline-size هتكون العرض. ولو نمط الكتابة بيكون من الأعلى للأسفل (مثل اللغة الصينية التقليدية)، فالـ inline-size هتكون الطول.
خاصية block-size في CSS بتحدد الحجم الرأسي أو الأفقي لكتلة العنصر بناءً على نمط الكتابة المستخدم. لو نمط الكتابة بيكون من اليسار لليمين، فالـ block-size هتكون الطول. ولو نمط الكتابة بيكون من الأعلى للأسفل، فالـ block-size هتكون العرض.
معلش دي شوية حاجات لازم توضح
في المثال ده، احنا عرفنا كونتينر اسمه mysite ونوع القياس هو inline-size. لما عرض الكونتينر يبقى 600 بيكسل أو أكتر، هتتغير خصائص العناصر جوا الكونتينر.
الميزة بقي في ال Container Queries ال Modularity and Flexibility
يعني كمثال علي دا
تخيل عندك Card component اللي ممكن تستخدمه في أماكن مختلفة في الموقع. باستخدام Container Queries، تقدر تخلي التصميم بتاع الكارد يتغير بناءً على حجم الكونتينر اللي هو فيه.
سهولة إعادة الاستخدام، المكونات اللي بتستخدم Container Queries بتكون سهلة في إعادة الاستخدام في مشاريع مختلفة أو في أجزاء مختلفة من نفس المشروع.
إمتى تستخدم كل واحدة فيهم؟
Media Queries: لما تكون بتشتغل على تصميم استجابي تقليدي وعاوز تغييرات بناءً على حجم الشاشة.
Container Queries: لو عندك تصميم معقد فيه مكونات كتير بأحجام مختلفة عاوز تعدلها بشكل مستقل.
لكن دلوقتي في تحول ناحية حاجة جديدة عرفتها Jen Simmons بـIntrinsic Web Design – اللي بتركز على عمل مكونات بتفهم السياق اللي هي فيه. وContainer Queries هي اللي بتخلي ده ممكن.
مقارنة بين Media Queries و Container Queries في ال CSS
الweb development بيتطور بسرعة، وعشان تواكب التطورات دي لازم تكون فاهم الأدوات الجديدة زي Container Queries وكمان الأدوات التقليدية زي Media Queries. في البوست دا، هنوضح بالتفصيل استخدامات كل أداة، المزايا والعيوب، وازاي تقدر تستفيد منها بأفضل شكل في مشاريعك.
نبدأ بال Media Queries
هي واحدة من أدوات CSS الأساسية اللي بنستخدمها عشان نخلي التصميم responsive ويتغير بناءً على حجم الشاشة أو نوع الجهاز. لما نستخدم Media Queries، بنحدد نقاط معينة (breakpoints) اللي عندها التصميم يتغير.
ال Media Queries
بتسمح لك تعمل تصميم يناسب كل أحجام الشاشات والأجهزة
أغلب مصممي الويب بيكونوا عارفينها ومتعودين عليها
ولكن
مش بتديك تحكم كبير في تعديل العناصر الداخلية لوحدها وركز علي لوحدها دي
لو عندك تصميمات معقدة، ممكن تلاقي نفسك مضطر تكتب كود كتير عشان تغطي كل الحالات
مثال بالكود
@media (max-width: 768px) {
.container {
flex-direction: column;
}
}
نيجي بقي لل Container Queries
جديدة في CSS وبتديك إمكانية تغير التصميم بناءً على حجم الكونتينر اللي العنصر جواه، مش حجم الشاشة. ده بيساعد في تصميم مكونات (components) أكثر مرونة واستقلالية حلو دا عشان ال Reusability
و بتقدر تغير التصميم بناءً على المساحة المتاحة للعنصر بشكل مستقل
ممتازة لتصميمات المكونات اللي بتكون جزء من تصميم أكبر
ولكن
لسه جديدة ومش مدعومة في كل المتصفحات
هتاخد شوية وقت عشان تتعود عليها
شوف بقالك قد إيه بتكتب media queries
مثال بالكود
.header {
container: mysite / inline-size;
}
@container mysite (min-width: 600px) {
.maincard {
grid-template-columns: 1fr 1fr;
}
.item {
background-color: green;
}
}
ركزلي شوية دا ال Syntax
container: [name] / [type];
اسم الكونتينر اللي هتستخدمه في الـContainer Queries
نوع القياس اللي هتستخدمه (inline-size لعرض الكونتينر، block-size لطول الكونتينر)
خاصية inline-size في CSS بتحدد الحجم الأفقي أو الرأسي لكتلة العنصر بناءً على نمط الكتابة المستخدم. لو نمط الكتابة بيكون من اليسار لليمين (مثل اللغة الإنجليزية)، فالـ inline-size هتكون العرض. ولو نمط الكتابة بيكون من الأعلى للأسفل (مثل اللغة الصينية التقليدية)، فالـ inline-size هتكون الطول.
خاصية block-size في CSS بتحدد الحجم الرأسي أو الأفقي لكتلة العنصر بناءً على نمط الكتابة المستخدم. لو نمط الكتابة بيكون من اليسار لليمين، فالـ block-size هتكون الطول. ولو نمط الكتابة بيكون من الأعلى للأسفل، فالـ block-size هتكون العرض.
معلش دي شوية حاجات لازم توضح
في المثال ده، احنا عرفنا كونتينر اسمه mysite ونوع القياس هو inline-size. لما عرض الكونتينر يبقى 600 بيكسل أو أكتر، هتتغير خصائص العناصر جوا الكونتينر.
الميزة بقي في ال Container Queries ال Modularity and Flexibility
يعني كمثال علي دا
تخيل عندك Card component اللي ممكن تستخدمه في أماكن مختلفة في الموقع. باستخدام Container Queries، تقدر تخلي التصميم بتاع الكارد يتغير بناءً على حجم الكونتينر اللي هو فيه.
سهولة إعادة الاستخدام، المكونات اللي بتستخدم Container Queries بتكون سهلة في إعادة الاستخدام في مشاريع مختلفة أو في أجزاء مختلفة من نفس المشروع.
إمتى تستخدم كل واحدة فيهم؟
Media Queries: لما تكون بتشتغل على تصميم استجابي تقليدي وعاوز تغييرات بناءً على حجم الشاشة.
Container Queries: لو عندك تصميم معقد فيه مكونات كتير بأحجام مختلفة عاوز تعدلها بشكل مستقل.
❤4🥰1
إعمل save للبوست أو share هتحتاجه كدا كدا ...
عاوز تبقي software engineer جامد جمودة ؟
البوست دا هيبقي refrence لل GitHub Repositories و هصنفهالك categories
يعني لو إنت شخص بتدور علي github repositories لل RoadMaps
1 - https://github.com/kamranahmedse/developer-roadmap
2 - https://github.com/liuchong/awesome-roadmaps
بتدور علي github repositories لل Books, Blogs, and Websites
1 - https://github.com/EbookFoundation/free-programming-books
2 - https://github.com/kilimchoi/engineering-blogs
3 - https://github.com/sdmg15/Best-websites-a-programmer-should-visit
4 - https://github.com/freeCodeCamp/freeCodeCamp
بتدور علي github repositories لل Algorithms
1 - https://github.com/TheAlgorithms
2 - https://github.com/arpit20adlakha/Data-Structure-Algorithms-LLD-HLD
3 - https://github.com/tayllan/awesome-algorithms
بتدور علي github repositories لل Algorithms
1 - https://github.com/kamranahmedse/design-patterns-for-humans
2 - https://github.com/DovAmir/awesome-design-patterns
بتدور علي github repositories لل System Design
1 - https://github.com/ByteByteGoHq/system-design-101
2 - https://github.com/donnemartin/system-design-primer
3 - https://github.com/InterviewReady/system-design-resources
4 - https://github.com/karanpratapsingh/system-design
بتدور علي github repositories للDesign Resources
1 - https://github.com/goabstract/Awesome-Design-Tools
2 - https://github.com/bradtraversy/design-resources-for-developers
بتدور علي github repositories لل Projects, Tutorials, and APIs
1 - https://github.com/florinpop17/app-ideas
2 - https://github.com/practical-tutorials/project-based-learning
3 - https://github.com/public-apis/public-apis
بتدور علي github repositories لل Interviews
1 - https://github.com/kdn251/interviews
2 - https://github.com/yangshun/tech-interview-handbook
3 - https://github.com/DopplerHQ/awesome-interview-questions
عاوز تبقي software engineer جامد جمودة ؟
البوست دا هيبقي refrence لل GitHub Repositories و هصنفهالك categories
يعني لو إنت شخص بتدور علي github repositories لل RoadMaps
1 - https://github.com/kamranahmedse/developer-roadmap
2 - https://github.com/liuchong/awesome-roadmaps
بتدور علي github repositories لل Books, Blogs, and Websites
1 - https://github.com/EbookFoundation/free-programming-books
2 - https://github.com/kilimchoi/engineering-blogs
3 - https://github.com/sdmg15/Best-websites-a-programmer-should-visit
4 - https://github.com/freeCodeCamp/freeCodeCamp
بتدور علي github repositories لل Algorithms
1 - https://github.com/TheAlgorithms
2 - https://github.com/arpit20adlakha/Data-Structure-Algorithms-LLD-HLD
3 - https://github.com/tayllan/awesome-algorithms
بتدور علي github repositories لل Algorithms
1 - https://github.com/kamranahmedse/design-patterns-for-humans
2 - https://github.com/DovAmir/awesome-design-patterns
بتدور علي github repositories لل System Design
1 - https://github.com/ByteByteGoHq/system-design-101
2 - https://github.com/donnemartin/system-design-primer
3 - https://github.com/InterviewReady/system-design-resources
4 - https://github.com/karanpratapsingh/system-design
بتدور علي github repositories للDesign Resources
1 - https://github.com/goabstract/Awesome-Design-Tools
2 - https://github.com/bradtraversy/design-resources-for-developers
بتدور علي github repositories لل Projects, Tutorials, and APIs
1 - https://github.com/florinpop17/app-ideas
2 - https://github.com/practical-tutorials/project-based-learning
3 - https://github.com/public-apis/public-apis
بتدور علي github repositories لل Interviews
1 - https://github.com/kdn251/interviews
2 - https://github.com/yangshun/tech-interview-handbook
3 - https://github.com/DopplerHQ/awesome-interview-questions
❤2🥰1
هل إنت من المبرمجين الشريرين ولا مبرمج طيوب لذوذ ؟
متستغربش تعال أقولك سيناريو غريب شوية،حازم بيستخدم موقعك من نفس المتصفح اللي بيخش بيه ع موقع زي ٱموالي أو موقع البنك يخلص معاملاته الرقمية ، واللي بيفتح منه برضه جيميل
ف طبعا المتصفح بيخزن ال cookies بتاعة حازم
طبعا إنت عارف الconcept بتاع AJAX
(Asynchronous JavaScript And XML)
طب م أحاول في موقعي
أعمل كود JavaScript يجيبلي بيانات حازم من المتصفح وبعدين أستخدم AJAX علشان أبعت ريكوست عشان أخزن بيانات حساب حازم أو أبعت ريكوست للجيميل كأني حازم
stoooooooooooooooop
بس ومتسرحش بخيالك ي نجم
مفيش حاجة من دي هتحصل عشان تفهم ليه
هنا بقى ييجي دور SOP
قبل ما نخش في التفاصيل، لازم نفهم حاجتين مهمين:
SOP (Same-Origin Policy)
CORS (Cross-Origin Resource Sharing)
SOP
ده بيوفر أمان أساسي. ببساطة، بيمنع أي موقع (زي موقعك كمبرمج شرير ) من إنه يقرأ البيانات أو الكوكيز من موقع تاني (زي جيميل) إلا لو الاتنين من نفس الأصل (الدومين، البروتوكول، والبورت).
يعني متقدرش تقرأ كوكيز الجيميل إلا لو إنت ال gmail !
CORS:
ده بقى زي المساعد لـSOP، بيدي استثناءات، يعني يسمح لبعض المواقع إنها تبادل بيانات مع بعضها بشروط معينة
____
واحدة واحدة بقي ، السيناريو اللي إنت كنت عاوز تعمله دا كمبرمج مش لذوذ إسمه CSRF
(Cross-Site Request Forgery)
يعني إيه يعني بستغل الثقة بتاعة حازم فيا كموقع وأستخدم الكوكيز الخاصة بيه لعمل تحويل مالي من حسابه لحسابي ..
العملية مش سهلة كدا ي نجم أولا ف أدوات حماية مختلفة
نبدأ ب
SOP (Same Origin Policy)
ودي زي م قلتلك مش هيسمح لأي سكريبتات على "example.com" إنها تقرأ البيانات بتاعتك من "anotherdomain.com" أو تبعت ريكوستات له يعني من الأخر بيضمن أن المواقع الضارة مش قادرة على الوصول إلى الكوكيز أو الموارد من دومين تاني بدون إذن.
تاني حاجة
HttpOnly Attribute
ودي ببساطة خاصية بتضاف للكوكيز بتخليها مش accesible من ال JavaScript.
لما الكوكيز تكون عليها HttpOnly، مش ممكن للسكريبتات اللي على المتصفح قراءة الكوكيز دي، وده بيحميها من هجمات
XSS (Cross-Site Scripting).
تالت حاجة وهي ال SameSite Attribute
هو خاصية تانية في الكوكيز بتحدد مدى مرونة إرسال الكوكيز بين المواقع. فيه ثلاث قيم رئيسية للخاصية دي:
Strict:
الكوكيز هتترسل بس مع الطلبات اللي جايه من نفس النطاق.
Lax:
الكوكيز هتترسل مع الطلبات اللي جايه من نفس النطاق وأيضًا مع الطلبات من روابط من مواقع أخرى، ولكن فقط مع بعض الطلبات زي GET.
None:
الكوكيز هتترسل مع الطلبات عبر المواقع المختلفة بدون قيود، ولكن لازم يكون الطلب عبر HTTPS.
_
يبقي كده SOP
بيوفر الحماية من الوصول الغير مصرح به بين الdomains.
HttpOnly
بيوفر الحماية للكوكيز من الوصول عبر JavaScript، مما يساعد في الحماية من XSS.
SameSite
بيوفر حماية مخصصة ضد CSRF من خلال تحديد متى وأين يمكن إرسال الكوكيز.
التكامل بين الثلاث أدوات دي بيوفر layers للحماية ضد مجموعة متنوعة من التهديدات، بما في ذلك CSRF، XSS، والتهديدات الأخرى المتعلقة بالكوكيز.
ف من الأخر السيناريو باعك كمبرمج شرير باظ ليه بقي ؟
في حالة المواقع الكبيرة زي جيميل، الكوكيز عادةً ما بتكون محمية بخصائص إضافية غير HttpOnly، زي:
إستخدام خاصية SameSite في الكوكيز بتاعتهم لتقليل فرص هجمات CSRF.
استخدام (CSRF Tokens)
المواقع الكبيرة بتضيف (CSRF Tokens) في الformsِ والطلبات الحساسة. الرموز دي بتكون فريدة لكل session وكل request
Token Validation
لما المستخدم يبعت طلب (POST request مثلا)،
الموقع بيتأكد إن الرمز اللي جاي مع الطلب هو نفس الرمز اللي الموقع أصدره للمستخدم ده.
لو الرمز مش مطابق، الطلب بيرفض.
تفعيل CORS بشكل محدود
CORS (Cross-Origin Resource Sharing):
المواقع الكبيرة بتستخدم إعدادات CORS بشكل محدود عشان تسمح لبعض الdomains الموثوقة بالوصول للموارد، وبكده تمنع الdomains الغير مصرح بها.
Content Security Policy (CSP)
المواقع بتستخدم CSP لتحديد المصادر المسموح لها بالتحميل والتشغيل على الصفحة، مما يقلل فرص تنفيذ كود ضار على الموقع.
Secure Attribute:
الكوكيز بتاعت الجلسات بتكون عليها خاصية Secure عشان يتم إرسالها بس عبر اتصالات HTTPS، وده بيمنع تسرب الكوكيز عبر اتصالات مش encrypted
متستغربش تعال أقولك سيناريو غريب شوية،حازم بيستخدم موقعك من نفس المتصفح اللي بيخش بيه ع موقع زي ٱموالي أو موقع البنك يخلص معاملاته الرقمية ، واللي بيفتح منه برضه جيميل
ف طبعا المتصفح بيخزن ال cookies بتاعة حازم
طبعا إنت عارف الconcept بتاع AJAX
(Asynchronous JavaScript And XML)
طب م أحاول في موقعي
أعمل كود JavaScript يجيبلي بيانات حازم من المتصفح وبعدين أستخدم AJAX علشان أبعت ريكوست عشان أخزن بيانات حساب حازم أو أبعت ريكوست للجيميل كأني حازم
stoooooooooooooooop
بس ومتسرحش بخيالك ي نجم
مفيش حاجة من دي هتحصل عشان تفهم ليه
هنا بقى ييجي دور SOP
قبل ما نخش في التفاصيل، لازم نفهم حاجتين مهمين:
SOP (Same-Origin Policy)
CORS (Cross-Origin Resource Sharing)
SOP
ده بيوفر أمان أساسي. ببساطة، بيمنع أي موقع (زي موقعك كمبرمج شرير ) من إنه يقرأ البيانات أو الكوكيز من موقع تاني (زي جيميل) إلا لو الاتنين من نفس الأصل (الدومين، البروتوكول، والبورت).
يعني متقدرش تقرأ كوكيز الجيميل إلا لو إنت ال gmail !
CORS:
ده بقى زي المساعد لـSOP، بيدي استثناءات، يعني يسمح لبعض المواقع إنها تبادل بيانات مع بعضها بشروط معينة
____
واحدة واحدة بقي ، السيناريو اللي إنت كنت عاوز تعمله دا كمبرمج مش لذوذ إسمه CSRF
(Cross-Site Request Forgery)
يعني إيه يعني بستغل الثقة بتاعة حازم فيا كموقع وأستخدم الكوكيز الخاصة بيه لعمل تحويل مالي من حسابه لحسابي ..
العملية مش سهلة كدا ي نجم أولا ف أدوات حماية مختلفة
نبدأ ب
SOP (Same Origin Policy)
ودي زي م قلتلك مش هيسمح لأي سكريبتات على "example.com" إنها تقرأ البيانات بتاعتك من "anotherdomain.com" أو تبعت ريكوستات له يعني من الأخر بيضمن أن المواقع الضارة مش قادرة على الوصول إلى الكوكيز أو الموارد من دومين تاني بدون إذن.
تاني حاجة
HttpOnly Attribute
ودي ببساطة خاصية بتضاف للكوكيز بتخليها مش accesible من ال JavaScript.
لما الكوكيز تكون عليها HttpOnly، مش ممكن للسكريبتات اللي على المتصفح قراءة الكوكيز دي، وده بيحميها من هجمات
XSS (Cross-Site Scripting).
تالت حاجة وهي ال SameSite Attribute
هو خاصية تانية في الكوكيز بتحدد مدى مرونة إرسال الكوكيز بين المواقع. فيه ثلاث قيم رئيسية للخاصية دي:
Strict:
الكوكيز هتترسل بس مع الطلبات اللي جايه من نفس النطاق.
Lax:
الكوكيز هتترسل مع الطلبات اللي جايه من نفس النطاق وأيضًا مع الطلبات من روابط من مواقع أخرى، ولكن فقط مع بعض الطلبات زي GET.
None:
الكوكيز هتترسل مع الطلبات عبر المواقع المختلفة بدون قيود، ولكن لازم يكون الطلب عبر HTTPS.
_
يبقي كده SOP
بيوفر الحماية من الوصول الغير مصرح به بين الdomains.
HttpOnly
بيوفر الحماية للكوكيز من الوصول عبر JavaScript، مما يساعد في الحماية من XSS.
SameSite
بيوفر حماية مخصصة ضد CSRF من خلال تحديد متى وأين يمكن إرسال الكوكيز.
التكامل بين الثلاث أدوات دي بيوفر layers للحماية ضد مجموعة متنوعة من التهديدات، بما في ذلك CSRF، XSS، والتهديدات الأخرى المتعلقة بالكوكيز.
ف من الأخر السيناريو باعك كمبرمج شرير باظ ليه بقي ؟
في حالة المواقع الكبيرة زي جيميل، الكوكيز عادةً ما بتكون محمية بخصائص إضافية غير HttpOnly، زي:
إستخدام خاصية SameSite في الكوكيز بتاعتهم لتقليل فرص هجمات CSRF.
استخدام (CSRF Tokens)
المواقع الكبيرة بتضيف (CSRF Tokens) في الformsِ والطلبات الحساسة. الرموز دي بتكون فريدة لكل session وكل request
Token Validation
لما المستخدم يبعت طلب (POST request مثلا)،
الموقع بيتأكد إن الرمز اللي جاي مع الطلب هو نفس الرمز اللي الموقع أصدره للمستخدم ده.
لو الرمز مش مطابق، الطلب بيرفض.
تفعيل CORS بشكل محدود
CORS (Cross-Origin Resource Sharing):
المواقع الكبيرة بتستخدم إعدادات CORS بشكل محدود عشان تسمح لبعض الdomains الموثوقة بالوصول للموارد، وبكده تمنع الdomains الغير مصرح بها.
Content Security Policy (CSP)
المواقع بتستخدم CSP لتحديد المصادر المسموح لها بالتحميل والتشغيل على الصفحة، مما يقلل فرص تنفيذ كود ضار على الموقع.
Secure Attribute:
الكوكيز بتاعت الجلسات بتكون عليها خاصية Secure عشان يتم إرسالها بس عبر اتصالات HTTPS، وده بيمنع تسرب الكوكيز عبر اتصالات مش encrypted
❤4🥰1