لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 05/15/15 في كل الموقع
-
في المقال الأول تكلمنا حول أساسيات صفحات الهبوط، وفي المقال الثاني صممنا صفحة هبوط في Photoshop باستخدام ما تعلمانه، الآن سنكمل ما بدأنا به ببناء صفحة الهبوط فعليا، سنمر على كل المراحل إنطلاقا من توزيع الملفات إلى صفحة جاهزة، هيا لننطلق. يمكنك تحميل الشِفرة المصدرية لهذا الدرس لمعاينة النتيجة النهائية. وهذا تذكير بواجهة الصفحة: الأساسياتفي البداية سنقوم بتوضيح ما سنقوم باستخدامه ولماذا سنستخدمه. أولا، لدينا الصور التي حصلنا عليها من ملف PSD الذي قمنا بتصميمه في درس التصميم، فلنستخدمها.لن نستخدم خط أيقونات لسبب وجيه وهو أنها ستكون مضيعة وقت وبدون فائدة فعلية فالصفحة مجرد صفحة واحدة لذا لا يوجد الكثير لنقلق بشأنه (بشأن عدد طلبات HTTP كمثال).سنستخدم هيكلة HTML5 Boilerplate وهو هيكل عمل مصغر لبناء صفحات HTML حيث يحتوي على تقسيم مجلدات ممتاز، ويوزدك ببعض الملفات المهمة مثل .htaccess و ملف index كامل يحتوي على كل شيء تحتاجه.سنستعمل بعض إضافات إطار عمل Bootstrap، وهم: Affix من أجل تثبيت قائمة التصفح عند النزول.إضافة Scrollspy من أجل تغيير لون الأيقونات كلما ممرنا على مرحلة.سنستخدم إضافة Owl carousel 2.0 من أجل جزء الشهادات، إذا كنت تملك إضافة أخرى فأنت حر باستخدامها.سنستعمل موقع TinyPNG من أجل ضغط الصور التي حصلنا عليها من ملف PSD.سنستخدم موقع Everything Font من أجل تحويل خط Cocon إلى نسخة الويب (woff) حتى نستخدمها.تقسييم الملفاتسيكون تقسيمنا للملفات على الشكل التالي: project/ ├── css/ │ ├── main.css │ ├── normalize.css │ └── owl.carousel.css ├── fonts/ │ └── CoconNextArabicLight.woff ├── js/ │ ├── main.js │ └── vendors/ │ ├── bootstrap.min.js │ ├── jquery-1.11.2.min.js │ └── owl.carousel.min.js ├── img/ ├── index.html └── favicon.icoعند تحميل إطار عمل H5BP فإنه يزودنا بالتقسييم بالتالي بشكل افتراضي، ما قمنا به نحن هو إضافة بعض الملفات في بعض الأماكن فحسب، مجلد img يحتوي على الصور التي حصلنا عليها من المرحلة السابقة عبر استخراجها من فوتوشوب، كما قمنا بإضافة bootstrap.js الذي يحتوي على كلٍ من affix وscrollspy. وقمنا بحذف بعض الملفات مثل modernizer وhtml5shiv لأننا لن ندعم المتصفحات القديمة. البدايةحسنا، نحتاج إلى أن نعد بعض الأمور قبل أن نبدأ، بعد تحميل كامل المكتبات المطلوبة نستطيع البدأ بإعداد بعض الأمور. نحن نملك خط Cocon بصيغة سطح المكتب (ttf). لا ضرر في هذه الصيغة إطلاقا، هي تعمل بشكل ممتاز في المتصفحات، ولكننا نستطيع تقليل الحجم إلى النصف عبر تحويل الخط إلى صيغة woff المخصصة للويب وذلك عبر موقع التحويل (ستجد الخط محولا في الشفرة المصدرية لهذا الدرس). نحتاج إلى ضغط الصور، هناك فائدة عظيمة نكسبها هنا، موقع TinyPNG سيقوم بتقليل حجم الصور إلى أكثر 70% مع الحفاظ على الجودة، وهذا حجم ممتاز لذلك سنقوم بذلك أيضا. الآن سنعد بعض الأمور الابتدائية في ملف CSS: @import url(owl.carousel.css); @font-face { font-family: Cocon; src: url(../fonts/CoconNextArabicLight.woff) format('woff'); } *, *:before, *:after { box-sizing: border-box; } body { font-family: cocon, sans-serif; background: #fff; position: relative; }سنقوم باستدعاء ملف owl.carousel من أجل تأثيرات الحركة في السكربت، سنقوم بإدراج خط Cocon للاستخدام، سنستعمل box-sizing من أجل احتواء العناصر بشكل أفضل. سنضيف بعض الأمور الافتراضية لوسم body. مكتبة scrollspy تحتاج إلى أن يكون وسم body بخاصية position:relative من أجل أن تعمل.هيكلة الصفحةفي سابق الأمر، كنُت قد خططت لبناء الصفحة عبر إطار عمل Bootstrap المعروف، وسبق وقلت هذا في المقال السابق، ولكني تراجعت عن الأمر لقلة الفوائد مقارنة بالسيئات، ووجدتها فرصة حسنة لاستخدام Flex module والتكلم عنه أكثر. أما بخصوص Bootstrap فلدي آرائي حوله، من بينها أنّه إطار مناسب تماما لإطلاق المشاريع بسرعة من أجل التجريب (لاحظ الاسم Bootstrap) كما أنّه إطار مناسب لبناء المشاريع الداخلية حيث لن يتم إطلاق المشروع لجمهور فعلي، إلا إذا كنت تنوي تخصيصه حتى النخاع فتغير مظهره، فذلك شأنك. الصفحة مكونة من 6 أجزاء أساسية: رأس الصفحة.روابط التصفح عبر الصفحة.مميزات التطبيق.الاقتباسات (أو الشهادات).الأرقام (أو التحليلات).التحميل والمشاركة.والهيكة الأساسية ستكون كالتالي: <header class="l-header"> <div class="l-app-preview"> </div> <div class="l-page-fold"> </div> </header><!-- .l-header --> <nav class="l-sticky-nav"> <div class="sticky-nav"> </div><!-- sticky-nav --> </nav><!-- l-sticky-nav --> <article id="features-section"> <section class="l-app-feature"> </section> </article><!-- #features-section --> <article id="testimonials-section"> </article><!-- #testimonials-section --> <article id="analysicts-section"> </article><!-- #analysicts-section --> <article id="download-section"> </article><!-- #download-section -->قمنا بتقسييم كل جزء من الصفحة إلى وسم article مستقل (ما عدى روابط التصفح ورأس الصفحة حيث يملكان وسوما افتراضية خاصة بهم من قبل). قمنا بتقسييم رأس الصفحة إلى جزئين، الأول سيحتوي بداخله صورة واجهة التطبيق، أما الثاني فسيحتوي على العنوان إلى جانب السطر الرئيسي وزر التحميل. روابط التصفح تملك جزئين، حاوي رئيسي وحاوي الروابط، وهناك سبب وجيه لهذا التكرار، بحيث عندما يتم تفعيل تثبيت الروابط على أعلى الشاشة، نرى أن يبقى هناك مكان فارغ (في المكان السابق الذي كانت الروابط موجودة فيه) حيث لا يحدث اختلال في الصفحة، الجزء المسؤول عن هذا سيكون l-sticky-nav، أيضا لاحظوا أنّ كل الروابط التي تحتوي على حرف L قبل اسمها (اختصارا لـ layout) ستكون مسؤولة عن الهيكلة بشكل خاص. رأس الصفحة<header class="l-header"> <div class="l-app-preview"> <img src="img/home-screen.png" alt=""> </div> <div class="l-page-fold"> <h1 class="display-title">اكتشف أشخاصا بنفس اهتماماتك</h1> <p class="display-content">تعرف على أشخاص يشاركونك الهوايات والاهتمامات شارك، اقرء، وتواصل مع الجميع عبر تطبيق اهتمامات</p> <a href="" class="display-badge"> <img src="img/badge.png" alt="حمل من متجر التطبيقات"> </a> </div> </header><!-- .l-header -->كان ذلك هو رأس الصفحة، بكل بساطة وكما أشدنا سابقا، الآن حان وقت إضافة بعض CSS له. .l-header { display: flex; justify-content: center; align-items: center; width: 100%; min-height: 100vh;/* used to make sure the header will cover the screen */ position: relative; padding: 48px 0; /* سيعطي هذا بعض المساحة للشاشات الصغيرة حيث المحتوى أكبر من ارتفاع الشاشة */ background: url(../img/background.png) center center no-repeat; background-attachment: fixed; background-size: cover; }الشفرة المصدرية مقسمة لثلاث أجزاء، كل جزء له مهمته المعينة. الجزء الأول مسؤول عن هيكلة رأس الصفحة، نحن نطلب منه أن يستخدم flex كنظام للهيكلة عبر display:flex وأن يقوم بوضع جميع العناصر في منتصف الصفحة أفقيا عبر justify-content:center والواقع أنها تقبل العديد من الخيارات الأخرى، منها flex-start التي تضع جميع العناصر في بداية الصفحة (اليمين في حالة العربية، أو اليسار في حالة اللاتينية، لكن الأمر لا علاقة له باتجاه الصفحة في واقع الأمر، بل باتجاه ترتيب العناصر عبر خاصية flex-direction التي تقبل 4 خيارات وهي ترتيب العناصر بشكل أفقي من بداية الصفحة لنهايتها عبر row ومن نهاية الصفحة إلى بدايتها عبر row-reverse أو من أعلى الصفحة إلى أسفلها عبر column أو العكس عبر column-reverse وسنتكلم عن هذا لاحقا) أو خيار flex-end الذي يقوم بالعكس، والخياران اللذان ستستخدمها كثيرا وهما space-around حيث يتم توزيع المساحة بين العناصر بالتساوي (وبالتالي في المنتصف ولكن مع مساحة بينهم وقبلهم وبعدهم) و space-between والتي تقوم بتوزيع المساحة بين العناصر بدون إضافة مساحة قبل العناصر وبعدهم (أيّ يتم تركيز كامل المساحة في المنتصف). الخيار الثالث يقول أننا نريد أن نضع العناصر في المنتصف عموديا وذلك عبر align-items:center والواقع أنّ الخاصية تملك أيضا خيارات كثيرة لا متسع لنا لشرحها كاملة الآن لأنها تحتاح لشرح بالصور في الغالب، ومنها flex-start التي تضع العناصر أعلى الصفحة (أو بالأحرى حسب الطريقة التي تم تحديد اتجاه المحور العمودي فيها عبر flex-direction كما بيّنا سابقا). الجزء الثاني، هو مسؤول عن جعل حجم رأس الصفحة بكامل أبعاد الشاشة، نستطيع جعله بكامل عرض الشاشة عبر width:100% أو بالمثل عبر width:100vw لا فرق بينهم لأنّ حاوي رأس الصفحة نفسه بكامل عرض الصفحة، تبقى المشكلة في الارتفاع، تحديد 100% لن ينفع وتحديد رقم معين لن ينفع إطلاقا مع كل الشاشات، الحل الوحيد هو استخدام وحدة القياس الجديدة vh والتي تقيم أبعاد الشاشة وليس العناصر، بحيث 100vh تعني كامل ارتفاع الشاشة. في الجزء الثالث سنقوم بإضافة خلفية، وضعها في المنتصف، نعطيها خاصية cover حتى تتمدد (مع المحافظة على الأبعاد ratio) على حسب الشاشة. .l-header:before { content: ""; position: absolute; top: 0; right: 0; height: 100%; width: 100%; background-color: rgba(0,0,0,0.64); }هذا الجزء مسؤول عن إضافة تأثير السواد فوق الصورة، البعض يقوم بإضافة عنصر (div) آخر داخل رأس الصفحة من أجل تحقيق هذا، ولكن هذا الحل أكثر نظافة، لاشيء فعلي لنشرحه هنا عدى أنّ عدم إدراج خاصية content (حتى ولو كانت فارغة) سيجعل الشفرة المصدرية السابقة غير فعالة، فأشباه الأصناف (pseudo-classes) لا تعمل بدونه. .l-app-preview, .l-page-fold { width: 50%; z-index: 10; position: relative; /* نحتاج إلى هذا الجزء لأن خاصية z-index لا تعمل مع static */ }هنا نقوم بإعطاء كل جزء منهم 50% من عرض الحاوي الخاص بهم، حتى يتم توزيع المحتوى بشكل عادل، خاصية z-index حتى نتأكد من أنّ المحتوى فوق تأثير السواد على الخلفية (لن يشكل هذا مشكلة في الأغلب لأننا استخدمنا شبه صنع before الذي سيضعه قبل العناصر أصلا). خاصية position:relative تم وضعها من أجل z-index لأنّه لا يعمل بدون تحديدها (في الواقع هو يعمل مع الجميع عدى static أيّ القيمة الافتراضية). مع إضافة بعض التأثيرات على العنوان، والقيام بتوسيط الصفحة، نخرج بهذه الشِفرة: .l-header { display: flex; justify-content: center; align-items: center; width: 100%; min-height: 100vh; position: relative; padding: 48px 0; background: url(../img/background.png) center center no-repeat; background-attachment: fixed; background-size: cover; } .l-header:before { content: ""; position: absolute; top: 0; right: 0; height: 100%; width: 100%; background-color: rgba(0,0,0,0.64); } .l-app-preview, .l-page-fold { width: 50%; z-index: 10; position: relative; } .l-app-preview img { display: block; margin: 0 auto; } .l-page-fold { padding-left: 24px; } .display-title { color: #fff; font-size: 55px; line-height: 1.2; margin-bottom: 36px; } .display-content { color: #fff; font-size: 28px; line-height: 1.7; margin-bottom: 128px; }تاليا سنعمل على روابط التصفح روابط التصفحالهيكلة كالتالي: <nav class="l-sticky-nav"> <div class="sticky-nav"> <div class="nav-element"> <a href="#features-section" class="nav-element--link active"> <img src="img/equalizer.png" alt="" class="nav-element--image"> </a> </div> <div class="nav-element"> <a href="#testimonials-section" class="nav-element--link"> <img src="img/id.png" alt="" class="nav-element--image"> </a> </div> <div class="nav-element"> <a href="#analysicts-section" class="nav-element--link"> <img src="img/globe.png" alt="" class="nav-element--image"> </a> </div> <div class="nav-element"> <a href="#download-section" class="nav-element--link"> <img src="img/download.png" alt="" class="nav-element--image"> </a> </div> </div><!-- sticky-nav --> </nav><!-- l-sticky-nav -->لاشيء لشرحه، هيا لنطلع على شِفرة CSS: .l-sticky-nav { margin-bottom: 128px; /* هذا الجزء منفصل عن روابط التحكم، بالأحرى عندما تلتصق الروابط في أعلى الشاشة سيبقى هذا في مكانه */ } .l-sticky-nav.fixed { padding: 50px; /* عندما يتم تثبيت التثبيت على روابط التصفح، سيبقى هذا في مكانه حتى لا تختل المساحة */ }سنعطي الحاوي الأول بعض المساحة في الأسفل، أيضا عندما يتم تثبيت الروابط سيصبح l-sticky-nav فارغا وبالتالي يكون ارتفاعه 0، مما يلغي فائدته، لذا في تلك الحالة سنجعل ارتفاعه 100px. الآن بالنسبة للحاوي الثاني: .sticky-nav { display: flex; justify-content: space-around; flex-wrap: wrap; padding: 24px; background-color: #fff; box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.1); }خاصية flex-wrap تحدد هل سيقوم الحاوي بوضع كامل العناصر في سطر واحد (عبر إعطائه no-wrap أيضا الخاصية الافتراضية) أو بوضع العناصر في سطر جديد إن لم يكن هناك متسع من المكان (عبر wrap)، عدى هذا كل شيء واضح، نقوم بتوسيط العناصر فحسب. .sticky-nav.affix { top: 0; right: 0; width: 100%; z-index: 10; position: fixed; }الآن عند تفعيل التثبيت سيتم (عبر Javascript) إضافة class إلى الحاوي الثاني، إنطلاقا منه سنقوم بتحديد ما نريده، وهو تثبيت العناصر في أعلى الشاشة، لكن في العلم أنّه عند إضافة خاصية fixed فالعنصر يخرج من نسق الصفحة، وشيء آخر وهو أنّ خاصية display:block لا تفيد بشيء حينها، لذا العنصر لن يأخذ كامل المساحة الأفقية التي يجدها (width:100%) بل يأخذ ما يحتاجه فحسب، لذا علينا تحديد الأمر بأنفسنا. .nav-element--image { filter: grayscale(100%); -webkit-filter: grayscale(100%); transition: all 200ms ease-out; } .nav-element--link.active .nav-element--image, .nav-element--link:hover .nav-element--image { filter: grayscale(0); -webkit-filter: grayscale(0); }نقوم بتحويل جميع الأيقونات إلى الرمادي عدى الأيقونات المفعلة (.active) أو التي يكون المؤشر فوقها. وهكذا نكون انتهينا من جزء آخر، الدور على جزء مميزات التطبيق. مميزات التطبيقالهيكلة كالتالي: <article id="features-section"> <section class="l-app-feature"> <div class="app-feature-preview"> <img src="img/feature-1.png" alt="" class="app-feature-image"> </div> <div class="app-feature-content"> <h2 class="app-feature-title">أضف، تابع، وتواصل مع من تشاركه الاهتمام</h2> <p class="app-feature-text">أضف إلى قائمة أصدقائك من تجدهم يشاركونك نفس الاهتمام، صنف أصدقائك على حسب اهتماماتك، وتواصل مباشرة معهم</p> </div> </section> <section class="l-app-feature"> <div class="app-feature-preview"> <img src="img/feature-2.png" alt="" class="app-feature-image"> </div> <div class="app-feature-content"> <h2 class="app-feature-title">شارك ما تجده مميزا، وعبر عن رأيك</h2> <p class="app-feature-text">أكتب المقالات لتشاركها مع دائرة أصدقائك، وأقرء مقالات الجديدة أو اكتشف اهتمامات جديدة</p> </div> </section> <section class="l-app-feature"> <div class="app-feature-preview"> <img src="img/feature-3.png" alt="" class="app-feature-image"> </div> <div class="app-feature-content"> <h2 class="app-feature-title">ابني حسابك الشخصي، وأحصل على متابعين</h2> <p class="app-feature-text">ابني حسابك الشخصي الخاص، شارك صورك وسيرتك، ودع الناس يقومون بمتابعتك</p> </div> </section> </article><!-- #features-section -->تم تقسييم كل جزء إلى section خاص به يحتوي بدوره على قسمين، واحد للصورة وواحد للعنوان والشرح، الأمر شبيه تماما برأس الصفحة، في الواقع سيعمل بنفس مفهوم رأس الصفحة. .l-app-feature { display: flex; justify-content: center; align-items: center; padding: 128px 0; } .l-app-feature:nth-child(even) { flex-direction: row-reverse; background: #13191C; } .l-app-feature:nth-child(even) .app-feature-title, .l-app-feature:nth-child(even) .app-feature-text { color: white; }الشيء الوحيد الجديد هنا هو (nth-child(even نحن هنا نقوم بتحديد كل العناصر التي تكون رتبتها رقما زوجيا (الثاني والرابع والسادس، يمكن أيضا القيام بالأمر عبر تمرير 2n+2 بدل evenمن أجل نفس النتيجة، في الواقع تستطيع تمرير أي معادلة من الشكلة an+b من أجل استهداف العناصر التي تريدها) قمنا بتمرير flex-direction:row-reverse من أجل عكس اتجاه المحور الأفقي حتى تبدأ العنصر من الاتجاه المعاكس، هذا سيجعل الصورة على اليسار والمحتوى على اليمين. وهذه كامل الشِفرة .l-app-feature { display: flex; justify-content: center; align-items: center; padding: 128px 0; } .l-app-feature:nth-child(even) { flex-direction: row-reverse; background: #13191C; } .l-app-feature:nth-child(even) .app-feature-title, .l-app-feature:nth-child(even) .app-feature-text { color: white; } .app-feature-preview, .app-feature-content { width: 50%; max-width: 600px; } .app-feature-preview img { display: block; margin: 0 auto; } .app-feature-title { font-size: 36px; color: #f85940; margin-bottom: 36px; } .app-feature-text { font-size: 28px; color: rgba(30,30,30,.9); line-height: 1.7; }جزء الشهاداتفي هذا الجزء قمنا باستخدام carousel من أجل عرض الشهادات والهيكلة كانت كالتالي: <article id="testimonials-section"> <h1 class="section-title">فلنسمع رأي البقية</h1> <section class="testimonials-carousel"> <div class="testimonial-item"> <div class="testimonial-text">أتمنى لو كان هذا التطبيق موجودا قبل سنة</div> <div class="testimonial-avatar"><img src="img/face-1-128.png" alt="" class="testimonial-image"></div> </div> </section> </article><!-- #testimonials-section -->أضفنا عنوانا، إلى جانب وضع الشهادات في حاوي خاص بهم من أجل تحديده عبر Javascript، ثم وضعنا لكل شهادة حاوي خاص بها testimonial-text يحتوي على محتوى الشهادة بالإضافة إلى صورة. .testimonial-item { display: flex; flex-direction: column; align-items: center; padding: 24px 0; margin-bottom: 48px; }هيكلة كل عنصر يتكون بسيطة، استخدما flex-direction:column لترتيب العناصر عموديا، كما استخدما align-items:center لتوسيط العناصر أفقيا (لاحظ أننا استخدمناها سابقا لتوسيط العناصر عموديا، ولكن لأن محور الترتيب اختلف الآن فهي ترتب العناصر أفقيا إلى الوسط) .testimonial-text:before, .testimonial-text:after { font-size: 48px; display: inline-block; padding: 0 16px; } .testimonial-text:before { content: "”"; } .testimonial-text:after { content: "“"; }قمنا هنا بإضافة علامتي تنصيص قبل وبعد الشهادة، قمنا بتكبير حجمهما ووضع بعض الفراغ بينهما وبين الشهادة. OwlCarousel (السكربت المستخدم من أجل عرض الشهادات) يعطينا أزرار التصفح بين الشهادات (على شكل نقاط) ولكنها بدون أيّ تأثير لذا سنقوم بذلك يدويا .owl-dots { text-align: center; } .owl-dot { height: 16px; width: 16px; border: 2px solid #E4523B; border-radius: 50%; display: inline-block; margin: 0 4px; } .owl-dot.active { background: #E4523B; }تحليلات الأرقاميحين وقت أرقام التحليلات، من أجل إطفاء التغيير وإضافة التركيز قمنا بإضافة خلفية لهم، هيكلة الجزء كانت كالتالي: <article id="analysicts-section"> <h1 class="section-title section-title__white">بعض الأرقام</h1> <div class="l-analysicts"> <div class="analysicts-item"> <div class="item-image"> <img src="img/articles.png" alt=""> </div> <h1 class="item-number">320</h1> <h2 class="item-title">مقالة نشرت</h2> </div> <div class="analysicts-item"> <div class="item-image"> <img src="img/groups.png" alt=""> </div> <h1 class="item-number">57</h1> <h2 class="item-title">مجموعة أنشئت</h2> </div> <div class="analysicts-item"> <div class="item-image"> <img src="img/users.png" alt=""> </div> <h1 class="item-number">+8000</h1> <h2 class="item-title">عضو مُسجل</h2> </div> <div class="analysicts-item"> <div class="item-image"> <img src="img/upload.png" alt=""> </div> <h1 class="item-number">450</h1> <h2 class="item-title">ملف رفع</h2> </div> </div> </article><!-- #analysicts-section -->منطق الهيكلة شبيهة بهيكلة مميزات التطبيق والشِفرة والتقسييم كانا بسيطان إلى أقصى حد: #analysicts-section { position: relative; padding: 48px 0; margin: 48px 0; background: url(../img/numbers-background.png) center center no-repeat; background-attachment: fixed; background-size: cover; } .l-analysicts { display: flex; justify-content: space-around; flex-wrap: wrap; } .analysicts-item { text-align: center; color: white; }جزء التحميل والمشاركةهذا الجزء بسيط إلى أقصى حد، عنوان بسيط مع زر للتحميل و 4 أزرار للدلالة على شبكات التطبيق الاجتماعية <article id="download-section"> <h1 class="section-title">إذا، هل قررت الانضمام؟</h1> <div class="cta-button"><img src="img/badge.png" alt=""></div> <div class="l-social-links"> <a href="" class="social-link"> <img src="img/facebook.png" alt="شارك في Facebook"> </a> <a href="" class="social-link"> <img src="img/twitter.png" alt="شارك في Twitter"> </a> <a href="" class="social-link"> <img src="img/pinterest.png" alt="شارك في Pinterest"> </a> <a href="" class="social-link"> <img src="img/google.png" alt="شارك في Google+"> </a> </div> </article> وبنفس البساطة أيضا .cta-button { margin: 36px 0; text-align: center; display: block; } .l-social-links { display: flex; justify-content: space-around; padding: 48px 0 64px; }Javascriptحان الوقت لإضافة Javascript إلى الصفحة، سنبدأ بإضافة Affix لروابط التصفح من أجل تثبيتهم. تنويه: في عالم مثالي كنا لنستخدم position:sticky لتقوم بالمهمة لنا، للأسف المتصفح الوحيد الذي يدعمها هو فيرفوكس، متصفح chrome كان يدعمها من قبل ولكنهم أزالوا الدعم في الوقت الحالي، لذا affix يعتبر أشبه بـِ polyfill. لدينا الشِفرة التالية التي سيتقوم بكل شيء لنا: $('.sticky-nav').affix({ offset: { top: $('.l-header').outerHeight() } }); $('.sticky-nav').on('affix.bs.affix', function () { $('.l-sticky-nav').addClass('fixed'); }); $('.sticky-nav').on('affixed-top.bs.affix', function () { $('.l-sticky-nav').removeClass('fixed'); });نقوم بتفعيل السكربت عبر إضافته إلى sticky-nav ثم نقوم بتحديد offset والذي يعني متى يتم تفعيل السكربت، نحن نريده أن يتفعل حالما يتم المرور عليه، نريد حساب كامل المسافة التي فوقه، وتلك المسافة ستكون حجم رأس الصفحة، لذا نضيفها عبر ()outerHeight التي تحسب الارتفاع الخارجي (من ضمنه padding). ثانيا نقوم بالاستماع إلى بعض الأحداث (events) والسكربت يوفر لنا 4 أحداث، سنستخدم اثنين فحسب، أول حدث ينطلق عندما يتم تفعيل السكربت مباشرة، وفي تلك اللحظة نضيف fixed إلى الحاوي من أجل أن يستغل المكان، تاليا نستمع للحدث الثاني والذي ينطلق حالما يتم إزالة السكربت (عند الرجوع للحالة العادية) في تلك اللحظة سنزيل fixed عن الحاوي ليعود إلى طبيعته. الآن سنتجه إلى scrollspy وهي تملك شروطا أكثر ازعاجا، مثل أنّها تعمل مع عناصر bootstrap فحسب لذا سنقوم ببعض التعديل في HTML و CSS أولا. <nav class="l-sticky-nav"> <ul class="nav sticky-nav"> <li class="nav-element"> <a href="#features-section" class="nav-element--link active"> <img src="img/equalizer.png" alt="" class="nav-element--image"> </a> </li> <li class="nav-element"> <a href="#testimonials-section" class="nav-element--link"> <img src="img/id.png" alt="" class="nav-element--image"> </a> </li> <li class="nav-element"> <a href="#analysicts-section" class="nav-element--link"> <img src="img/globe.png" alt="" class="nav-element--image"> </a> </li> <li class="nav-element"> <a href="#download-section" class="nav-element--link"> <img src="img/download.png" alt="" class="nav-element--image"> </a> </li> </ul><!-- sticky-nav --> </nav><!-- l-sticky-nav -->ما قمنا به هنا هو إضافة nav إلى الحاوي الثاني sticky-nav وقمنا بتغييره من div إلى ul ثم قمنا بتغيير العناصر nav-element من div إلى li. نقوم الآن بتعديل بعض CSS: .nav-element.active .nav-element--image, .nav-element:hover .nav-element--image { filter: grayscale(0); -webkit-filter: grayscale(0); }كل ما فعلناه هو أننا غيرنا nav-element–link إلى nav-element فحسب. الآن نستطيع استخدام الإضافة بشكل عادي تماما. $('body').scrollspy({ target: '.l-sticky-nav' });سوف نقوم بإضافتها إلى body هذا لأن عناصرنا (أقسام الصفحة) تقع مباشرة داخل وسم body وحددنا الهدف l-sticky-nav حيث يكون هو من يتم تعديل القيم فيه. تاليا سنقوم بإضافة carousel إلى الشهادات: if($('.testimonials-carousel').children().length > 1) { $('.testimonials-carousel').owlCarousel({ loop: true, nav: false, dots: true, rtl: true, items: 1 }) } ما نقوم به هو أننا نتفقد إن كان هنالك أكثر من شهادة، لأن OwlCarousel لا يعمل إذا كان هناك عنصر واحد في الصفحة (مشكلة على الأرجح سيتم إزالتها في النسخة الرسمية) بعد ذلك نقوم بتفعيله، وإعطائه بعض الخيارات، منها أننا لا نريد روابط للتقليب إلى اليمين واليسار، وأننا نريد نقاط التصفح فحسب، وأننا نريده أن يعمل من اليمين إلى اليسار (هذا السبب الوحيد الذي يدفعنا إلى استخدام النسخة 2.0 على النسخة الرسمية 1.3 وهو بسبب دعم اليمين إلى اليسار) وأننا نريد عنصرا واحدا كل مرة. هذا هو كامل شِفرة Javascript، لقد كانت بسيطة حقا: $(document).ready(function(){ $('.sticky-nav').affix({ offset: { top: $('.l-header').outerHeight() } }); $('.sticky-nav').on('affix.bs.affix', function () { $('.l-sticky-nav').addClass('fixed'); }); $('.sticky-nav').on('affixed-top.bs.affix', function () { $('.l-sticky-nav').removeClass('fixed'); }); $('body').scrollspy({ target: '.l-sticky-nav' }); if($('.testimonials-carousel').children().length > 1) { $('.testimonials-carousel').owlCarousel({ loop: true, nav: false, dots: true, rtl: true, items: 1 }) } })الخاتمةكانت هذه رحلة طويلة، انطلقنا من تعلم أساسيات ومكونات صفحات الهبوط إلى بناء واحدة لتطبيق وهمي، أول مقال ليس مخصصا للمطوريين أو المصممين بشكل خاص، أيّ مسوق أو مدير مشروع يستطيع أن يبني صفحة هبوط منتجه انطلاقا من ذلك الدليل على ورقة وإرساله لمطور ما، المقالان الآخيران كان أكثر تعمقا حيث في الواقع تطبيقا لما تعلمناه، الآن لكم المقدرة على إطلاق صفحات لمشاريعك، وجلب عملاء أكثر ومشتريين أكثر1 نقطة
-
تستخدِم أداة fsck هذا المجلَّد من أجل إصلاح الأعطاب في نظام الملفّات (نظام الملفّات Files system وليس العتاد Hardware). توجد معرّفات inode الخاصّة بالملفّات المفقودة في مجلّد lost+found. تستخدم `fsck` هذه المعرّفات في محاولة إصلاح الأعطاب. كونُ المجلّد فارغًا يعني ألّا أعطاب مُلاحظة في نظام الملفّات. يوجد عادة مجلّد lost+found لكلّ نظام ملفّات.1 نقطة
-
تُحيل هذه الأعداد إلى الفصل أو المقطع ضمن التّوثيق حيثُ توجد هذه الأوامر. يُمكن معرفة فصول التّوثيق عند تنفيذ الأمر man man. هذه الفصول هيّ: 1: برامج أو أوامر Shell.2: نداء للنّظام System call.3: دوّال مكتبة C.4: ملفّات خاصّة.5: صيّغ ملفّات واصطلاحات.6: ألعاب.7: متفرّقات.8: أدوات لإدارة النّظام.1 نقطة
-
بما أن العديد من الدروس المتعلقة بـِ Java وUbuntu تفترض وجود Java مُثبتة مُسبقا على النظام، فإن هذا المقال سيرشدك إلى تعلم تثبيت وإدارة إصدارات مختلفة من Java حتى يتسنى لك البدء في العمل، تتبع الدروس والمضي قدما. تثبيت JRE/JDK الإفتراضيهذا هو الخيار الأكثر سهولة والمنصوح به. هذه العملية ستثبت OpenJDK 6 على أبنتو 12.04 وسابقاتها وحتى على 12.10+ فسيُثبّتُ هذا OpenJDK 7 تثبيت جافا مع apt-get سهل للغاية. أولا، حدث مستودع الحزم: sudo apt-get updateثم، تأكد من أن جافا ليست مثبتة على الجهاز: java -versionإذا كانت مخرجات الأمر: "The program java can be found in the following packages"فهذا يعني أن جافا لم تُثبت بعد، لذلك طبق الأمر التالي: sudo apt-get install default-jreهذا الأمر سيثبتُ (Java Runtime Enviroment (JRE، إذا كنت تريد (Java Development Kit (JDK عوضا عن ذلك، والتي تكون ضرورية لترجمة (compile) تطبيقات Java (مثلا Apache Ant, Apache Maven, Eclipse و IntelliJ IDEA ) طبق الأمر التالي: sudo apt-get install default-jdkهذا كل ما تحتاجه من خطوات لتثبيت Java. جميع الخطوات القادمة اختيارية ويجب تطبيقها فقط عند الحاجة. تثبيت OpenJDK 7 (اختياري)لتثبيت OpenJDK 7 ، طبق الأمر التالي: sudo apt-get install openjdk-7-jreهذا الأمر يثَبّتُ (Java Runtime Environment (JRE. إن كنت ترغب بتثبيت (Java Development Kit (JDK عوضا عن ذلك فنفذ الأمر التالي: sudo apt-get install openjdk-7-jdkتثبيت Oracle JDK (اختياري)Oracle JDK هو JDK الرسمي؛ لكنه لم يعد مقدما من Oracle بشكل افتراضي لـ Ubuntu، لكن لا يزال بإمكانك تثبيته باستخدام apt-get. لتثبيت أي نسخة أولا نفذ الأوامر التالية: sudo apt-get install python-software-properties sudo add-apt-repository ppa:webupd8team/java sudo apt-get updateبعد ذلك، حسب النسخة المراد تثبيتها، نفذ أحد الأوامر التالية حسب النسخة المراد تثبيتها: Oracle JDK 6هذه نسخة قديمة لكنها لا زالت تُستعمَل في كثير من التطبيقات والأدوات، لذلك نذكرها هنا من باب العلم بالشيء: sudo apt-get install oracle-java6-installerOracle JDK 7sudo apt-get install oracle-java7-installerOracle JDK 8هذه آخر نسخة مستقرة لحد كتابة هذا الدرس. تم الإعلان عن الإطلاق بشكل عام في مارس 2014. هذا الرابط الخارجي عن Java 8 يمكن أن يساعدك لفهم الأمور بشكل جيد. sudo apt-get install oracle-java8-installerملاحظة: إذا حدث وأعطاك الأمر بعد مُدّة خطأً كالتالي (شخصيا، واجهتني المُشكلة، أظنّ أن السبب راجع إلى كوني أعيش في المغرب مع سرعة شبكة بطيئة): download failed Oracle JDK 8 is NOT installed. /usr/bin/dpkg returned an error code (1)لقد بحثت عن حلّ للمُشكلة ولكنّني لم أجد سوى حلّ بدائي وهو أن تعيد أمر التثبيت كلّما أعطاك هذا الخطأ (ستحتاج إلى تكرار الأمر 4 أو 5 مرّات لإكمال التحميل والتّثبيت بنجاح): sudo apt-get install oracle-java8-installerحيث ستكون المُخرجات كالتالي: 2 not fully installed or removed.هذا يعني أنّ الأمر الذي أدخلته سيستكمل التحميل ولن يحتاج إلى إعادته من جديد. إدارة Javaإذا كان لديك العديد من نسخ جافا المثبتة في الخادوم، يمكن اختيار النسخة الافتراضية، للقيام بذلك طبق الأمر التالي: sudo update-alternatives --config javaالمخرجات عادة ستكون كهذا إذا كنت تملك تثبتيتين (إذا كان لديك أكثر من ذلك، بالطبع ستكون المخرجات أكثر): There are 2 choices for the alternative java (providing /usr/bin/java). Selection Path Priority Status ------------------------------------------------------------ * 0 /usr/lib/jvm/java-7-oracle/jre/bin/java 1062 auto mode 1 /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/java 1061 manual mode 2 /usr/lib/jvm/java-7-oracle/jre/bin/java 1062 manual mode Press enter to keep the current choice[*], or type selection number: يمكنك الآن اختيار الرقم لاستخدامه كخيار افتراضي. هذه العملية يمكن فعلها كذلك بالنسبة لمترجم جافا (javarc): sudo update-alternatives --config javacستظهر نفس شاشة الاختيار السابقة ويجب استعمالها بنفس الطريقة. هذا الأمر يمكن تنفيذه لجميع الأوامر التي تملك تثبيتات مختلفة. في جافا، مثلاً: keytool ، javadoc و jarsigner ضبط متغير بيئة “JAVA_HOME” لضبط متغير بيئة JAVA_HOME ، والذي تحتاجه بعض البرامج، أولا عليك إيجاد مسار تثبيت جافا الخاص بك: sudo update-alternatives --config javaوالمخرجات تكون كالتالي: There are 2 choices for the alternative java (providing /usr/bin/java). Selection Path Priority Status ------------------------------------------------------------ * 0 /usr/lib/jvm/java-7-oracle/jre/bin/java 1062 auto mode 1 /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/java 1061 manual mode 2 /usr/lib/jvm/java-7-oracle/jre/bin/java 1062 manual mode Press enter to keep the current choice[*], or type selection number:مسار التثبيت هو كل من: /usr/lib/jvm/java-7-oracle /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-7-oracleأنسخ المسار من تثبيتك الذي تريده ثم عدل الملف etc/environment/: sudo nano /etc/environmentفي هذا الملف أضف السطر التالي (مغيرا مسار_التثبيت إلى ما نسخته): JAVA_HOME="مسار_التثبيت"هذا كاف لضبط متغير البيئة. الآن أعد تحميل هذا الملف: source /etc/environmentجرب الآن تطبيق الأمر: echo $JAVA_HOMEإذا كان المخرج مسارك، فمتغير البيئة قد ضُبط بنجاح. إذا لم يكن الأمر كذلك، المرجو التأكد من أنك اتبعت جميع الخطوات بشكل صحيح. ترجمة -وبتصرّف- للمقال: How To Install Java on Ubuntu with Apt-Get.1 نقطة
-
هذا يعتمد على نوعيّة وهيئة السّجلّات Logs الّتي تُريد استخراج عناوين IP منها. مثلا في سجلّاّت Apache يوجد عنوان IP في العمود الأوّل من كل سطر ضمن ملفّ السّجلّ. في هذه الحالة يُمكن استخراج عنوان IP عن طريق الأمر التّالي: cut -d ' ' -f 1 logFile > ips.txtيُستخدم أمر cut لاستخراج جزء من أسطر في ملف نصّي. الخيّار d- يُحدّد الفاصل بين الأعمدة، أي أنّ الأمر عندما يجد مسافة سيعتبر ما بعدها عمودا جديدًا. الخيّار f- يعني الحقل (العمود) أو الحقول التي نُريد الاحتفاظ بها من الملفّ. في حالة سجلّات Apache يوجد عنوان IP في العمود الأوّل، لذا نُحدّد الرّقم 1. logFile هو اسم الملّف الّي نُريد استخراج العناوين منه. نحتفظ بنتيجة تنفيذ الأمر في ملفّ باسم ips.txt يُمكن أيضًا استخدام grep وتعبير نمطي Regex لاستخراج عنوان IP كما يلي: grep -oE '.*([0-9]{1,3}[\.]){3}[0-9]{1,3}*'الخيّار o- لاستبقاء جزء السّطر الّذي يُوافق التّعبير النمطي فقط. توجد ملحوظة في الطّريقة الأخيرة. عادة يوجد إصدارُ المتصفّح في السجلّات، إن كان رقم الإصدار مكوَّنًا من 4 خانات فسيظهر محتوى السّطر الموجود بين عنوان IP ورقم إصدار البرنامج في النّتيجة. يُمكِن التّغلب على هذا الأمر باستبقاء أول مطابقة للتّعبير النمطي فقط في كلّ سطر، ولكن في هذه الحالة من الأفضل استخدام cut (على كلّ حال استخدامُ cut يستغل موارد أقلّ من الجهاز). مثال على الملحوظة الأخيرة (سطر من سجلّ Apache لديّ في المدوَّنة ) 197.241.75.122 - - [31/Mar/2015:10:49:02 -0600] "GET /2013/03/%D8%B1%D8%B3%D8%A7%D9%84%D8%A9-%D8%AE%D8%B7%D8%A3-grub-error-no-such-partition-grub-rescue/ HTTP/1.1" 304 174 "https://www.google.com/" "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) MxNitro/1.0.0.300 في آخر السّطر يوجد رقم إصدار مكوِّن في متصفّح المستخدِم (MxNitro/1.0.0.300). صيغة هذا الرّقم تُوافق هيئة عنوان IP ولكنّه ليس عنوان IP.1 نقطة