المحتوى عن 'عرض'.



مزيد من الخيارات

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المُحتوى


التصنيفات

  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • نصائح وإرشادات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • التجارة الإلكترونية
  • مقالات عامة

التصنيفات

  • PHP
    • Laravel
    • ووردبريس
  • جافاسكريبت
    • Node.js
    • jQuery
    • AngularJS
    • Cordova
  • HTML5
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • سي شارب #C
    • منصة Xamarin
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • برمجة أندرويد
  • لغة Swift
  • لغة R
  • سير العمل
    • Git
  • صناعة الألعاب
    • Unity3D
  • مقالات عامّة

التصنيفات

  • تجربة المستخدم
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
    • كوريل درو
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • مقالات عامّة

التصنيفات

  • خواديم
    • الويب HTTP
    • قواعد البيانات
    • البريد الإلكتروني
    • DNS
    • Samba
  • الحوسبة السّحابية
    • Docker
  • إدارة الإعدادات والنّشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • مقالات عامة

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • استسراع النمو
  • المبيعات

التصنيفات

  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • مقالات عامة

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
  • أندرويد
  • iOS
  • macOS
  • ويندوز

التصنيفات

  • شهادات سيسكو
    • CCNA
  • شهادات مايكروسوفت
  • شهادات Amazon Web Services
  • شهادات ريدهات
    • RHCSA
  • شهادات CompTIA
  • مقالات عامة

أسئلة وأجوبة

  • الأقسام
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة البرمجة
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات
    • أسئلة الشهادات المتخصصة

التصنيفات

  • ريادة الأعمال
  • العمل الحر
  • التسويق والمبيعات
  • البرمجة
  • التصميم
  • DevOps

تمّ العثور على 15 نتائج

  1. تعرّفنا في الدرس السابق على طريقة تثبيت إطار العمل Rails وبدأنا العمل على مشروعنا الأول وهو عبارة عن مدوّنة بسيطة، وقمنا بتشغيل الخادوم الخاص بإطار العمل. وفي هذا الدرس سنتعرّف على آلية عمل إطار العمل Rails من خلال مثال بسيط، ثم نشرع بعده ببناء مدونتنا البسيطة لنتعرف بصورة أكبر على العديد من المفاهيم التي يستند إليها هذا الإطار. آلية عمل إطار Rails سنتعرّف على آلية عمل إطار Ruby on Rails من خلال مثال بسيط نعرض فيه مجموعة من الكلمات في الصفحة الرئيسية لتطبيقنا، وللقيام بذلك سنحتاج إلى متحكّم Controller وعرض View. وظيفة المتحكّم هي استقبال الطلبات الواردة إلى التطبيق، وتربط المسارات Routes بين الطلبات والمتحكّمات. وغالبًا ما يكون هناك أكثر من مسار واحد لكل متحكّم، ويمكن للمسارات المختلفة أن تؤدّي إلى أحداث Actions مختلفة، ووظيفة الحدث هي جمع المعلومات اللازمة وتقديمها إلى العرض. أمّا وظيفة العرض فواضحة من اسمه، وهي عرض المعلومات التي حصل عليها من الحدث بصورة مقروءة للإنسان. من الضروري هنا الانتباه إلى أن عملية جمع المعلومات تتمّ ضمن المتحكّم وليس ضمن العرض، ومهمّة العرض الوحيدة هي عرض المعلومات. يستخدم إطار Rails لغة قوالب خاصّة في العروض تدعى eRuby (اختصار لـ Embedded Ruby) والتي تُعالج بواسطة دورة الطلب في Rails قبل أن تُرسل إلى المستخدم. سلنجأ إلى أداة المولّد generator لإنشاء متحكّم يحمل اسم Welcome يتضمّن حدثًا باسم index. اكتب الأمر التالي في سطر الأوامر: $ bin/rails generate controller Welcome index سيقوم Rails بإنشاء مسار وعدد من الملفات. create app/controllers/welcome_controller.rb route get 'welcome/index' invoke erb create app/views/welcome create app/views/welcome/index.html.erb invoke test_unit create test/controllers/welcome_controller_test.rb invoke helper create app/helpers/welcome_helper.rb invoke test_unit invoke assets invoke coffee create app/assets/javascripts/welcome.coffee invoke scss create app/assets/stylesheets/welcome.scss ما يهمّنا من هذه الملفات هما المتحكم والموجود في المسار app/controllers/welcome_controller.rb والعرض الموجود في المسار app/views/welcome/index.html.erb. افتح الملف app/views/welcome/index.html.erb في محرّر النصوص المفضّل لديك، واحذف محتوياته واستبدلها بالشيفرة التالية: <h1>Hello, Rails!</h1> بعد أن أنشئنا المتحكم والعرض يجب علينا إخبار Rails بالمسار الذي سيأخذ المستخدم إلى هذا العرض. نحن نرغب في حالتنا هذه أن يتم توجيه المستخدم إلى العرض عندما يتوجّه إلى العنوان http://localhost:3000، ولكن صفحة الترحيب تشغل هذا المسار في الوقت الحاضر. بعد ذلك يجب إخبار Rails بموقع الصفحة الرئيسية ليتمكّن من عرضها للمستخدم. افتح الملف config/routes.rb في محرّر النصوص: Rails.application.routes.draw do get 'welcome/index' # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end الشيفرة أعلاه موجودة في ملف المسارات والذي يتضمّن مدخلات DSL خاصّة (DSL اختصار لـ domain-specific language) والتي تخبر Rail بطريقة ربط الطلبات الواردة إلى التطبيق بالمتحكمات والأحداث. عدّل هذا الملف بالصورة التالية: Rails.application.routes.draw do get 'welcome/index' root 'welcome#index' end من خلال السطر root 'welcome#index' يربط إطار العمل Rails الطلبات الواردة إلى المسار الرئيسي في التطبيق مع الحدث index في المتحكّم Welcome، أما السطر get 'welcome/index' فيربط من خلاله Rails الطلبات الواردة إلى العنوان http://localhost:3000/welcome/index بنفس الحدث ونفس المتحكّم، وقد تمّ إنشاء هذه الشيفرة من قبل أداة المولّد. والآن شغّل الخادوم الخاص بـ Rails ثمّ توجّه في المتصفّح إلى العنوان http://localhost:3000، وستشاهد عبارة “Hello, Rails!” الموجودة في ملف app/views/welcome/index.html.erb وهذا يعني أن هذا المسار قد توجّه فعلًا إلى الحدث index في المتحكم Welcome والذي قام بدوره بتصيير العرض بصورة صحيحة. البدء بإنشاء المدوّنة بعد أن تعرّفنا على المتحكّمات والأحداث والعروض، لنبدأ العمل على مدوّنتنا. سننشئ الآن ما يسمى في إطار العمل Rail بالمورد resourse، والمورد هو مصطلح يعبّر عن مجموعة من العناصر المتشابهة، مثل المقالات، الأشخاص أو الحيوانات. ويمكن إنشاء create وقراءة read وتحديث update وإلغاء destroy العناصر في المورد، وتسمى هذه العمليات بعمليات CRUD. يقدّم Rails تابعًا باسم resources يمكن استخدامه للإفصاح عن مورد بنمط REST القياسي. يجب إضافة مورد المقالة إلى ملف config/routes.rb وكما يلي: Rails.application.routes.draw do get 'welcome/index' resources :articles root 'welcome#index' end والآن إن قمت بتنفيذ الأمر bin/rails routes فستشاهد جميع المسارات الخاصّة بجميع الأحداث التي تتّصف بنمط REST. سنتعرّف على معنى عمود prefix وبقية الأعمدة في وقت لاحق، ولكن لاحظ أنّ Rails قد خمّن صيغة المفرد (article) واستخدمها في السياق الصحيح. $ bin/rails routes Prefix Verb URI Pattern Controller#Action articles GET /articles(.:format) articles#index POST /articles(.:format) articles#create new_article GET /articles/new(.:format) articles#new edit_article GET /articles/:id/edit(.:format) articles#edit article GET /articles/:id(.:format) articles#show PATCH /articles/:id(.:format) articles#update PUT /articles/:id(.:format) articles#update DELETE /articles/:id(.:format) articles#destroy root GET / welcome#index سنعمل الآن على إضافة خاصيتي إنشاء المقالات وعرضها، وستكون الاستمارة Form المسؤولة عن ذلك بالشكل التالي: قد تبدو الاستمارة بدائيًّة ولكنّها كافية في الوقت الحاضر، وسنعمل على تحسين مظهرها فيما بعد. إنشاء المتحكّمات والمسارات اللازمة في البداية يجب اختيار المسار الذي سيوجّه المستخدم إلى استمارة إنشاء المقالة الجديدة، وسنستخدم المسار /articles/new للقيام بهذه المهمّة، بعدها يصبح بميسور التطبيق أن يتلقّى الطلبات على هذا المسار. توجّه الآن في متصفحك إلى الرابط http://localhost:3000/articles/new وستتلقّى الخطأ التالي: يحدث هذا الخطأ لأنّ المسار بحاجة إلى متحكّم يرسل إليه الطلب؛ لذا سنقوم بإنشاء متحكّم باسم ArticlesController، وذلك من خلال تنفيذ الأمر التالي: $ bin/rails generate controller Articles افتح الملف الذي قمت بإنشائه app/controllers/articles_controller.rb وسترى متحكّمًا فارغًا: class ArticlesController < ApplicationController end المتحكّم عبارة عن صنف Class موروث من ApplicationController وسنقوم بتعريف التوابع ضمن هذا الصنف والتي ستمثل الأحداث الخاصّة بهذا المتحكم، وهذه الأحداث هي المسؤولة عن تنفيذ عمليات CRUD على المقالات الموجودة في تطبيقنا. إن أعدت تحميل الصفحة ستتلقّى خطأً جديدًا: يشير هذا الخطأ إلى عدم قدرة Rails على إيجاد الحدث new ضمن المتحكّم ArticlesController الذي قمنا بإنشائه للتوّ. وهذا عائد إلى أنّ المتحكّمات تكون فارغة عند إنشائها إلا إذا حدّدنا الأحداث المطلوبة خلال عملية إنشاء المتحكّم. ولتعريف حدث جديد بصورة يدوية، سنحتاج فقط إلى تعريف تابع جديد ضمن المتحكم. افتح الملف app/controllers/articles_controller.rb وضمن الصنف ArticlesController عرّف تابعًا جديدًا وكما يلي: class ArticlesController < ApplicationController def new end end والآن أعد تحميل الصفحة في المتصفّح وستتلقّى خطأً آخر: يظهر هذا الخطأ لأنّ Rails يتوقّع أنه يجب أن تمتلك الأحداث الصرفة المشابهة لهذا الحدث عروضًا ترتبط معها لعرض المعلومات التي تتضمنها، ونظرًا لعدم وجود أي عرض مرتبط بهذا الحدث، أطلق Rails هذا الخطأ. لنطّلع على رسالة الخطأ الكاملة: لنستعرض النص السابق سريعًا، ونفهم مضمونه بصورة جيدة. يحدّد الجزء الأول من نصّ الخطأ القالب المفقود، وفي هذه الحالة القالب المفقود هو articles/new. يبدأ Rails بالبحث عن هذا القالب، وإن لم يفلح في العثور عليه فإنه يحاول تحميل قالب يدعى application/new وذلك لأنّ المتحكّم ArticleController هو صنف موروث من المتحكّم ApplicationController. يتضمن الجزء الثاني من رسالة الخطأ request.formats والذي يحدّد صيغة القالب الذي سيتم عرضه كاستجابة للطلب الذي تلقّاه التطبيق، وقد تم اختيار صيغة text/html لأنّنا طلبنا هذه الصفحة بواسطة المتصفح؛ لذا يبحث Rails عن قوالب HTML. أما request.variant فيحدد طبيعة الأدوات المادّية physical devices التي سيتم تقديمها مع الطلب وتساعد Rails في تحديد القالب الذي سيستخدمه في الاستجابة، وهو فارغ نظرًا لعدم توفّر المعلومات. أبسط قالب يمكن أن يعمل في هذه الحالة هو القالب الموجود في المسار app/views/articles/new.html.erb. هذه اللاحقة مهمّة للغاية: فالجزء الأول من اللاحقة (.html) يعبّر عن صيغة القالب، أمّا الجزء الثاني (.erb) فيمثّل المعالج handler الذي سيتم استخدامه في تصيير القالب. يحاول Rails البحث عن قالب يحمل الاسم articles/new ضمن المجلد app/views. يجب أن تكون صيغة هذا القالب هي HTML حصرًا، وسيكون erb المعالج الافتراضي لـ HTML. يستخدم Rails عددًا من المعالجات مثل: builder والمستخدم في إنشاء قوالب XML، وcoffee الذي يستخدم لغة CoffeeScript لبناء قوالب JavaScript. بما أنّنا نرغب في بناء استمارة HTML جديدة فسنستخدم لغة ERB والتي تتيح لنا تضمين لغة Ruby في HTML. إذًا سيكون اسم القالب articles/new.html.erb وسيكون ضمن المجلد app/views الخاص بالتطبيق. أنشئ ملفًّا جديدًا باسم new.html.erb في المسار app/views/articles وأضف إليه ما يلي: <h1>New Article</h1> أعد تحميل الصفحة وستلاحظ ظهور العنوان في رأس الصفحة، وهذا يعني أن هناك تناغمًا تامًّا بين كلّ من المسار والمتحكم والحدث والعرض. الاستمارة الأولى سنستخدم منشئ النماذج form builder لإنشاء الاستمارة الأولى في هذا القالب. يمكن استخدام منشئ النماذج الرئيسي في Rails باستخدام التابع المساعد form_for. أضف الشيفرة التالية في الملف app/views/articles/new.html.erb: <%= form_for :article do |f| %> <p> <%= f.label :title %><br> <%= f.text_field :title %> </p> <p> <%= f.label :text %><br> <%= f.text_area :text %> </p> <p> <%= f.submit %> </p> <% end %> أعد تحميل الصفحة وستلاحظ ظهور نفس الاستمارة التي عرضناها في المثال السابق. كما تلاحظ فإنّ بناء الاستمارات في Rails أمر سهلٌ للغاية. عندما نستدعي التابع form_for فإننا نمرّر إليه عنصرًا يحدّد الهدف من هذه الاستمارة، والهدف في حالتنا هذه هو :article. يُستخدم الكائن FormBuilder والذي مثّلناه بـ f لبناء عنصري label وحقلي نصوص text fields لكلّ من عنوان المقال ومتنها. وفي النهاية استدعينا التابع submit لإنشاء زرّ اﻹرسال الخاصّ بالاستمارة. ولكن تعاني هذه الاستمارة من مشكلة صغيرة. لو تفحّصت شيفرة HTML التي تم توليدها من خلال الشيفرة السابقة فستلاحظ أن خاصية action التابعة للاستمارة تشير إلى المسار articles/new وهذا المسار هو نفسه الذي يقودنا إلى هذه الصفحة، والمفروض أن يستخدم هذا المسار لعرض استمارة إنشاء مقالة جديدة لا غير. إذًا يجب أن تستخدم الاستمارة مسارًا آخر، ويمكن القيام بذلك بسهولة من خلال استخدام الخيار :url في form_for. عادة ما يحمل الحدث المسؤول عن إرسال مقال جديد اسم “create”، لذا يجب توجيه الاستمارة إلى هذا الحدث. عدّل السطر الذي يتضمن form_for في ملف app/views/articles/new.html.erb كما يلي: <%= form_for :article, url: articles_path do |f| %> في هذا المثال تم تمرير الدالة المساعدة articles_path إلى الخيار :url، ولنتعرّف على نتيجة هذا التعديل سنلقي نظرة على مخرجات الأمر bin/rails routes في سطر اﻷوامر: $ bin/rails routes Prefix Verb URI Pattern Controller#Action articles GET /articles(.:format) articles#index POST /articles(.:format) articles#create new_article GET /articles/new(.:format) articles#new edit_article GET /articles/:id/edit(.:format) articles#edit article GET /articles/:id(.:format) articles#show PATCH /articles/:id(.:format) articles#update PUT /articles/:id(.:format) articles#update DELETE /articles/:id(.:format) articles#destroy root GET / welcome#index توجّه الدالة المساعدة articles_pat الاستمارة إلى نمط URI المرتبط لاحقة articles وسيرسل الاستمارة - تلقائيًا - طلبًا من نوع POST إلى المسار، والذي يرتبط بالحدث create التابع للمتحكّم ArticlesController. بعد أن أنشأنا الاستمارة وعرّفنا المسار المرتبط به، أصبح باﻹمكان تعبئة حقول الاستمارة والضغط على زرّ اﻹرسال لبدء عملية إنشاء مقال جديد، ولكن عند إرسال المقال ستتلقّى الخطأ المتوقَّع التالي: علاج هذا الخطأ بسيط وهو إنشاء الحدث create ضمن المتحكّم ArticlesController. إنشاء المقالات سنقوم الآن بتعريف الحدث create ضمن صنف ArticlesController في الملف app/controllers/articles_controller.rb بعد الحدث new وكما يلي: class ArticlesController < ApplicationController def new end def create end end إن أعدت إرسال الاستمارة مرة أخرى فستلاحظ عدم حدوث أي تغيير في الصفحة. لا تقلق، هذا الأمر عائد إلى أنّ Rails يعيد الاستجابة “204 No Content” لأي حدث لا يحدّد الاستجابة المطلوبة. وقد أضفنا الحدث create دون تحديد الاستجابة المطلوبة منه، وهي في حالتنا هذه، إنشاء مقالة جديدة في قاعدة البيانات. عند إرسال الاستمارة يتم إرسال الحقول الخاصة بها إلى Rails على هيئة معاملات parameters، يمكن الإشارة إليها في الأحداث التابعة للمتحكّم وذلك لإنجاز مهّمة ما، ولتعرف كيف تبدو هذه المعاملات عدّل حدث create بالصورة التالية: def create render plain: params[:article].inspect end يأخذ التابع render هنا جدول تقطيع Hash بسيط مع المفتاح :plain والقيمة هي تابع params [:article].inspect. توابع params هي الكائن الذي يمثّل المعامل (أو الحقل) المأخوذ من الاستمارة. ويعيد تابع params كائن من نوع ActionController::Parameters والذي يتيح لنا الوصول إلى مفاتيح جدول التقطيع من خلال السلاسل النصّيّة Strings أو الرموز Symbols. وفي حالتنا هذه، فإن المعاملات المهمّة هي المعاملات المأخوذة من الاستمارة. لتوضيح عمل توابع params، إليك المثال التالي: في عنوان URL هذا: http://www.example.com/?username=dhh&email=dhh@mail.com فإن params[:username] تحمل القيمة “dhh” و params[:email] تحمل القيمة “dhh@mail.com”. والآن أعد إرسال الاستمارة مرة أخرى وستشاهد شيئًا مماثلًا لما يلي: <ActionController::Parameters {"title"=>"First Article!", "text"=>"This is my first article."} permitted: false> يعرض هذا الحدث المعاملات الخاصة بالمقالة والمأخوذة من الاستمارة، ولكن ليس هذا ما نريده بالضبط، فنحن نشاهد المعاملات ولكنّها لا تقدّم أي فائدة تذكر في حالتها هذه. في الدرس القادم سنتعرّف على النماذج Models في إطار العمل Rails وسنستخدمها في إضافة مقالة جديدة إلى قاعدة البيانات التابعة للتطبيق. المصدر: توثيقات Ruby on Rails.
  2. لا شك أنك تعي أن عملك الحر يعني أنك في بحر من المنافسة مع أقرانك، ويلزمك الكثير من الوقت والتدريب والتفرغ من أجل الوصول إلى المستوى الذي تريد، فلن يقرأ أحد من العملاء شيئًا من رسائلك إن كانت مشابهة لغيرها من أكوام الرسائل في صناديق رسائلهم. ولقد قضيت سنوات عديدة في إتقان أسلوب العرض الذي أقدمه، وعرفت جيدًا ما يتطلبه الأمر كي تكتب عرضًا يحفز عميلك المحتمل لقراءته وقبوله، ويبني مصداقية لك، ويريه أنك أفضل من يقوم بالوظيفة التي يريدها. وقد استخدمت أسلوبي ذلك قبل أسبوع في الفوز بعقدين جديدين مع عميلين لكتابة مقالات لهما، في مقابل 500$ للمقالة الواحدة. فلا تستهن أبدًا بأهمية تلك الرسالة الأولى التي ترسلها إلى عميل محتمل، فهي التي تضع القواعد لعلاقتكما الجديدة، فمن المهم أن تبعث تلك الرسالةُ قيمة فور النظر إليها، وتجذب انتباه العميل من اللحظة الأولى. وقد استخدمت باستمرار رسائل باردة مكتوبة بعناية للفوز بعملاء جدد لعملي الحر، فهي طريقة فعالة للغاية، خاصة حين تكون في بداية مسيرتك المهنية كمستقل، أو تسعى مثلي للحصول على عملاء جدد. ولتعلم أنه يلزمك فهم عميق لكيفية تفاعل الناس مع صناديق رسائلهم، وما الذي يجعلهم يقرأون تلك الرسائل أو يتفاعلون معك أنت وليس مع منافسك. غير أن في الأمر صعوبة بسبب أن لديك وقتًا محدودًا لصنع ذلك الانطباع الأول قبل أي أحد آخر. ذلك أن الشخص العادي يستغرق في المتوسط نحو 100 مللي ثانية من أجل تكوين انطباع أولي عن شخص آخر، وذلك صحيح أيضًا لمن يستقبلون رسائل عروضك، فهم يكتفون بذلك الوقت الضئيل كي يحددوا ما إذا كانت رسالتك تستحق وقتهم أم أنها تبدو رسالة سبام من مظهرها الخارجي، فتوقع حينها أنهم لن يقرؤونها أبدًا. وإليك الآن خطواتي الأربعة التي ستعينك على كتابة رسائل بأسلوب يضمن تفاعل العملاء معها، وتعطيك أفضل الانطباعات الأولى: 1. اجعل عرضك شخصيًا خذ وقتك في البحث عن خلفية العميل الذي تريد أن تتواصل معه قبل أن تبدأ فعليًا في مراسلته، وانظر هل يمكنك أن تعرف أي شيء عن اهتماماته الشخصية، أو ربما تفاصيل مهمة عن عمله من تصفح موقعه وحساباته على الشبكات الاجتماعية؟ لقد بدأت إحدى أفضل علاقاتي مع عميل بهذا العنوان "حب مشترك للحيوانات والتسويق بالمحتوى"، ذلك أني استغرقت وقتًا كافيًا في البحث في خلفية ذلك العميل، واكتشفت أنه ينشر الكثير من صور الكلاب على إنستجرام (والتي كنت أعجب بها بالمناسبة)، وبناءً عليه فقد استطعت التواصل معه على مستوى شخصي أكثر، بدلًا من الأسلوب الرسمي المتحفظ في التواصل. ولهذا فإني أنصح باستخدام الأسماء الأولى في الرسائل البريدية مع عملائك، فإن استخدام ألقاب مثل السيد أو السيدة يصنع على الفور حواجز من الرسمية والتحفظ بينكما، ولن تجد ما يظهر الارتباط بينكما قدر التواصل على المستوى الشخصي. 2. أوف بما تعِدْ إن فتح عميل لرسالتك شيء والإبقاء على اهتمامه وإقناعه بك أثناء قراءته للرسالة شيء آخر تمامًا، لذلك تأكد أن أول جمل في رسالتك وأول فقرة تحتوي على معلومات وتفاصيل كافية لجعله يستمر بالقراءة. ربما أشياء مثل إشارة سريعة إلى الطريقة التي وصلت إليه بها، وتنبيه أنك قد أعددت خطة بالفعل من أجله، وإحصاءات أو مثال عن مشروع مشابه قمت به في السابق (أرفق رابطًا له)، كل تلك أمور ذات أولوية لبناء زخم كافٍ لزيادة فرصتك في الفوز بذلك العميل. 3. اجعل عرضك موجزًا وبليغًا لم أستخدم أبدًا أكثر من ثلاث فقرات في رسائل عروضي إلى العملاء المحتملين، ذلك أني أعرف أن لدى أغلبنا دورة اهتمام قصيرة المدى بسبب طريقة استخدامنا لتطبيقات المحادثة والرسائل. ويميل العملاء حين يتعلق الأمر بالتوظيف إلى تخطي كلمات الرسالة إلى الأجزاء التي يريدونها، أو التي يعلمون أنها تفيدهم. بالتالي فإن إبقاء رسائلك قصيرة وبليغة في نفس الوقت سيجنبك إغراق العميل الذي تحاول الفوز بمشروعه بالمحتوى الذي تحشوه في رسالتك. فلتجهز رسالتك بحيث يسهل عليه قراءتها، كألا تستخدم فقرات أطول من 3-4 أسطر، وتفصل كلماتك في نقاط نظيفة ومرتبة. وكذلك، تجنب الجمل الطويلة ما استطعت، وهذب مسوَّدتك لتصل إلى الحد الأدنى من الكلمات دون الإخلال بجودة الرسالة ومدى تأثيرها على العميل. 4. وطِّد دعائم الثقة والمصداقية اعلم أن الانطباع الأول غالبًا ما يبقى في ذهن العميل، لذا فمن الأفضل أن تنجح في مد جسور من الثقة بينكما في أسرع وقت ممكن. واعلم كذلك أن عرضك يحتاج أن تظهر للعميل به أنك خبير بما تقدمه، وسابق لمن حولك في مجالك، كي تقنعه أنك أهل للعمل على مشروعه. لكن، احذر أن تكثر من الإطناب، أو المحاولة المبالغ فيها كي تبدو أكبر من قيمتك، ودع عملك يتحدث عن نفسه بدلًا من ذلك، عملك الذي يفترض أن تكون قد وضعت رابطًا أو عدة روابط إليه. ولا تنسى وضع دعوة لعميلك أن يتخذ إجراءً في آخر الرسالة، فكر ما الذي تريده من عميلك أن يفعله بعد قراءة الرسالة، واكتب شيئًا حول الأمر. إنني أنهي رسائل عروضي مثلًا بشيء كهذا "رجاءً أخبرني إن كانت لديك بضع دقائق نتحدث فيها سويًا قليلًا هذا الأسبوع". إن مثل تلك الجملة تظهر أني مستعد للبدء مباشرة في العمل. وتأكد أن تقدم قيمة في كل مرة تتواصل فيها مع عميلك، أعني أن تبتعد عن مجرد سؤاله هل سيقبل عرضك أم لا، وقدم له بدلًا من ذلك بعض التفاصيل عن الخطة التي بدأت بالفعل في وضع هيكلها العام من أجله، فإظهار أنك مستعد للاستثمار في عمله حتى قبل أن يتم اختيارك للمشروع يميزك بلا شك عن منافسيك، ويزيد من فرصتك في الفوز بالعميل. ترجمة –بتصرف- للمقال How to write an effective pitch for new freelance clients لصاحبه Ryan Robinson حقةق الصورة البارزة محفوظة لـ Vecteezy
  3. في الدروس السابقة تعرّفنا على OneNote وكيفية استخدامه لحفظ أنواع كثيرة من الملاحظات وكيفية تنظيمها في دفاتر الملاحظات، المقاطع، والصفحات. وبما أنّ الصفحات هي الجزء الأساسي الذي ستضيف ملاحظاتك عليه وترتّبها، تتوفر مجموعة من الأدوات والخصائص للتحكّم في طريقة عرض الصفحات وتغيير إعدادها لتسهيل قراءة المعلومات أو إضافتها. يمكن الوصول إلى جميع الأوامر الخاصة بطريقة عرض الصفحة أو إعدادها من تبويب View. الطريقة الافتراضية لعرض الصفحات هي طريقة العرض العادية Normal View وسنستعرض كيفية تغييرها إلى طرق العرض الأخرى وكيفية استخدام خيارات إعداد الصفحة. Full Page View يعمل هذا الخيار على توسيع أبعاد الصفحة إلى أقصى حدّ ممكن بجعلها تملأ الشاشة (أي وضع ملء الشاشة). ويمكنك استخدامه عندما تصبح الصفحة مزدحمة بالعناصر وترغب في توفير المزيد من المساحة لترتيبها. يتم تشغيل هذا الوضع بالنقر على أمر Full Page View من تبويب View (أو بطريقة مختصرة بواسطة النقر على زر السهمين المتعاكسين في زاوية الصفحة العليا اليمنى): عند تشغيل وضع ملء الشاشة يتم إخفاء كل ما حول حدود الصفحة، كتبويبات الأدوات، تبويبات المقاطع، جزء الصفحات، وغيرها، مع الإبقاء على قائمة منسدلة في الأعلى للتنقّل بين المقاطع ودفاتر الملاحظات: يمكنك إظهار تبويبات الأدوات أثناء تشغيل وضع ملء الشاشة بالنقر على النقاط الثلاثة في الأعلى. أمّا للعودة إلى طريقة العرض العادية فانقر على زر السهمين المتعاكسين من جديد: Dock to Desktop يعمل هذا الخيار على تصغير نافذة OneNote إلى حد معيّن وتثبيته على أحد جوانب سطح المكتب، مما يتيح لك إمكانية فتح برامج أخرى والعمل عليها واستعراض ملاحظاتك في نفس الوقت. وبهذه الطريقة أيضًا يمكنك إضافة محتوى إلى صفحات OneNote عن طريق السحب والإفلات. لتشغيل طريقة العرض هذه انقر على أمر Dock to Desktop من تبويب View: ستلاحظ أنّ نافذةOneNote المصغّرة ستبّقى مثبّتة في نفس المكان على الشاشة وبمستوى فوق جميع النوافذ التي ستفتحها. للعودة إلى طريقة العرض العادية، انقر على السهمين المتعاكسين في الجزء العلوي من نافذة OneNote المصغرة: ملاحظة: بإمكانك إضافة الخيار Dock to Desktop إلى شريط أدوات الوصول السريع بالنقر عليه بزر الفأرة الأيمن واختر Add to Quick Access Toolbar: تعديل إعدادات الصفحة في مجموعة Page Setup تتوفر المزيد من الخيارات للتحكم في تخطيط الصفحة ومظهرها. تغيير اللون اللون الافتراضي لخلفية صفحات OneNote هو الأبيض، لكن إذا كنت تفضّل لونًا ثانيًا، بإمكانك الاختيار من مجموعة الألوان في قائمة Page Color: انقر على اللون المرغوب لتطبيقه، وإذا أردت العودة إلى اللون الافتراضي انقر على No Color. تسطير الصفحة تسطير الصفحة وإظهار خطوط الشبكة من الخيارات المفيدة التي تساعدك على ترتيب العناصر ومحاذاتها في الصفحة. فإذا أردت إضافة سطور للصفحة، انقر على Rule Lines واختر التباعد المرغوب للسطور من مجموعة Rule Lines: أمّا لإظهار خطوط الشبكة فانقر على Rule Lines واختر حجم الشبكة المرغوب من مجموعة Grid Lines، علمًا أنّه لا يمكن تطبيق خياري التسطير وخطوط الشبكة معًا في نفس الوقت: إخفاء عنوان الصفحة إذا كنت تفضّل إزالة عنوان الصفحة وما يرافقه من معلومات الوقت والتاريخ واستغلال المساحة التي يشغلها لإضافة الملاحظات انقر على Hide Page Title: سيظهر لك مربّع حوار لتأكيد رغبتك في إزالة العنوان، انقر على Yes للمواصلة: للتراجع عن إزالة العنوان اضغط على مفتاحي Ctrl+ Z من لوحة المفاتيح، أو انقر مجددًا على أمر Hide Page Title ثم قم بإدخال العنوان. حجم الورقة يتضّمن أمر Paper Size خيارات أخرى للتحكّم في حجم الورقة، اتجاهها (أفقي أو عمودي)، اتجاه الصفحة (من اليمين إلى اليسار أو بالعكس)، الهوامش، وغيرها. ويمكن الوصول إلى هذه الخيارات من جزء Paper Size الذي يظهر عند النقر على أمر Paper Size: تتوفر في قائمة Size أغلب الأحجام القياسية، اختر الحجم المرغوب ثم حدّد اتجاه الورقة من قائمة Orientation. ومن الخيارات في قسم Print Margins يمكنك التحكّم في أبعاد هوامش الصفحة، وهذه تظهر عند الطباعة فقط. أما من قائمة Page body فيمكنك تحديد اتجاه الصفحة من اليمين إلى اليسار أو بالعكس. ملاحظة: عند إجراء أي تغيير على إعدادات الصفحة فإنّه سيُطبّق على الصفحة الحالية فقط. إلى هنا نصل إلى نهاية درسنا. في الدرس القادم سنتعلّم طريقة تصدير، مشاركة وطباعة ملاحظات OneNote.
  4. بعد أن تعرفنا في الدرس الأول على طريقة تثبيت Django وإنشاء مشروعنا الأول فيه، سنشرع في هذا الدرس في إنشاء تطبيقنا الأول والذي سيكون عبارة عن موقع بسيط للاقتراعات يتكون من قسمين: القسم الأول: واجهة يمكن للمستخدم أن يطلع من خلالها على الأسئلة المطروحة واختيار الإجابة التي يرغب فيها. أما القسم الثاني: لوحة تحكم يمكن من خلالها إضافة الأسئلة وتعديلها وحذفها وإضافة الأجوبة وغير ذلك من الأمور. المشاريع Projects والتطبيقات Applications قبل أن ندخل في تفاصيل إنشاء تطبيق الاقتراعات، لا بأس في الحديث بشكل موجز عن مفهومي "المشروع" Project و"التّطبيق" Application في Django. يمثّل المشروع تطبيق الويب الذي يتم إنشاؤه بواسطة Django، ويتم تعريفه من خلال ملف الإعدادات Settings، فكما رأينا في الدرس السابق فبعد تنفيذ الأمر: django-admin startproject mysite تم إنشاء حزمة بايثون تحتوي على ملفات settings.py و urls.py و wsgi.py، وعادة ما تتوسع هذه الحزمة بإضافة المزيد من الملفات مثل ملفات CSS والقوالب وما إلى ذلك من الأمور التي لا تكون مرتبطة بتطبيق معيّن. وعادة ما يكون مجلّد المشروع هذا (المجلد الذي يحتوي على الملف manage.py) حاويًا للتطبيقات التي يتم إنشاؤها بشكل مستقل، وهذه التطبيقات ما هي إلا حزم بايثون تعمل على تقديم بعض الخصائص وتؤدي بعض المهام، ويمكن استخدام هذه التطبيقات في مشاريع متعددة، وهذا ما يسمى بمبدأ قابلية إعادة الاستخدام re-usability. إنشاء تطبيق الاقتراعات ملاحظة: ابتدءًا من هذا الدرس فإن عبارة "مجلد المشروع" تعني المجلد الذي يحتوي على ملف manage.py. توجّه في سطر الأوامر إلى مجلد المشروع ثم اكتب الأمر التالي: python manage.py startapp polls يمكن الحصول على نفس النتيجة من خلال الأمر التالي: django-admin startapp polls بعد تنفيذ الأمر ستجد أنّ إطار العمل قد أنشأ مجلدًا جديدًا يحمل الاسم polls، ويتضمن عددًا من الملفات نستعرضها بشكل مختصر: init__.py__: هذا الملف مشابه للملف الموجود في مجلد المشروع، وهو ملف فارغ يعني وجوده أن هذا المجلد هو حزمة من حزم بايثون. admin.py: يمكن من خلال هذا الملف إدارة وتخصيص لوحة التحكم والتي تأتي جاهزة مع التطبيق. apps.py: يمكن من خلال هذا الملف إعداد التطبيق configuration لاستخدامه في مشاريع أخرى. models.py: سيتضمن هذا الملف النماذج التي يتعامل التطبيق معها، والتي تكون مسؤولة عن إنشاء جداول قواعد البيانات. tests.py: يمكن من خلال هذا الملف إجراء الاختبارات Tests على التطبيق. views.py: تضاف في هذا الملف العروض المسؤولة عن تحديد البيانات والمعلومات التي سيتم عرضها على المتصفح، وهي كذلك صلة الوصل بين المسارات والقوالب. مجلد migrations: سيستقبل هذا المجلد الملفات الناشئة عن عملية تهجير قاعدة البيانات. إعدادات المشروع يحتوي مجلد المشروع على ملف الإعدادات settings.py، وهو عبارة عن ملف بايثون يحتوي جميع الإعدادات الخاصة بالمشروع، وسنستعرض بعض محتويات هذا الملف بشكل موجز. BASE_DIR: متغير نصّي يقدّم مسار المجلد الأساسي للمشروع، ويمكن الاستفادة من هذا المتغير في تحديد مسارات المجلدات التي تحتوي على القوالب أو الملفات الساكنة وغيرها، وسنتعرف على طريقة استخدامه عند الحديث عن القوالب. SECRET_KEY: عبارة عن سلسلة نصية من حروف ورموز عشوائية يمكن الاستفادة منها في حماية التطبيق. DEBUG: متغير من نوع bool، ويمكن من خلاله التحكم في وضع التنقيح Debugging، حيث تظهر معلومات مفيدة عند حدوث الأخطاء، ولكن ينصح بتغيير قيمته إلى False عند نقل المشروع إلى بيئة الإنتاج. INSTALLED_APPS: عبارة عن قائمة تتضمن التطبيقات التي سيضمها المشروع الحالي، ويمكنك أن تلاحظ وجود عدد من التطبيقات المثبتة بشكل مسبق، مثل إدارة لوحة التحكم admin، والاستيثاق auth، والجلسات sessions وغيرها. TEMPLATES: عبارة عن قائمة تتضمن إعدادات القوالب المستخدمة في المشروع، وما يهمنا فيها هو العنصر DIRS والذي يتم من خلاله تعيين المسارات التي تحتوي على ملفات القالب. DATABASES: قائمة أخرى مسؤولة عن تحديد المعلومات اللازمة للتعامل مع قواعد البيانات، وسنتطرق إليها عند الحديث عن النماذج Models والاتصال بقواعد البيانات. LANGUAGE_CODE: يمكن من خلال هذا المتغير تحديد لغة واجهة لوحة التحكم، والإعداد الافتراضي هنا هو اللغة الإنكليزية، ولكن Django يدعم العديد من اللغات ومن ضمنها العربية، وإن كنت ترغب في استخدام اللغة العربية في عرض عناصر لوحة التحكم، فيمكنك تغيير قيمة هذا المتغير بالشكل التالي: LANGUAGE_CODE = 'ar' TIME_ZONE: يمكن من خلال هذا المتغيير تعيين المنطقة الزمنية التي سيستخدمها Django في دوال الوقت والتاريخ. ويمكن استبدال هذه القيمة حسب الرغبة. STATIC_URL: في هذا المتغير يتم تحديد مسار المجلد الذي يحتوي على الملفات الساكنة وهي ملفات CSS و Javascript والخطوط والصور وغيرها. كتابة العرض الأول العرض View عبارة عن دالة مكتوبة بلغة Python (أو صنف كما سنرى في الدروس اللاحقة) يمكن تلخيص عملها ببساطة في أنها تأخذ الطلبات Requests التي يرسلها العميل وتقوم بإرجاع الإجابة response والتي يمكن أن تكون على هيئة شيفرة بصيغة HTML، أو إعادة توجيه لصفحة أخرى، أو صفحة خطأ 404، أو ملف XML، أو صورة أو أي شي آخر. لنبدأ الآن بكتابة العرض الأول في مشروعنا، وللقيام بذلك افتح ملف polls/view.s.py في محرر النصوص المفضّل لديك، ثم امسح محتوياته واكتب الشيفرة التالية: from django.http import HttpResponse def index(request): html = "مرحبًا بك في تطبيق الاقتراعات، هذه هي الصفحة الرئيسية." return HttpResponse(html) في السطر الأول من هذه الشيفرة قمنا باستيراد الصنف HttpResponse من وحدة django.http، وهو المسؤول عن التعامل مع الاستجابة التي ترد على الطلب الذي أرسلناه إلى الخادوم من خلال الدالة index، وذلك عن طريق تمرير المعامل request عند تعريف الدالة. ستقوم هذه الدالة بإعادة العنصر HttpResponse والذي يحتوي على الإجابة، وهي في مثالنا هذا عبارة عن سلسلة نصية بسيطة. ملاحظة: في حال عدم ظهور الأحرف العربية بشكل صحيح، أضف السطر التالي إلى بداية ملف views.py: # -*- coding:utf8 -*- لنتمكن من مشاهدة النتيجة على المتصفح، يجب أن نربط هذا العرض بمسار معين؛ وللقيام بذلك توجه إلى الملف mysite/urls.py وعدّل محتوياته لتصبح بالشكل التالي: from django.conf.urls import url from django.contrib import admin from polls import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^polls/', views.index), ] يتضمن هذا الملف جميع المسارات التي سنستخدمها في المشروع، وهو بمثابة جدول لمحتويات الموقع. في البداية قمنا باستيراد محتويات ملف views.py الموجود في مجلد polls من خلال الشيفرة التالية: from polls import views من خلال هذه الشيفرة يمكنك أن تلاحظ أن Django يتعامل مع المجلد polls باعتباره حزمة من حزم بايثون، وذلك لاحتواءه على ملف init__.py__ كما ذكرنا سابقًا. بهذا الطريقة يمكننا الوصول إلى دالة index التي أنشأناها قبل قليل في ملف views.py الموجود في مجلد polls (أو حزمة polls لنكون أكثر دقة) وذلك تمهيدًا لربطها بالمسار الذي نرغب فيه. أضفنا كذلك الشيفرة التالية إلى قائمة urlpatterns: url(r'/polls', views.index), وهي عبارة عن دالة وظيفتها ربط المسار الذي نحدده في المعامل الأول بالعرض الذي نحدده في المعامل الثاني. لاحظ أن المسار عبارة عن سلسلة نصية مسبوقة بحرف r صغير وذلك لإخبار بايثون بأن يتعامل مع هذه السلسلة النصية على أنّها سلسلة خام raw، بمعنى أنه سيتم تجاوز جميع العلامات الخاصة المستخدمة في هذه السلسلة، وهذا ضروري جدًّا، لأن Django يستخدم التعبيرات النظامية Regular Expressions في تحديد المسارات وتمرير المتغيرات، وهذه التعبيرات تستخدم الكثير من الرموز التي يجب تجاوزها لتعمل الشيفرة بالشكل الصحيح. سنتعرف على المسارات وآلية عملها وكيفية استخدام التعبيرات النظامية، في الدروس اللاحقة. يمكنك الآن التوجه إلى مجلد المشروع وتشغيل الخادوم الخاص بـ Django عن طريق سطر الأوامر من خلال الأمر التالي: python manage.py runserver انتقل في المتصفح إلى العنوان التالي: http://127.0.0.1:8000/polls لتشاهد عبارة الترحيب في واجهة الموقع. يمكننا استخدام شيفرة HTML ضمن السلسلة النصية التي ترجعها دالة العرض، وللقيام بذلك افتح ملف polls/view.py وعدّله ليصبح بالشكل التالي: from django.http import HttpResponse def index(request): html = """ <html dir="rtl"> <head> <title>تطبيق الاقتراعات</title> </head> <body> <h1>تطبيق الاقتراعات</h1> <p>مرحبًا بك في تطبيق الاقتراعات، هذه هي الصفحة الرئيسية.</p> </body> </html> """ return HttpResponse(html) من المؤكد أن التطبيقات التي نراها على صفحات الإنترنت لا تتمتع بهذه البساطة الشديدة، وهذا يعني أن استخدام شيفرة HTML ضمن دالة العرض أمر غير عملي على الإطلاق، وهنا تظهر الحاجة إلى فصل هذه الشيفرات عن العروض وهذه هي وظيفة القوالب Templates والتي سنتعرف إليها في الدروس اللاحقة. خاتمة تعرفنا في هذا الدرس على مفهومي المشروع والتطبيق في Django، وقمنا بكتابة العرض الأول وتعرفنا بشكل مختصر على المسارات Urls. سنتعرف في الدرس القادم على كيفية التعامل مع قواعد البيانات من خلال النماذج Models، وكذلك سنتعرف على كيفية تهجير قواعد البيانات، وكذلك الاستعلام عن البيانات برمجيًا، وذلك لتهيئة قاعدة البيانات التي سنستخدمها في تطبيق الاقتراعات.
  5. بغضِّ النَّظر عن ماهية موقع الوِّيب خاصَّتك، إلَّا أنَّكَ إذا أضفتَ إليه عرض شرائح JavaScript يؤدِّي كُلَّ وظائفه بجودةٍ عالية، فإنَّكَ بذلك تكون قد قُمتَ بتضييق الفجوة بين عملك والعُملاء المُستهدفين. لقد خَدَمَتْ عروض شرائح JavaScript على نحوٍ كبيرٍ كإضافاتٍ لصفحات الوِّيب، حيثُ أنَّها وسيلة رائعة لعرض الكثير والكثير من المعلومات في مساحةٍ صغيرةٍ نسبيًّا. إذا كانت التَّفاصيل المذكورة هذه كافية لإغرائكَ لإنشاء عرض شرائحكَ الخاص باستخدام JavaScript (مع اللَّوحات المُنزلقة) فأنتَ في المكان المُناسب لتعلُّم هذا. سنتشاركُ في هذا الدَّرس بعض الخطوات البسيطة التي يسهل تنفيذها لإنشاء عرض شرائح JavaScript. توضيح الخطوات المُتَّبعة في هذا الدَّرس لإنشاء عرض شرائح JavaScript سأستخدم في هذا الدَّرس شفرات HTML وCSS بسيطة لإنشاء مظهر عرض الشَّرائح في حين أنَّ تنفيذ وظيفة الإنزلاق سيتمّ عن طريق استخدام مكتبة jQuery وهي مكتبة تابعة لـ JavaScript. كما سأستخدم أيضًا إضافتين واسعتي الانتشار: LocalScroll وScrollTo لتقديم التَّاثيرأت الكامنة في عرض شرائح JavaScript. تسمحُ الإضافة الأولى للرَّابط بتخطِّي عرض الشَّرائح إلى شريحةٍ مُحدَّدة بناءً على المُعرِّف ID الذي قد تمَّ تحديده. بينما تُقدِّم الإضافة الثَّانية وظائف انزلاقٍ مُمتازة، حيثُ أنَّها توفِّر خاصيَّة الانتقال بين الشَّرائح بدلًا من القفز من شريحة إلى الأُخرى. حيثُ أنَّنا سنأخذ مُعامِلات الوصول الأساسيَّة في الحُسبان عند بناء عرض الشَّرائح، فسيكون بإمكان كُلّ مُستخدم التنقُّل وعرض الشَّرائح حتى عند توقُّف JavaScript عن العمل. فيما يلي نظرة على بنية HTML لعرض الشَّرائح: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Sliding-enabled slideshow using jQuery | Script Tutorials</title> <meta name="description" content="Sliding-enabled slideshow using jQuery demo - Script Tutorials"> <!-- include to stylesheet --> <link rel="stylesheet" href="css/style.css" type="text/css" /> <!-- include jQuery library and other javascripts --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> <script src="js/jquery.scrollTo.js"></script> <script src="js/jquery.localscroll.js"></script> <script src="js/custom-scripts.js"></script> </head> <body> <div id="slideshow"> <!-- List of slider images --> <ul> <li id="slide1"><img src="images/slide1.jpg" alt="Slide 1" /></li> <li id="slide2"><img src="images/slide2.jpg" alt="Slide 2" /></li> <li id="slide3"><img src="images/slide3.jpg" alt="Slide 3" /></li> <li id="slide4"><img src="images/slide4.jpg" alt="Slide 4" /></li> <li id="slide5"><img src="images/slide5.jpg" alt="Slide 5" /></li> </ul> </div> <div id="slideshow-nav"> <!-- Navigation list of slider images --> <ul> <li><a href="#slide1">Slide 1</a></li> <li><a href="#slide2">Slide 2</a></li> <li><a href="#slide3">Slide 3</a></li> <li><a href="#slide4">Slide 4</a></li> <li><a href="#slide5">Slide 5</a></li> </ul> </div> </body> </html> بالاطّلاع بعنايةٍ على الشَّفرات أعلاه ستُلاحظ أنَّ شفرات HTML لصفحات العرض تبدأ بـ Doctype، عنوان title ورابط إلى ملف نمط CSS. بعد هؤلاء الثلاث ستجد أنَّه لتجهيز عرض الشَّرائح وتشغيله قد تمَّ اضافة رابط لكلٍّ من: الإضافتين LocalScroll وScrollTo السَّابق توضيحهما، مكتبة jQuery وملف script.js. كذلك قد تمَّ فصل شفرات HTML المسئولة عن تكوين عرض الشَّرائح إلى قسمين: وسم div مُعرَّف بـ slideshow وآخر مُعرَّف بـ slideshow-nav. من المُهمّ هُنا مُلاحظة أنَّ وسم div المُعرَّف بـ slideshow سوف يحتوي على قائمة غير مُرقَّمة من صورٍ مُتَّصلة، ووسوم li تحتوي على مُعرِّفاتٍ تتوافق مع روابط slideshow-nav. لنُلقي الآن نظرة على أنماط CSS css/style.css #slideshow {/*slider container css*/ width: 800px; height: 400px; overflow: hidden; margin: 50px auto 50px auto; box-shadow: 0px 0px 50px #333; -moz-box-shadow: 0px 0px 50px #333; -webkit-box-shadow: 0px 0px 50px #333; } #slideshow ul {/*manage slider scroll elements css*/ width: 4000px; list-style: none; } #slideshow ul li { float: left; } ستقوم أنماط CSS الموجودة بالأعلى بالعمل على تحويل المظهر البسيط النَّاشئ عن شفرات HTML إلى صفحاتٍ تظهرُ بشكلٍ يُشبه عرض الشَّرائح المطلوب. يتمّ تنفيذ هذا بدءًا من تحديد ارتفاع وعرض هذه الشَّرائح، تحديد أيضًا الأبعاد لتكون مُماثلة تمامًا لأبعاد شرائح الصور. مع كُلّ الشَّرائح عائمة جنبًا إلى جنب فإنَّه من المُمكن تحديد قياسات العرض الكُلِّي للقائمة الغير مُرقَّمة حتَّى 4590px. كذلك قد تمَّ استخدام خاصيَّة الفائض overflow لمنع ظهور الصور المُتعدِّدة بأكملها في الصَّفحة. كُلّ ما تحتاج لفعله هُنا هو ببساطة تعيين خاصيَّة الفائض كـ overflow: scroll، يؤدِّي هذا التَّعيين إلى السَّماح لعرض الشَّرائح بالعمل حتَّى في حالة عدم وجود JavaScript. تمَّ إضافة ظلّ لطيف باستخدام CSS3-box shadow كما هو مُبيَّن أدناه #slideshow-nav {/* Slider navigation container css */ width: 150px; margin: 0 auto 100px auto; } #slideshow-nav ul { list-style: none; } #slideshow-nav ul li { float: left; } #slideshow-nav ul li a {/* navigation styling css */ display: block; width: 20px; height: 20px; float: left; margin: 0 5px; background: #fff; text-indent: -9999px; border-radius: 50%; -webkit-border-radius: 50%; box-shadow: 0px 0px 30px #000; -webkit-box-shadow: 0px 0px 30px #000; } #slideshow-nav ul li a:hover, #slideshow-nav ul li a.active { /* hover and active navigation css */ background: #333; } بمُعاينةٍ دقيقةٍ هُنا سنُلاحظ أنَّه قد تمَّ نقل وسم div الذي تمَّ تعريفه بـ slideshow-nav إلى موضعٍ أسفل القسم الرئيسي لعرض الشَّرائح. لا نُريد كذلك وجود عدَّة أزرار في عرض الشَّرائح والتي لا تعمل عند تفعيل وظائف JavaScript. يُمكنكَ استخدام visibility: hidden لإخفاء تلك الأزرار كوضعٍ افتراضي، مِمَّا يجعل امكانية إظهارها في وقتٍ لاحق أمرًا مُتاحًا. قد يُثير اهتمامكَ أيضًا معرفة أنَّهُ قد تمَّ تحويل الروابط الخاصَّة بكلّ قائمةِ تنقُّلٍ إلى أزرار دائريَّة بمُساعدة border-radius في CSS3 مع إزاحة النَّصّ الافتراضي خارج الشَّاشة عن طريق تعيين قيمة سالبة لـ text-indent. إلى الآن فإنَّ عرض الشَّرائح يعمل بصورة ملموسة ودون الحاجة إلى JavaScript. هُناك فقط شريط تنقُّل يُتيح للمُستخدم التَّحرُّك ذهابًا وإيابًا بين صُورٍ مُختلفة. وأخيرًا، لنُلقي نظرة على وظائف jQuery js/custom-scripts.js $(document).ready(function() { var slider = $("#slideshow"); var slider_nav = $("#slideshow-nav"); slider_nav.find("a[href=#slide1]").addClass("active"); slider_nav.localScroll({ target:'#slideshow', axis: 'x' }); slider_nav.find("a").click(function(){ slider_nav.find("a").removeClass("active"); $(this).addClass("active"); }); }); إذا نظرتَ إلى الشَّفرات أعلاه ستجد أنَّه قم تمَّ تغيير أنماط CSS الخاصَّة بوسم slideshow من overflow: scroll إلى overflow: hidden لإزالة شريط التَّمرير. بعد ذلك تمَّ تعيين ظهور أزرار nav لتُصبح مرئيَّة مع اضافة فئة active تلقائيًّا إلى الزرّ الأوَّل. كذلك تمَّ تفعيل كلتا الإضافتين: LocalScroll وScrollTo، إضافةً إلى تطبيق وظائف LocalScroll على عناصر slideshow-nav عن طريق توجيه تلك العناصر لاستهداف عناصر slideshow بالتَّحرُّك على طول محور X. أخيرًا، للتأكُّد من أنَّ جميع الأزرار في عرض الشَّرائح تعمل مع فئتها النَّشطة (متى تمَّ نقرُها)، سوف نستخدم قاعدة jQuery بسيطة والتي من شأنها إزالة الفئة النَّشطة من الأزرار التي لم يتمّ نقرها. ستظهر تلك الفئة النَّشطة المُحدَّدة ضمن أنماط CSS لعرض لون خلفية رمادي إلى الزر الذي تمَّ نقره فقط. بعمل اختبارٍ سريعٍ في المُتصفِّح سيظهر عرض شرائح JavaScript يعمل على أكمل وجه. الإخراج إليك هذا المثال الحي ختامًا بهذا نكون قد انتهينا من إنشاء عرض شرائح JavaScript بإمكانه إضافة مظهرًا جميلًا إلى صفحات الوِّيب خاصَّتك. ترجمة -وبتصرُّف- للمقال: A Complete Tutorial On Creating Sliding-Enabled Slideshow Using jQuery.
  6. إن تقديم الخصومات والمنتجات/الخدمات المجانية للعملاء المحتملين هي وسيلة فعالة لزيادة الاهتمام فيك وفي أعمالك. وسيزداد الإهتمام بشكل كبير بعرضك، عندما تتيحه لمدة محدودة فقط، والتفسير النفسي لهذا هو أن ندرة شيء ما مهما كان (طعام، موارد أو حتى عرض مثير…) سيدفعنا للتّصرف بسرعة للحصول عليه قبل فوات الأوان. في درسنا اليوم سنتعلم كيف يمكننا الاستفادة من هذا المفهوم باستخدام ملحقي Social Marketing و Scheduled Content وسننشئ عرضًا لمدة محدودة لتشجيع المستخدمين للإعجاب بحساباتنا على شبكات التواصل الاجتماعي ومن ثم العودة للوصول إلى الخصم الخاص. لنبدأ! Social Marketing و Scheduled Content ستتمكن من لفت الأنظار حول ما تقدّمه من مُنتجات باستخدام ملحق Social Marketing من خلال تقديم حوافز للمستخدمين الذين ينشرون منتجاتك أو خدماتك على شبكات التواصل الإجتماعي الكبرى مثل فيسبوك وتويتر و جوجل+ وغيرها. يعمل هذا الملحق على عرض إعلان مباشرة في موقعك عن طريق عرض نافذة منبثقة تظهر بها روابط المشاركة على شبكات التواصل الاجتماعي، وعندما يشارك أحد الزوار عرضك، يتم الكشف عن العرض مع رسالة. يمكنك دمج الإعلانات بسهولة مع مشاركاتك وصفحاتك باستخدام الأكواد القصيرة (shortcodes)، ويمكنك أيضا تخصيصها بسهولة بالاعتماد على الكثير من الخيارات التي تختارها عند إنشائك لإعلانك. أما بالنسبة لـ Schedule Selected Content فسيسمح لك بجدولة المحتويات لإظهارها على موقعك في أي وقت تريده في المستقبل. ستتمكن باستخدام هذين الملحقين من إنشاء وجدولة عروض محدودة الوقت للشبكات الاجتماعية. في هذا الدرس، سأنشئ عرضًا لشركتي المتخصصة في تصميم الويب لأريك كيف يمكنك إعداد هذه الملحقات. سأنشئ عرضًا يمنح قسيمة (coupon) مجانية للحصول على مُلحق تجاري بالإضافة إلى دعم مجاني لمدة شهر مع تخفيض 50% على أسعار القوالب، وهذا العرض سيبقى لمدة 24 ساعة وسينتهي عند منتصف الليل. البداية ثبت وفعّل أولا ملحقي Schedule Selected Content و Social Marketing. إعداد Social Marketing عند تفعيل ملحق Social Marketing، ستُوجّه إلى صفحة إعداداته، ويمكنك إنشاء إعلانك الأول بثلاثة خطوات فقط: إعداد الخيارات: سنتحكّم هنا في الإعدادات الأساسية للإعلان مثل خيارات المظهر والتحميل… إنشاء إعلانك: سيظهر هنا شكل إعلانك بعد إضافة المحتويات والتفاصيل. إضافة إعلانك: سيتم توفير كود قصير سيمكنك من إضافة إعلانك في أي مكان في موقعك. انقر على زر Configure your settings لإعداد الخيارات حسب تفضيلاتك. يمكنك إما اختيار إحدى القوالب الجاهزة أو استخدام أنماط (stylesheet) موقعك الحالي لإنشاء إعلانك. أود أن أذكر أن خيار "lazy dependency loading" سيحمّل -عند تفعيله- عناصر إعلانك حسب الحاجة وذلك لتقليص وقت تحميل موقعك. عند انتهاءك من الخيارات، انقر على زر Save Changes and go back to Tutorial في أسفل الصفحة. إنشاء الإعلان بعد ذلك انقر على زر Create Advert في صفحة Getting Started، ستلاحظ وجود محرر WYSIWYG والذي يشبه كثيرا محرر التدوينات والصفحات باستثناء أنه توجد بعض الخيارات الإضافية أسفل المحرر. أدخل عنوان ومحتويات إعلانك، كِلا الحقلين سيظهران في الواجهة الأمامية (front end)، وبعد ذلك أدخل الخيارات التي ترغب بها لكن قبل أن تنقر على Publish، قد ترغب في إضافة و جدولة إعلانك أوّلًا. إظهار عرضك محدود الوقت أنشئ مشاركة أو صفحة جديدة أو حتى افتح واحدة قمت بإنشائها سابقا تريد إظهار عرضك فيها (يمكنك أيضا إظهار إعلانك في نافذة منبثقة باستخدام ملحق PopUp Pro). بعد ذلك حدد المكان التي تريد عرض إعلانك بها وانقر على Insert Social Ad بجانب زر Add Media في أعلى المحرر. ستظهر لك نافذة منبثقة حيث يمكنك اختيار المحاذاة وبعدها ستجد زر Insert Social Ad والذي يسمح لك بعرض الإعلان الذي تريده. عند الضغط على رابط Advanced ستظهر لك خيارات إضافية حيث يمكنك إضافة أصناف CSS لاستخدامها في ملف styles.css. سيظهر لك كود قصير shortcode في المحرر. حان الآن وقت جدولة عرضك. جدولة عرضك لمدة محدودة حدد الكود قصير shortcode، وستجد زرًا في أسفل المحرر المرئي لجدولة إعلانك بجانب أيقونة Toggle Toolbar. أنقر عليه. ستظهر لك نافذة منبثقة تسمح لك بكتابة التواريخ المطلوبة وعدد مرات تشغيل عرضك المحدود. بمجرد أن تنتهي من اختياراتك، انقر على زر Insert في أسفل الجانب الأيمن من النافذة المنبثقة، وبعد ذلك انقر على Update أو Publish لإظهار إعلانك للجميع. الخاتمة تملك الآن الأدوات اللازمة لإضافة عرضك لمدة محدودة إلى موقعك، وإذا واجهت بعض المشاكل، يمكنك التحقق من التوثيق الموجود في علامة التبويب Usage في صفحات ملحقي Social Marketing و Schedule Selected Content. ترجمة -وبتصرف- للمقال: Creating a Limited Time Offer on Your Site with Social Marketing and Scheduled Content لصاحبته Jenni McKinnon.
  7. راجعت مؤخرًا مئات من العروض التي قدّمتها شركات ناشئة لـ Capital Factory، وقد كان أغلبها ورقيًا ومصوّرًا (فيديو)، في حين تمّت دعوة 20 منهم لتقديم العروض بشكل شخصي. وقد تبلورت لديّ بعض الملاحظات المهمة: يرتكب الجميع نفس الأخطاء.الأشخاص الذين يتجنّبون خطأ واحد فقط من هذه الأخطاء أشخاصًا يتميّزون عن البقية.ترتبط هذه المشاكل بشكل أساسي بالمبدأ الذي تقوم عليه الشّركة النّاشئة أو بسلوك مؤسّس الشركة (ولا علاقة لها بالجانب الخاص بالبحث عن الحصول على استثمار.)من المحتمل أنّك ترتكب الكثير من هذه الأخطاء أيضًا. أرجو أن لا يتبادر إلى ذهنك أنّي ألومك على ذلك، إذ لم يتضّح الأمر بالنسبة إليّ إلا بعد مشاهدة مئات العروض، وهذا غير ممكن بالنسبة إليك. لذا أقدّم إليك في هذا المقال مجموعة من هذه الأخطاء وطرق علاجها. مزايا غير تنافسيةيعتقد المؤسّس أن المزايا التي يتحدّث عنها هي مزايا تنافسية وتُميّزه عن غيره، في حين أن ما يتحدّث عنه ليس مزايا تنافسية إطلاقًا. على سبيل المثال "لدينا إمكانيات فريدة مُتعلّقة بالـ SEO" أو "هذه المزيدة فريدة من نوعها" ليست مزايا تنافسية. للمزيد حول الأمر اقرأ هذا المقال الذي سبق وأن كتبته حول الأمر: لا، هذه الميزات لا تجعل شركتك الناشئة أفضل من غيرها. خلو الشركة من أفضلية غالبةلا تملك الشّركة ما يجعلها مُختلفة عن غيرها من الشّركات النّاشئة. تحتاج إلى مزية خارقة لا يمتلكها أحد ولن يستطيع أحد على وجه الأرض أن ينافسك عليها (ربما لأنّك غيرك سيفوقك في الجوانب الأخرى). للمزيد عن الأمر اقرأ مقالي: المزايا الحقيقية التي تميز الشركات الناشئة الناجحة عن غيرها. لم يذكر أحد أنه سيقوم بشراء منتجلن تحتاج إلى إجراء دراسات إحصائية كبيرة لتبدأ بالعمل على شركتك النّاشئة، ولكن ما يثير الدهشة هو أن هناك من المؤسسين من يطلق مشروعه قبل إيجاد ولو شخص واحد فقط يمتلك الرغبة الحقيقية في دفع المال مقابل المنتج الذي تقدّمه هذه الشركة. ستجد تفاصيل أوفى حول الأمر في مقالي: من أخبرك أن أحدا ما قد يرغب بشراء منتج كهذا؟. التحديد غير الصحيح لمكانك بين المنافسينيتفرّع هذا الخطأ إلى فرعين متعاكسين: الأول: الاعتقاد الجازم بأنّ تفرّدك يعني عدم وجود المنافسة. والثاني: تحديد مواصفات شركتك بالاعتماد على المنافسين بدلًا من بناء هويّتك ورسالتك الخاصّة. تفاصيل أوفى حول الأمر في مقالي السّابق: قم بتحديد مكان شركتك بين المنافسين بهذه الطريقة. عدم وجود طريق واضح للوصول إلى العملاءإن كانت خطّة التسويق الخاصّة بك تعتمد على اختبارات A/B والحصول على المشتركين عن طريق RSS، فإنّك ضائع لا محالة. هناك بعض الأخطاء الشائعة التي ارتأيت أنّها ليست بحاجة إلى مقالات خاصّة لكل منها: عدم القدرة على وصف الشركة خلال 60 ثانيةربما تكون قد سمعت عن حديث المصعد Elevator pitch، ولكن عندما طلبنا القيام به لم يفلح أحد تقريبًا في القيام به بالشكل الصحيح. قدرتك على وصف الشركة بشكل موجز وسريع أمر مهمّ جدًا، حتى ولو لم تصل إلى مرحلة الحصول على الاستثمار لأنّ قدرتك على القيام بذلك يعني أنّك تفهم عملائك جيّدًا وتفهم كذلك الرغبة التي تدفعهم إلى شراء منتجاتك. بناء المنتج لنفسك لا للسوقتبدأ الكثير من الأفكار العظيمة بمبدأ "ما حكّ جلدك مثل ظفرك" ولكنّ لا يمكن اعتماد هذا المبدأ كخطّة للمشروع التجاري. غالبًا ما تفترض أنّك وعميلك متماثلان، وتريان المشكلة من نفس المنظار، وترغبان في حلّها بنفس الطريقة، وترغبان في دفع الأموال لقاء ذلك. ولكنّ هذا ليس بصحيح، فأنت لا تشبه عملائك على الإطلاق، وأحد الأسباب هو أنّك تمتلك الحافز الكافي لترك عملك وإطلاق شركتك الخاصّة. ومن السهل أن تفسح المجال أمام أفكارك المسبّقة الغريبة لتمنعك من ملاحظة رغبات السوق. التظاهر بعدم وجود الأخطاءهناك الكثير من نقاط الضعف يمكن أن تبتلى بها: شركتك الناشئة هذه هي شركتك الأولى التي تُطلقها، انعدام الخبرة والجهل بمبادئ التسويق، برنامج مليء بالأخطاء، وغيرها. لا مشكلة في كل ذلك ما دمت تعترف بوجود هذه الأخطاء وتحاول مواجهتها والتخلّص منها، أمّا إن كنت مصرًا على الكذب عليّ وعلى عملائك بشأن هذه الأخطاء، فهذه مشكلة كبيرة، فالكذبة المتعمدة كذبتان. لا تعرف ما لا تعرفه لا يهمّني إن لم تؤهّلك سيرتك الذاتية لبناء شركتك الناشئة، فسيرتي الذاتية كانت كذلك. ولكن إن كانت إجابتك على أي سؤال يطرح عليك: "وما أدراني؟ أنا لا أعلم." فسأعرف حينها أنّك لست جاهلًا وحسب، بل غير قادر على التخلص من هذا الجهل. كيف لي أن أعلم بأن هذا لن يتسبب في انحراف مشروعك التجاري عن الهدف إلى أن تنفد الأموال من بين يديك في نهاية المطاف؟ أنا لا أعلم. ترجمة - وبتصرّف - للمقال 5Lessons from 150 startup pitches لصاحبه Jason Cohen. حقوق الصورة البارزة: Designed by Freepik.
  8. بعد أن انتهينا من إعداد المشروع وإنشاء توابع وعروض الإنشاء والتخزين والعرض، سوف نقوم في درسنا الأخير اليوم بكتابة الشيفرة البرمجية لتوابع التعديل والتحديث والحذف ومن ثم العروض الموافق لها. تابع Editإن توابع وعروض edit وdelete غير موجودة لحد الساعة، فلننشئها، سنبدأ بالعمل على edit أولا. عدل على تابع المتحكم: public function edit($id) { $marketingImage = Marketingimage::findOrFail($id); return view('marketingimage.edit', compact('marketingImage')); }مرة أخرى قمنا باستخدام تابع findOrFail وقمنا بإرسال الكائن إلى العرض لأننا نريد أن نقوم بتعبئة الاستمارة مسبقا بالقيم المناسبة من سجلات البيانات. عرض Editعدل على ملف views/marektingimage/edit.blade.php ليكون كالتالي: @extends('layouts.master') @section('content') {!! Breadcrumb::withLinks(['Home' => '/', 'marketing images' => '/marketingimage', "edit $marketingImage->image_name.$marketingImage->image_extension" ]) !!} <h1>Edit {{ $marketingImage->image_name. '.' . $marketingImage->image_extension }} </h1> <hr/> @if (count($errors) > 0) <div class="alert alert-danger"> <strong>Whoops! </strong> There were some problems with your input. <br> <br> <ul> @foreach ($errors->all() as $error) <li>{{ $error }} </li> @endforeach </ul> </div> @endif <div> Note: name and path values cannot be changed. If you wish to change these, then delete and create a new photo: </div> <br> {!! Form::model($marketingImage, ['route' => ['marketingimage.update', $marketingImage->id], 'method' => 'PATCH', 'class' => 'form', 'files' => true] ) !!} <!-- image name Form Input --> <div> <ul> <li> <h4>Image Name: {{ $marketingImage->image_name. '.' . $marketingImage->image_extension }} </h4> </li> <li> <h4>Image Path: {{ $marketingImage->image_path }} </h4> </li> <li> <h4>Mobile Name: {{ $marketingImage->mobile_image_name. '.' . $marketingImage->mobile_extension }} </h4> </li> <li> <h4>Mobile Path: {{ $marketingImage->mobile_image_path }} </h4> </li> </ul> </div> <!-- is_something Form Input --> <div class="form-group"> {!! Form::label('is_active', 'Is Active:') !!} {!! Form::checkbox('is_active') !!} </div> <!-- is_featured Form Input --> <div class="form-group"> {!! Form::label('is_featured', 'Is Featured:') !!} {!! Form::checkbox('is_featured') !!} </div> <!-- form field for file --> <div class="form-group"> {!! Form::label('image', 'Primary Image') !!} {!! Form::file('image', null, array('class'=>'form-control')) !!} </div> <!-- form field for file --> <div class="form-group"> {!! Form::label('mobile_image', 'Mobile Image') !!} {!! Form::file('mobile_image', null, array('class'=>'form-control')) !!} </div> <div class="form-group"> {!! Form::submit('Edit', array('class'=>'btn btn-primary')) !!} </div> {!! Form::close() !!} <div> {!! Form::model($marketingImage, ['route' => ['marketingimage.destroy', $marketingImage->id], 'method' => 'DELETE', 'class' => 'form', 'files' => true] ) !!} <div class="form-group"> {!! Form::submit('Delete Photos', array('class'=>'btn btn-danger', 'Onclick' => 'return ConfirmDelete();')) !!} </div> {!! Form::close() !!} </div> @endsection @section('scripts') <script> function ConfirmDelete() { var x = confirm("Are you sure you want to delete?"); if (x) return true; else return false; } </script> @endsectionلم نسمح للمستخدم بتعديل أسماء الصور أومساراتها لأننا نريدهم أن يقوموا بحذف السجلات والبدء من جديد وإلا سيكون الأمر معقدا عندما نقوم بتعديل الأسماء التي قمنا بحفظها في السجلات وهذا الأمر لا يدخل في نطاق الدرس. ماهي الاختلافات الأخرى في الاستمارة ؟ سوف تلاحظ أننا نستخدم حقول أقل وقمنا باستخدام الربط بين النموذج والاستمارة في مساعدي الاستمارة (form helper): {!! Form::model($marketingImage, ['route' => ['marketingimage.update', $marketingImage->id], 'method' => 'PATCH', 'class' => 'form', 'files' => true] ) !!}إن مثيل النموذج marketingImage$ مرتبط بالاستمارة لذلك سيتم تعبئة الحقول بشكل مسبق، ولاحظ أننا قمنا أيضا بتحديد marketingImage->id$ حتى نتمكن من إرسال ذلك إلى تابع المتحكم وتعديل السجل الصحيح. ولقد قمنا بتعيين قيمة PATCH إلى method وهذه سوف تتغير تلقائيا لأن HTML لا يدعم PATCH، ولقد قمنا بتعيين قيمة true إلى files حتى نتمكن من إرسال الملفات. بقية الشيفرة سهلة وقمنا بشرحها سابقا، لاحظ أننا قمنا بوضع زر للحذف في الأسفل في حالة ما أراد المستخدم الحذف بدل التعديل. عند سير العمل بطريقة عادية، سوف تكون خطوتك القادمة في الغالب الانتقال إلى تابع update في MarketingImagesController لكننا سنقوم بإنشاء صنف request للتعامل مع سيناريو update. EditImageRequestالفرق في عملية التحقق بين create و update هو أنه عندما تقوم بإنشاء صورة سيكون ملف الصورة إلزاميا على عكس التحديث، لذلك قررت لأجل البساطة والوضوح أن نقوم بإنشاء صنف request منفصل باسم EditImageRequest بدلا من وضعه في صنف request واحد. المشكلة التي واجهتها هي أنني لا أعرف كيف أجعلها شرطية فعلى أي تابع يجب وضع الصنف، لذلك بدأت في التفكير في الأمر، فبدلا من ذلك، يمكنني أن أقوم بتمرير حقل خفي والذي سوف يُعرف الاستمارة وسوف أقوم بوضع فيه عنصر تحكم منطقي (controlling logic)، فإذا كانت الاستمارة استمارة create، فستكون الصور إلزامية، لكنني في النهاية قررت أنه من الأسهل أن أقوم بعمل صنف منفصل. لذلك قم بتنفيذ هذا الأمر من سطر الأوامر: php artisan make:request EditImageRequestثم قم بتعيين قيمة return true في تابع authorize في ذلك الصنف وعدل تابع rules إلى التالي: public function rules() { return [ 'is_active' => 'boolean', 'is_featured' => 'boolean', 'image' => 'mimes:jpeg,jpg,bmp,png | max:1000', 'mobile_image' => 'mimes:jpeg,jpg,bmp,png | max:1000' ]; }قمنا بالفعل بالتحدث عن تابع rules سابقا ولا داعي لإعادة شرحه هنا. تابع Updateلنقم الآن بالانتقال إلى تابع update في MarketingImageController، عدله كما يلي: public function update($id, EditImageRequest $request) { $marketingImage = Marketingimage::findOrFail($id); $marketingImage->is_active = $request->get('is_active'); $marketingImage->is_featured = $request->get('is_featured'); $this->formatCheckboxValue($marketingImage); $marketingImage->save(); if ( ! empty(Input::file('image'))){ $destinationFolder = '/imgs/marketing/'; $destinationThumbnail = '/imgs/marketing/thumbnails/'; $file = Input::file('image'); $imageName = $marketingImage->image_name; $extension = $request->file('image')->getClientOriginalExtension(); //create instance of image from temp upload $image = Image::make($file->getRealPath()); //save image with thumbnail $image->save(public_path() . $destinationFolder . $imageName . '.' . $extension) ->resize(60, 60) // ->greyscale() ->save(public_path() . $destinationThumbnail . 'thumb-' . $imageName . '.' . $extension); } if ( ! empty(Input::file('mobile_image'))) { $destinationMobile = '/imgs/marketing/mobile/'; $mobileFile = Input::file('mobile_image'); $mobileImageName = $marketingImage->mobile_image_name; $mobileExtension = $request->file('mobile_image')->getClientOriginalExtension(); //create instance of image from temp upload $mobileImage = Image::make($mobileFile->getRealPath()); $mobileImage->save(public_path() . $destinationMobile . $mobileImageName . '.' . $mobileExtension); } flash()->success('image edited!'); return view('marketingimage.edit', compact('marketingImage')); }دعونا نبدأ بتوقيع التابع: public function update($id, EditImageRequest $request) {سوف ترى أننا نقوم بسحب مثيل من كائن request الصحيح، وقمنا باستخدام findOrFail في نموذج السجل حتى نتمكن من تعيين القيم من مثيل request، وبعد ذلك قمنا بتهيئة (format) قيم خانة الاختيار (checkbox) ثم حفظناها: $marketingImage = Marketingimage::findOrFail($id); $marketingImage->is_active = $request->get('is_active'); $marketingImage->is_featured = $request->get('is_featured'); $this->formatCheckboxValue($marketingImage); $marketingImage->save();إذا لم تكن الصورة الأولية فارغة، سوف نقوم بالتحديث: if ( ! empty(Input::file('image'))){ $destinationFolder = '/imgs/marketing/'; $destinationThumbnail = '/imgs/marketing/thumbnails/'; $file = Input::file('image'); $imageName = $marketingImage->image_name; $extension = $request->file('image')->getClientOriginalExtension(); //create instance of image from temp upload $image = Image::make($file->getRealPath()); //save image with thumbnail $image->save(public_path() . $destinationFolder . $imageName . '.' . $extension) ->resize(60, 60) // ->greyscale() ->save(public_path() . $destinationThumbnail . 'thumb-' . $imageName . '.' . $extension); }ثم سنفعل نفس الشيء على صور الهاتف: if ( ! empty(Input::file('mobile_image'))) { $destinationMobile = '/imgs/marketing/mobile/'; $mobileFile = Input::file('mobile_image'); $mobileImageName = $marketingImage->mobile_image_name; $mobileExtension = $request->file('mobile_image')->getClientOriginalExtension(); //create instance of image from temp upload $mobileImage = Image::make($mobileFile->getRealPath()); $mobileImage->save(public_path() . $destinationMobile . $mobileImageName . '.' . $mobileExtension); }ثم قمنا بتنفيذ flash لـ success وبعد ذلك قمنا بالعودة return وفي حالتنا هذه إلى صفحة التعديل edit، لكن يمكنك تغيير العودة إلى أي صفحة تريدها: flash()->success('image edited!'); return view('marketingimage.edit', compact('marketingImage'));أرجو ملاحظة أنه إذا كنت تقوم بعمل هذا لشركة تطوير، ربما قد تريد أن تجعل هذه الشيفرة أقوى عن طريق التحقق من أن الملف قد تم إنشاءه، وسوف تتعامل مع الأمر بشكل مختلف إذا لم يعمل لبعض الأسباب، لكن كل هذا خارج نطاق الدرس. حسنا، الآن آخر خطوة في درسنا. تابع Destroyسوف نحتاج إلى كتابة تابع destroy للتعامل مع حذف الصور: public function destroy($id) { $marketingImage = Marketingimage::findOrFail($id); $thumbPath = $marketingImage->image_path.'thumbnails/'; File::delete(public_path($marketingImage->image_path). $marketingImage->image_name . '.' . $marketingImage->image_extension); File::delete(public_path($marketingImage->mobile_image_path). $marketingImage->mobile_image_name . '.' . $marketingImage->mobile_extension); File::delete(public_path($thumbPath). 'thumb-' . $marketingImage->image_name . '.' . $marketingImage->image_extension); Marketingimage::destroy($id); flash()->success('image deleted!'); return redirect()->route('marketingimage.index'); }يمكنك أن ترى أننا قمنا باستخدام findOrFail على id الذي تم استلامه عن طريق التوقيع، ثم استخدمنا مساعدي الملف (File helper) لـ Laravel للحذف، وهكذا تحصلنا مرة أخرى على صياغة جميلة لتبين لنا ما نقوم بفعله. قمنا أيضا باستخدام تابع ()public_path ووضعنا مكونات الصورة داخل ذلك التوقيع، وبعد ذلك قمنا بتكرار نفس الأمر مع كل نوع من الصور مرتبط مع السجل، ثم استخدمنا تابع destroy لحذف السجل من قاعدة البيانات، وقمنا بتنفيذ flash لتابع success ومن ثم قمنا بإعادة التوجيه إلى صفحة index، وهاقد انتهينا. خاتمةلقد تعلمنا في هذه الدروس العديد من الطرق والمفاهيم الجديدة في Laravel، وعلى الرغم من بساطة التطبيق الذي قمنا بعمله إلا أنه سيكون بداية جيدة لاحتراف إدارة الصور في Laravel، وإذا كان لديك أي سؤال أو تعليق، فيسرنا أن نسمعه في التعليقات في الأسفل، وإذا أعجبتك هذه التدوينة، أرجو أن تقوم بمشاركتها مع أصدقاءك. ترجمة -وبتصرّف- للدرس Basic Image Management Part 3 لصاحبه Bill Keck. حقوق الصورة البارزة: Designed by Freepik.
  9. في الحالة العادية، سوف تقوم بكتابة تابع (store method) أولا، ومن ثم تترك عملية التحقق في النهاية حتى يعمل store بشكل جيد، لكن في حالتنا هذه سيكون الأمر معقدا قليلا بما أننا نتعامل مع ملفات منفصلة يجب حفظها، ففي حالة الصور، سوف نحتاج إلى التحقق أولا. صنف Requestسوف نبدأ بإنشاء صنف (request class) والذي سيقوم بالتعامل مع عملية التحقق من استمارة الإنشاء. سوف نبدأ بكتابة هذا الأمر على سطر الأوامر: php artisan make:request CreateImageRequestهذا الأمر سيقوم بإنشاء الملف ووضعه داخل مجلد app/Http/Requests. بعد ذلك، عدل الملف كالتالي: <?php namespace App\Http\Requests; use App\Http\Requests\Request; use App\Marketingimage; class CreateImageRequest extends Request { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'image_name' => 'alpha_num | required | unique:marketing_images', 'mobile_image_name' => 'alpha_num | required | unique:marketing_images', 'is_active' => 'boolean', 'is_featured' => 'boolean', 'image' => 'required | mimes:jpeg,jpg,bmp,png | max:1000', 'mobile_image' => 'required | mimes:jpeg,jpg,bmp,png | max:1000' ]; } }واحد من الأشياء التي أحبها في إطار Laravel هو كيفية تعامله مع عملية التحقق، فإذا كانت هذه المرة الأولى التي ستتعامل فيها مع عملية التحقق، سوف تجد أن هذه العملية بسيطة للغاية. لاحظ أننا قمنا بكتابة السطر التالي في تابع authorize: return true;هذا السطر سوف يسمح للطلب أن يمر، فإذا وضعنا شرطا عليه فسنستطيع التحكم فيه، فعلى سبيل المثال، يمكننا استخدامه في تسجيل الدخول للأعضاء فقط. بعد ذلك لدينا قواعد التابع، الذي سوف يتم فرضها على عملية التحقق في حقول الاستمارة، لن نتعمق أكثر هنا، فإذا أردت المزيد يمكنك الإطلاع على توثيق Laravel. للتذكير فإننا نفصل ما بين قواعد التّحقق بمحرف "|" ولما نضيف قاعدة "unique" فإننا نُرفقها باسم الجدول الذي يجب أن نبحث فيه (يعني الجدول الذي نرغب في أن يكون السّجل record الذي نقوم بحفظه وحيدًا "unique"). ومن الطبيعي أننا أننا قمنا بإضافة قيد على حجم الملفات. يمكنك إيجاد قائمة كاملة من قواعد التحقق في الوثائق. تابع Storeعلى أي حال، سوف ننتقل الآن لتابع store في MarketingImageController، عدل التابع كما يلي: public function store(CreateImageRequest $request) { //create new instance of model to save from form $marketingImage = new Marketingimage([ 'image_name' => $request->get('image_name'), 'image_extension' => $request->file('image')->getClientOriginalExtension(), 'mobile_image_name' => $request->get('mobile_image_name'), 'mobile_extension' => $request->file('mobile_image')->getClientOriginalExtension(), 'is_active' => $request->get('is_active'), 'is_featured' => $request->get('is_featured'), ]); //define the image paths $destinationFolder = '/imgs/marketing/'; $destinationThumbnail = '/imgs/marketing/thumbnails/'; $destinationMobile = '/imgs/marketing/mobile/'; //assign the image paths to new model, so we can save them to DB $marketingImage->image_path = $destinationFolder; $marketingImage->mobile_image_path = $destinationMobile; // format checkbox values and save model $this->formatCheckboxValue($marketingImage); $marketingImage->save(); //parts of the image we will need $file = Input::file('image'); $imageName = $marketingImage->image_name; $extension = $request->file('image')->getClientOriginalExtension(); //create instance of image from temp upload $image = Image::make($file->getRealPath()); //save image with thumbnail $image->save(public_path() . $destinationFolder . $imageName . '.' . $extension) ->resize(60, 60) // ->greyscale() ->save(public_path() . $destinationThumbnail . 'thumb-' . $imageName . '.' . $extension); // now for mobile $mobileFile = Input::file('mobile_image'); $mobileImageName = $marketingImage->mobile_image_name; $mobileExtension = $request->file('mobile_image')->getClientOriginalExtension(); //create instance of image from temp upload $mobileImage = Image::make($mobileFile->getRealPath()); $mobileImage->save(public_path() . $destinationMobile . $mobileImageName . '.' . $mobileExtension); // Process the uploaded image, add $model->attribute and folder name flash()->success('Marketing Image Created!'); return redirect()->route('marketingimage.show', [$marketingImage]); }حسنا، دعونا نبدأ بفهم هذه الشفرة الطويلة، سنبدأ مع توقيع الدالة: public function store(CreateImageRequest $request)هذا الجزء واضح، فلقد قمنا فقط بسحب نسخة (instance) من كائن request يحمل الاسم request$ وهذا سوف يساعدنا على إنشاء نسخة جديدة للنموذج: //create new instance of model to save from form $marketingImage = new Marketingimage([ 'image_name' => $request->get('image_name'), 'image_extension' => $request->file('image')->getClientOriginalExtension(), 'mobile_image_name' => $request->get('mobile_image_name'), 'mobile_extension' => $request->file('mobile_image')->getClientOriginalExtension(), 'is_active' => $request->get('is_active'), 'is_featured' => $request->get('is_featured'), ]);لاحظ أنني أقوم بالتعليق كثيرا على هذا التابع (method)، لأنه من السهل أن يربكك. على أي حال، قمنا بإنشاء مثيل جديد لـ Marketingimage ووضعنا خصائص النموذج باستخدام مثيل request$. أما البقية الشيفرة، فلقد قُمنا بسحب البيانات من الاستمارة إذا نجحت في عملية التحقق. ثم سوف نحتاج إلى تعريف مسارات الصور: //define the image paths $destinationFolder = '/imgs/marketing/'; $destinationThumbnail = '/imgs/marketing/thumbnails/'; $destinationMobile = '/imgs/marketing/mobile/';ملاحظة: حاولت أن أجعل هذه الأسماء بديهية قدر الإمكان. بعد ذلك، سوف نقوم بتعيينها إلى النموذج حتى نتمكن من حفظهم في قاعدة البيانات. //assign the image paths to new model, so we can save them to DB $marketingImage->image_path = $destinationFolder; $marketingImage->mobile_image_path = $destinationMobile;نستطيع فعل هذا بطريقة أخرى، فيمكننا أن نقوم بتقديم معلومات المسار في الاستمارة أو يمكننا تخطي هذا كليا، لكن وجدت أن إبقاء المسار في قاعدة البيانات يجعل العمل مع الصور أسهل عندما نحتاج إلى استخدامها في العروض (views)، وهذا هو سبب استخدامنا هذه الطريقة. ثم سنقوم بتهيئة (format) قيم خانة اختيار ومن ثم نقوم بحفظها: // format checkbox values and save model $this->formatCheckboxValue($marketingImage); $marketingImage->save(); يمكنك أن ترى أنني أقوم بتسليم مثيل النموذج marketingImage$ إلى تابع formatCheckboxValue، وهو تابع قمت بعمله للتأكد من أن خانة الاختيار يتم التعامل معها بشكل جيد: public function formatCheckboxValue($marketingImage) { $marketingImage->is_active = ($marketingImage->is_active == null) ? 0 : 1; $marketingImage->is_featured = ($marketingImage->is_featured == null) ? 0 : 1; }بسبب نوع البيانات في قاعدة البيانات، يمكننا توفير فقط رقمين 0 و 1، لذلك نحتاج إلى التأكد من أننا نقوم بالتحويل بشكل صحيح من خانة الاختيار (checkbox) في الاستمارة (form). لقد قمنا بتسليمها إلى مثيل النموذج ومن ثم سيقوم بوضع الخصائص وفقا لذلك. بعد ذلك نعود إلى تابع store، ونقوم ببساطة بالحفظ: $marketingImage->save();وهذا سوف يهتم بسجلات قاعدة البيانات، ومع ذلك، لانزال بحاجة إلى التعامل مع الملف. في البداية سوف نعمل على بعض أجزاء الصورة التي سنحتاجها: //parts of the image we will need $file = Input::file('image'); $imageName = $marketingImage->image_name; $extension = $request->file('image')->getClientOriginalExtension();بدلا من ذلك، يمكنك جعل بعض هذه الشفرات في سطر واحد (inline) لكنك ستحصل على سطور طويلة جدا بالإضافة إلى أن إبقائها هكذا أسهل للتتبع والفهم. الآن سوف نحتاج إلى استخدام مكتبة الصور (Image library) لمساعدتنا على الخروج من هنا، سنقوم بإنشاء مثيل لهذه الصورة من الصور المرفوعة: //create instance of image from temp upload $image = Image::make($file->getRealPath());بعد ذلك، سنقوم بحفظها وإنشاء صورة مصغرة والتي سنقوم بحفظها عن طريق سَلسَلة التوابع (chaining the methods): //save image with thumbnail $image->save(public_path() . $destinationFolder . $imageName . '.' . $extension) ->resize(60, 60) // ->greyscale() ->save(public_path() . $destinationThumbnail . 'thumb-' . $imageName . '.' . $extension);سوف نقوم بتقسيم هذه الشيفرة إلى أجزاء حتى نفهمها بشكل أفضل، أول جزء يقوم بحفظ الصور الأولية: $image->save(public_path() . $destinationFolder . $imageName . '.' . $extension)استخدمنا ()public_path للوصول إلى المكان الذي يمكننا تعريف فيه مجلد الهدف (مجلد الصور) والذي هو imgs/marekting/. بعد ذلك قمنا بسَلسَلة أجزاء الصورة (مسار ملف الصورة) التي نحتاجها وهذا سوف يعطينا كل شيء نحتاجه وسيسهل علينا عملية متابعة الشيفرة البرمجية. بما أننا نحتاج أيضا إلى إنشاء صورة مصغرة، قمنا بسَلسَلة ذلك التابع: ->resize(60, 60)وهذا السطر سوف ينشئ لنا نسخة بحجم 60 × 60 من الصورة، وإذا أردت تغيير حجم النسخة يمكنك فعل هذا بسهولة بتغيير الأرقام، ويمكنك أيضا إنشاء حقل في الاستمارة للمستخدمين لتحديد ارتفاع و عرض الصور المصغر. (لن نقوم بهذا في هذا الدرس.) قمتُ بإرفاق (على شكل تعليق) تابع متسَلسَل لجعل الصورة المصغرة ذات تدرج رمادي، فإذا أردت صور مصغرة بيضاء وسوداء اجعل السطر شيفرة برمجية (عن طريق إزالة //). والآن سنقوم بحفظ الصورة المصغرة: ->save(public_path() . $destinationThumbnail . 'thumb-' . $imageName . '.' . $extension);وسنقوم بنفس الشيء لصور الهاتف: // create instance of image from temp upload $mobileImage = Image::make($mobileFile->getRealPath()); $mobileImage->save(public_path() . $destinationMobile . $mobileImageName . '.' . $mobileExtension);يما أنها مثل الصور الأولية لكن بدون صورة مصغرة، سوف نتركها هكذا. حسنا، بعد ذلك لدينا رسالة الفلاش (flash message): flash()->success('Marketing Image Created!');هذه الشيفرة لن تعمل إلا إذا قمت بتثبيت حزمة الفلاش لجفري ويِ (Jefferey Wey) وقمت باستدعائها في عرض (view) الصفحة الرئيسية، وإذا لم تقم بتثبيت هذه الحزمة فلا تكتب هذه الشيفرة. في النهاية، بعد حفظ كُل من النموذج وملفات الصور، سوف نقوم بإعادة التوجيه نحو صفحة العرض: return redirect()->route('marketingimage.show', [$marketingImage]);الآن يمكنك تجربة رفع وحفظ الصور وعمل صورة مصغرة وصورة للهاتف عن طريق زيارة الاستمارة في العنوان التالي: yourdomain.com/marketingimage/createيمكنك التأكد من إنشاء الصور من خلال النظر إلى المجلدات حيث يُفترض أن تكون الصور. سوف ترى أن تابع store يقوم بالكثير من الأشياء، لكن ينقصه آلية للتحقق من الأخطاء، يمكنك فعل هذا لجعل التطبيق أكثر قوة على الرغم من أنني أعتقد أن أمر ليس ضروري. بما أن Laravel يقوم بوظيفة جيدة عن طريق فصل استمارة التحقق من تابع store، لن يتوقف التابع إذا فشلت عملية التحقق. حسنا ماذا يمكن أن يفشل أيضا ؟ حسنا ربما تفشل عملية حفظ الملف وهذا يمكن أن يكون بسبب امتلاء النظام، أو بسبب مشاكل في الصلاحيات أو خطأ في كتابة المسارات وأسماء المجلدات. هذه الأخطاء صعبة الاكتشاف والتصحيح بسبب أنه ربما قد لا تحصل على رسائل الخطأ المناسبة، وعلى أية حال، هذه هي أشهر الأخطاء إذا أردت اكتشافها وتصحيحها. يمكنك أن ترى أنه على الرغم من أنه لا شيء صعب في إدارة الصورة إلا أن الصعوبة موجودة بشكل ما. الخطوة المنطقية التالية هي إنشاء تابع show في المتحكم وإنشاء العرض الخاص به. تابع showحسنا، هذه هي شيفرة تابع العرض: public function show($id) { $marketingImage = Marketingimage::findOrFail($id); return view('marketingimage.show', compact('marketingImage')); }هذه الشيفرة واضحة للغاية، يقوم Laravel باسترجاع مثيل النموذج ثم يقوم بإرجاعه إلى العرض view، لاحظ استخدام findOrFail والتي تقوم بإرجاع ModelNotFoundException، والتي يمكنك التعامل معها من خلال ملف Handler.php في app/Exceptions. عرض showحسنا، بعدما انتهينا من التابع ننتقل إلى العرض view: @extends('layouts.master') @section('content') {!! Breadcrumb::withLinks(['Home' => '/', 'marketing images' => '/marketingimage', "show $marketingImage->image_name.$marketingImage->image_extension" ]) !!} <div> {{ $marketingImage->image_name }} : <br> <img src="/imgs/marketing/{{ $marketingImage->image_name . '.' . $marketingImage->image_extension . '?'. 'time='. time() }}"> </div> <div> {{ $marketingImage->image_name }} - thumbnail : <br> <img src="/imgs/marketing/thumbnails/{{ 'thumb-' . $marketingImage->image_name . '.' . $marketingImage->image_extension . '?'. 'time='. time() }}"> </div> <div> {{ $marketingImage->mobile_image_name }} - mobile : <br> <img src="/imgs/marketing/mobile/{{ $marketingImage->mobile_image_name . '.' . $marketingImage->mobile_extension . '?'. 'time='. time() }}"> </div> @endsectionملاحظة: يمكنك إزالة مساعدات Breadcrumb إذا لم تكن تستخدم تلك الحزمة. لم نجعل الواجهة الأمامية فاخرة هنا، قمنا فقط بعمل صفحة بسيطة لإظهار الصور. وبما أننا أرسلنا مثيل marketingImage$ إلى المتحكم، فإننا استخدمنا تركيبة blade لاستدعاء اسم الصورة: {{ $marketingImage->image_name }}ثم نقوم بإستدعاء الصور الأولية: <img src="/imgs/marketing/{{ $marketingImage->image_name . '.' . $marketingImage->image_extension . '?'. 'time='. time() }}">سترى أننا استخدمنا تركيبة blade طباعة اسم الصورة وامتدادها والتي هي مسجلة في قاعد البيانات، وبإبقاء الامتداد في قاعدة البيانات يمكننا استخدام امتدادات مختلفة بدلا من فرض استخدام jpg. على سبيل المثال. سوف تلاحظ أيضا أننا أضفنا: '?'. 'time='. time() للحصول على متغير، وهذا الأمر سيمنع عملية تخزين المؤقت للصور نظرا لأنه تم إلحاق الوقت في نهاية الرابط. إن التخزين المؤقت للصور يمكن أن يكون مشكلة بالنسبة لإدارة الصور عندما تقوم برفع الصور. وبالطبع هذا الأمر اختياري ويمكنك تجاوزه. بقية الشيفرة البرمجية تقريبا نفسها مع بعض التغييرات للصور المصغرة والصور الهواتف. لن تكون الصفحة جميلة جدا، لكنها تقوم بالمهمة. والآن إذا كان لديك صورة قمت برفعها لحفظها في قاعدة البيانات، يمكنك مشاهدتها عن طريق الذهاب إلى: yourproject.com/marketingimage/1يمكنك تغيير الرقم في النهاية لأن هذا الرقم هو رقم الصورة في سجل البيانات. حسنا، بعد ذلك، قبل أن نعمل على edit و update، لنقم ببناء تابع index في المتحكم ثم عرض (index view). تابع indexفي MarketingImageController، عدل تابع index كما يلي: public function index() { $images = Marketingimage::all(); return view('marketingimage.index', compact('images')); }يمكنك أن ترى أن الشيفرة سهلة للغاية، فلقد قمنا فقط باسترجاع جميع السجلات إلى كائن images$، والتي يتم تمريرها إلى العرض view عن طريق تابع compact. عرض Indexبعد ذلك، سنقوم بتعديل views/marketingimages/index.blade.php كما يلي: @extends('layouts.master') @section('content') {!! Breadcrumb::withLinks(['Home' => '/', 'marketing images' => '/marketingimage']) !!} <br> <div> <div class="panel panel-default"> <!-- Default panel contents --> <div class="panel-heading">List of Marketing Images </div> <div class="panel-body"> <a href="/marketingimage/create"> <button type="button" class="btn btn-lg btn-success">Create New </button> </a> </div> <!-- Table --> <table class="table"> <tr> <th>Id </th> <th>Name </th> <th>Thumbnail </th> <th>Edit </th> <th>Delete </th> </tr> @foreach($images as $image ) <tr> <td>{{ $image->id }} </td> <td>{{ $image->image_name }} </td> <td> <a href="/marketingimage/{{ $image->id }}"> <img src="/imgs/marketing/thumbnails/{{ 'thumb-'. $image->image_name . '.' . $image->image_extension . '?'. 'time='. time() }}"> </a> </td> <td><a href="/marketingimage/{{ $image->id }}/edit"> <span class="glyphicon glyphicon-edit" aria-hidden="true"> </span> </a> </td> <td>{!! Form::model($image, ['route' => ['marketingimage.destroy', $image->id], 'method' => 'DELETE']) !!} <div class="form-group"> {!! Form::submit('Delete', array('class'=>'btn btn-danger', 'Onclick' => 'return ConfirmDelete();')) !!} </div> {!! Form::close() !!} </td> </tr> @endforeach </table> </div> </div> @endsection @section('scripts') <script> function ConfirmDelete() { var x = confirm("Are you sure you want to delete?"); if (x) return true; else return false; } </script> @endsectionلقد بدأنا بتوسيع layouts.master ومن ثم قمنا بفتح content كما يلي: @section('content')ومن ثم استخدمنا Breadcrumb. (مرة أخرى، إذا كنت لا تستخدم الحزمة فاحذف هذا السطر.) بعد ذلك قمنا باستخدام شيفرات Bootstrap أساسية، والتي حصلنا عليها من الموقع الرسمي. وفي النهاية سنجد جدول داخل مُكوّن panel لـ bootstrap بالإضافة إلى زر لإنشاء صورة جديدة، وأزرار أخرى للتعديل والحذف لكل صورة، وستظهر الصور المصغرة لكل صورة في الجدول. سوف ترى في رأسية مُكوّن panel كيف قمنا بالتعامل مع زر create: <a href="/marketingimage/create"> <button type="button" class="btn btn-lg btn-success"> Create New </button> </a>كل شيء واضح، فالجدول ليس معقدا، لكنه تطلب حلقة foreach لطباعة جميع الصفوف (rows): <!-- Table --> <table class="table"> <tr> <th>Id </th> <th>Name </th> <th>Thumbnail </th> <th>Edit </th> <th>Delete </th> </tr> @foreach($images as $image ) <tr> <td>{{ $image->id }} </td> <td>{{ $image->image_name }} </td> <td> <a href="/marketingimage/{{ $image->id }}"> <img src="/imgs/marketing/thumbnails/{{ 'thumb-'. $image->image_name . '.' . $image->image_extension . '?'. 'time='. time() }}"> </a> </td> <td> <a href="/marketingimage/{{ $image->id }}/edit"> <span class="glyphicon glyphicon-edit" aria-hidden="true"> </span> </a> </td> <td>{!! Form::model($image, ['route' => ['marketingimage.destroy', $image->id], 'method' => 'DELETE' ]) !!} <div class="form-group"> {!! Form::submit('Delete', array('class'=>'btn btn-danger', 'Onclick' => 'return ConfirmDelete();')) !!} </div> {!! Form::close() !!} </td> </tr> @endforeach </table>لا توجد أية صعوبة في الشيفرة، يمكنك أن ترى أنني أضفت مساعدات النموذج form helper حول رابط الحذف delete، وهذا لأسباب أمنية، يجب علينا الحذف باستخدام POST بدل السماح بأن تكون مفتوحة بشكل واسع من خلال استعمال GET. سوف تلاحظ أيضا أننا قمنا باستخدام التالي: 'Onclick' => 'return ConfirmDelete();'والتي استخدمناها مع الجافاسكربت لفتح صندوق التأكيد confirm box، حتى لا يقوم المستخدمون بحذف شيء عن طريق الخطأ. ثم في ('section('scripts@ أضفنا شيفرات جافاسكربت التالية، وكملاحظة سريعة، افترضنا أنه لديك ('yeld('scripts@ في صفحتك الرئيسية (master page)، وإذا لم يكن لديك هذا السطر، يمكنك ببساطة إرفاق الجافاسكربت قبل endsection@ التابعة لـ ('section('content@. هذه هي شيفرة الجافاسكربت: <script> function ConfirmDelete() { var x = confirm("Are you sure you want to delete?"); if (x) return true; else return false; } </script>شيفرة بسيطة للغاية. والآن، يجب أن تحصل على صفحة index تعمل بدون مشاكل، قم بتجربة ذلك عن طريق الذهاب بمتصفحك إلى: yourproject.com/marketingimageنُكمل في الجزء الثالث من الدرس إن شاء الله. ترجمة -وبتصرّف- للمقال Basic Image Management Part 2 لصاحبه Bill Keck. حقوق الصورة البارزة: Designed by Freepik.
  10. الخطوة السابقة هي الطريقة الأكثر انتشارًا في حفظ ملفات بوربوينت إلى جهازك بعد الانتهاء من إنشائها، وبالرغم من أن برنامج أوفيس بوربوينت يُقدم العديد من الخيارات المميزة في حفظ وتصدير العروض التقديمية، إلا أن أغلب مستخدمي البرنامج يطبقون الطريقة السابقة دون الاستفادة من باقي الخيارات في حفظ العروض التقديمية. لذا سنشرح لكم في هذا الدرس كيفية حفظ وتصدير ملفات بوربوينت بكفاءة عالية وفاعلية. حفظ العروض بنسبة 16:9 و4:3 (الطول * العرض) قبل البدء بتصميم العروض التقديمية يجب عليك معرفة الحجم الملائم للشرائح وذلك بالقياس مع الوسيلة المستخدمة أثناء العرض، فتغيير أبعاد العرض (حجم الشريحة) بعد حفظه يعني كأنك تبدأ من جديد، وحتى تتجنب المشاكل المتعلقة بحجم الشرائح داخل العرض التقديمي يجب أن تحدد من البداية ما إذا كنت ترغب بحفظها بنسبة 16:9 أو 4:3. حالياً فإن الحجم الأنسب لتصميم الشرائح هو 16:9، هذه النسبة تتوافق مع جميع الشاشات الحديثة، مثل أجهزة العرض الحديثة (بروجكتور) وشاشات التلفاز وأجهزة الحاسوب widescreen، أما النسبة القياسية التقليدية 4:3 فقد أصبحت أقل شيوعاً في الفترة الحالية، ويقتصر استخدامها للهواتف الذكية، أو الشاشات صغيرة الحجم أو عند ند نشرها عبر مواقع متخصصة لعرض ملفات بوربوينت مثل SlideShare، لذا يُفضل غالباً استخدام هذه النسبة من البداية. وبأي حال، يُمكنك حفظ العروض التقديمية بكلا الحجمين 16:9 و4:3 إن احتجت استخدامها لأغراض متعددة. هذه الطريقة يتبعها جميع مصممي العروض التقديمية المدفوعة، حيث ستلاحظ في معظم المواقع المتخصصة في بيع العروض وجود نسختين من العرض الأولى بنسبة 16:9 والثانية 4:3. والآن نأتي لكيفية إنشاء العروض بنسبة 16:9 و4:3 اذهب لقائمة تصميم، ثم حجم الشريحة، ستلاحظ ظهور خيارين الأول 16:9 والثاني 4:3 كما هو موضح في الصورة يمكنك اختيار نسبة عرض خاصة إن أردت من خلال حجم شريحة مخصص. حفظ الملفات في مسار (مجلد) ثابتفي كل مرة نقوم بها بحفظ ملفات بوربوينت نضطر لتحديد المسار الخاص بحفظ الملف على جهاز الحاسوب، لكن يُمكن تجاوز هذه العملية عن طريق تحديد مسار ثابت لحفظ الملفات، وبمجرد حفظ الملف الجديد ستجد بأنه انتقل للمجلد الذي قمت باختياره. اتبع الخطوات التالية: من قائمة ملف، اختر خيارات، ثم من القائمة الجانبية اليمنى اختر حفظ، ثم ضع علامة (√) على خيار حفظ إلى الكمبيوتر بشكل افتراضي، وفي خانة موقع الملف المحلي الافتراضي ضع مسار المجلد الذي ترغب بحفظ العروض داخله باستمرار. حفظ العرض كملف فيديوأغلب مستخدمي برنامج بوربوينت يقومون بحفظ العروض التقديمية بصيغة PPT وهي الصيغة الأساسية الخاصة ببرنامج بوربوينت، لكن في بعض الأحيان نحتاج إلى حفظ العرض كملف فيديو لرفعه على مواقع مشاركة الفيديو أو لاستخدامات أخرى مختلفة، وبدلاً من القيام بحفظ العرض وتحويله إلى ملف فيديو باستخدام بعض البرامج المتخصصة، يُمكنك حفظ العرض كملف فيديو مباشرة من خلال بوربوينت بكل سهولة. في الواقع يوجد طريقتان لحفظ العرض على هيئة فيديو، الأولى: توجه إلى القائمة ملف، حفظ باسم، ومن القائمة المنسدلة حفظ كنوع اختر MPEG-4 VIDEO، ستلاحظ أن العرض حُفظ على هيئة ملف فيديو mp4، لكن من خلال استخدام هذه الطريقة يتم حفظ الفيديو بحسب الإعدادات التلقائية المسبقة للملف. أما في حال اختيارك لـ WINDOWS MEDIA VIDEO فسيتم حفظ العرض بصيغة wmv إن احتجت لتخصيص إعدادات ملف الفيديو فيمكنك اتباع الطريقة الثانية: ملف، تصدير، ثم اختر إنشاء فيديو، بعدها بإمكانك اختيار جودة الفيديو بحسب رغبتك مثل عرض تقديمي عالي الجودة أو حفظه للهواتف الذكية، بالإضافة إلى تحديد زمن ظهور كل شريحة داخل الفيديو. كما هو موضح في الصور التالية. تصدير العرض بصيغ متعددةيُمكنك حفظ العروض التقديمية بصيغ مختلفة أخرى، فبرنامج بوربوينت يقدم لك العديد من الخيارات المنوعة من ضمنها حفظ الملف على هيئة PDF أو على هيئة صورة بصيغة JPEG أو PNG، فقط اختر من القائمة المنسدلة الصيغ المناسبة لك، كما يمكنك حفظ الملف على هيئة صور من خلال القائمة تصدير تمامًا كما هو الحال في حفظ الفيديو. تأمين العرض بكلمة مرورإذا كنت ترغب بتأمين العرض التقديمي بواسطة كلمة مرور، فيمكنك بعد الانتهاء من حفظ الملف اتباع الخطوات التالية: من القائمة ملف اختر معلومات، ثم حماية العرض التقديمي، ثم اختر التشفير باستخدام كلمة مرور. في الخانة المنبثقة قم بكتابة كلمة المرور لتشفير الملف ثم اضغط موافق إلى هنا نأتي إلى نهاية الدرس الأول من هذه السلسلة، سنتعرف في الدرس القادم على كيفية تحديد توقيت العرض التقديمي بفاعلية.
  11. من أهم العوامل الدالة على فاعلية العروض التقديمية هي التزام مقدم العرض بالمدة المتاحة له، وأحيانًا يضطر المقدم لتجاوز عدة نقاط هامة داخل العرض نظرًا لضيق الوقت، أو من خلال التطرق إلى معلومات إضافية غير ضرورية لشعوره بانتهاء ما يود تقديمه بصورة سريعة جدًا. هذه المشكلة تنتج دائمًا من سوء تقدير مقدم العرض أثناء إنشائه للعرض التقديمي، إذ أنه لم يتح لنفسه فرصة كافية للتدرب على المدة المحددة بصورة فعالة، أو من خلال تقدير مدة ثابتة لكل شريحة من شرائح العرض بطريقة ارتجالية. وبالرغم من أن برنامج أوفيس بوربوينت يُقدم أدوات فعالة جدًا في التدريب على مدة العرض إلا أن الكثير من المستخدمين لا يلتفتون لها، لذا سنقوم في هذا الدرس بشرح كيفية تحديد توقيت العرض التقديمي بفاعلية باستخدام برنامج بوربوينت. في البداية يجب أن نلتفت إلى أن التمرين على التوقيت يكون بعد انتهائك من إنشاء العرض بالكامل، حتى تستطيع التحكم والتعديل بطريقة فعالة فيما بعد. خاصية أوقات التمرينهذه الطريقة تساعدك على تحديد التوقيت المثالي لكل شريحة أثناء العرض، وهي تُعد أداة فعالة جدًا في حال رغبتك بانتقال الشرائح تلقائياً بعد مدة محددة دون الحاجة للنقر، حيث يقوم البرنامج بتسجيل مقدار الوقت اللازم لكل شريحة أثناء قيامك بالتمرن على العرض. لاستخدام هذه الخاصية اتبع التالي: من شريط القوائم اختر عرض الشرائح، ستظهر لك أوقات التمرين، بعد ذلك ستلاحظ فتح الشرائح في وضع ملء الشاشة مع وجود شريط لتسجيل المدة الزمنية أعلى الشاشة.بعد انتهاء الشريحة الأولى انتقل بالسهم للشريحة التالية وهكذا، وبعد الانتهاء من كافة الشرائح قم بالضغط على زر Esc وسيقوم البرنامج بعرض الزمن المستغرق لكل شريحة. خاصية تسجيل عرض الشرائحخاصية تسجيل عرض الشرائح تشبه تمامًا خاصية أوقات التمرين، لكن مع اختلاف بسيط وهو القدرة على تسجيل الصوت من ميكروفون الحاسوب أثناء التدريب، مما يتيح لك محاكاة العرض التقديمي بطريقة فعالة للغاية. ويُمكن من خلال هذه الميزة تسجيل جميع الفقرات التي ترغب بإلقائها أثناء العرض بالتزامن مع ظهور الشرائح المختلفة، بالإضافة إلى تسجيل توقيتات الشرائح والحركات. لاستخدام هذه الخاصية اتبع التالي: من شريط القوائم اختر تسجيل عرض الشرائح، ستظهر لك قائمة منبثقة بخيارين، الأول يتيح لك التسجيل من بداية العرض، والثاني يتيح لك التسجيل من شريحة محددة، اختر ما تراه مناسبًا لك. بعد ذلك سيظهر لك مربع حوار لتحديد الخيارات الخاصة بالتسجيل، الأول تسجيل التوقيتات والحركة ضمن التسجيل، والثاني السرد والحبر ومؤشر الليزر. في حال اختيارك لتسجيل السرد فيجب عليك أن تتأكد من تشغيل الميكروفون والتحدث من خلاله بصورة واضحة. بعد ذلك قم بالنقر على بدء التسجيل، ستلاحظ انتقالك إلى وضع ملء الشاشة مع وجود نفس خيارات ميزة أوقات التمرين. وفي حال انتهائك من تسجيل كافة الشرائح المطلوبة قم بالضغط من لوحة المفاتيح على مفتاح Esc ستلاحظ وجود أيقونة الصوت إلى جانب كل شريحة، وفي حال الاستمرار لنهاية الشرائح سيتم نقلك للصفحة الرئيسية تلقائياً. عند التأشير على أيقونة الصوت داخل الشريحة بعد التسجيل، سيكون بوسعك التحكم بها من خلال رفع مستوى الصوت أو خفضه أو نقل الأيقونة إلى أي مكان آخر داخل الشريحة. إن لاحظت وجود أي أخطاء في التسجيل، فيمكنك استخدام خاصية مسح التسجيل وذلك من خلال التوجه إلى السهم بجانب تسجيل عرض الشرائح ثم اختر مسح. سيظهر لك 4 خيارات وهي: إلغاء التوقيتات الموجودة على الشريحة الحالية.إلغاء التوقيتات الموجودة على كافة الشريح.إلغاء السرد الموجود على الشريحة الحالية.إلغاء السرد الموجود على الشريحة الحالية. خاصية إخفاء الشريحةبعد استخدامك لإحدى الخصائص السابقة قد تجد أنك بحاجة إلى إزالة بعض الشرائح، لكن بدلاً من حذفها نهائياً يُمكنك المحافظة على كافة الشرائح كما هي واستخدام خاصية إخفاء الشريحة، والتي تتيح لك التنقل بين الشرائح الأخرى أثناء العرض دون وجود الشرائح المخفية، فمثلاً لو قمت بإخفاء الشريحة رقم 3 ستلاحظ أثناء العرض أن البرنامج انتقل من شريحة 2 إلى شريحة 4 ودون الحاجة لحذف الشريحة نهائياً. لاستخدام هذه الخاصية اتبع الآتي: من شريط القوائم، اختر عرض الشرائح، ثم قم بتحديد الشريحة (أو الشرائح) المراد إخفائها، بعد ذلك قم بالنقر على إخفاء الشريحة كما هو موضح في الصورة. إلى هنا نأتي إلى نهاية الدرس الأول من هذه السلسلة، سنتعرف في الدرس القادم على كيفية إدراج ملفات الفيديو والصوت إلى شرائح PowerPoint.
  12. لا بدّ لكل مستقلّ أن يمرّ خلال مسيرته المهنيّة بتلك اللحظة التي يحتاج فيها إلى كتابة عرض للعمل على مشروع معيّن، وإن لم تكن خائفًا من فكرة كونك بائعًا للخدمات فإن هذا الخوف سيتضاعف بعد أن تدرك الكمّ الهائل من المستقلّين الذين يقدّمون العروض أملًا في الحصول على العمل. وكل هؤلاء وعلى اختلاف مشاربهم مجتمعون على قول عبارة (اخترني)، فهل يمكنك إيصال صوتك مع وجود كل هذه الأصوات؟ لنقم بذلك إذًا. سنخوض معًا في التفاصيل الدقيقة التي تتضمنها عملية كتابة عرضك كمستقلّ وسأستفيد من خبرتي التي اكتسبتها من العمل في هذا المجال لسنوات عديدة لأساعدك على إبراز صوتك من بين الجموع، وسيتضمن ذلك: أفضل الأساليب المتّبعة.الأخطاء الواجب تجنّبها.كيف تتابع نتائج العرض الذي ستقدمه.كيف تعدّل أسلوبك استنادًا إلى النتائج التي تابعتها.كيف أكتب عروضي عادة لم يكن حالي عندما بدأت بالعمل كمستقلّ مختلفًا عن حال أي مستقلّ جديد، إذ لم أكن أفقه شيئًا، أضف إلى ذلك صفة العناد والتعنّت، لتحصل على قائمة طويلة جدًّا بالأخطاء التي ستقترفها في فترة زمنية قصيرة؛ لذا سأوضّح لك الأخطاء التي وقعت فيها بدلًا من تعدادها ووصف سوءها فقط. النصّ التالي هو عرض كنت سأكتبه بهذه الطريقة لو لم أتعلم من الأخطاء التي ارتكبتها سابقًا. كنت في السابق معتادًا على كتابة بعض العروض الشاملة التي أمتدح فيها نفسي على الدوام، ولكن عندما أنظر إلى هذه العروض اليوم فإني أشعر بالغثيان، لا بل سيكون تعبير (الغثيان الشديد) أفضل في هذا الموقف، فالدعابة لن تنفع أحدًا هنا. حان الوقت الآن لتقسيم هذا العرض إلى أجزاء متعدّدة ومعرفة الأخطاء التي يحتويها بعد أن تعرّفنا إلى هذا الأسلوب الفظيع في كتابة العروض، وسنبدأ بتحليل ونقد أسلوبي القديم هذا من منظور عامّ قبل الولوج إلى التفاصيل، وسيساعدك هذا على فهم الأمور العامّة بصورة جيّدة. بعض النقاط العامةكل ما فعلته هو التبجحلن يبدو هذا العرض سيّئًا عند النظر إليه للوهلة الأولى وكلّ شيء فيه صحيح، فقد تكلّمت عن خبرتي وذكرت ما قمت به من أعمال، وأشرت إلى ما أفتخر به من إنجازات في العمل، ثم أعطيت رابطًا لمعرض أعمالي، وقدّمت شكري في نهاية العرض. ما الخطأ في كل ذلك؟ إن نظرت إلى العرض بإمعان فإنك ستلاحظ سمة تتواتر فيه من البداية إلى النهاية، إنها سمة التبجّح والتباهي، مع الاكتفاء بتقديم مادة قليلة إلى الشخص أو الفريق الذي أرسلت إليه هذا العرض. لم أجب عن أي شيء فيما سردتهكما قلت لك سابقًا، فقد كنت أستخدم هذا الأسلوب لكل طلب عمل يصادفني. إذًا باعتقادك ما هي نسبة الإجابات التي حصلت عليها بعد إرسال هذا النوع من العروض لمرّات عديدة؟ الإجابة هي 0%، ولنأخذ عملية صيد الأسماك كمثال لفهم سبب انخفاض النسبة إلى هذا المستوى. عندما ترغب في صيد الأسماك يكون أمامك خياران، الأوّل أن تستخدم طُعمًا تحبّه جميع الأسماك بلا استثناء، والثاني استخدام طُعم خاص لصيد نوع معيّن من الأسماك. لقد كنت أستخدم الطُّعم الأوّل والذي يبدو أنه يرضي جميع أنواع الأسماك، ولكنّه لم يجذب سوى ما يتغذّى في الأعماق. الكثير من المعلومات غير ذات الصلةإن كنت أريد تقديم عرض لأعمل كمصمّم في المشروع، فما الفائدة من ذكر خبرتي في التطوير ضمن العرض؟ كنت أظنّ مسبقًا أنّ ذلك سيدلّل على مهاراتي المتنوّعة وسيرضي ذلك العميل ويدفعه إلى التعامل معي. ولكن ما فعلته في الواقع هو أنّي قدّمت إلى قارئ العرض انطباعًا مفاده أنّي لا أعير مشروعه الاهتمام اللازم، أو حتّى أنّي لا أمتلك القدرة ربّما على فهم ما أقرؤه. لم أُظهر شخصيتي في العرضألم تلاحظ أثناء قراءتك لهذا العرض أنّك قادر على إزالة اسمي واستبداله باسمك بكل سهولة؟ من المؤكّد أنّ كل هذا التباهي لن يكون ملائمًا في هذه النقطة من مسيرتك المهنية، ولكن يمكنك تبديل الاسم دون الحاجة إلى تبديل شيء آخر. للأسف هذا هو الحال لأنّي لم أقم بأي شيء لإظهار شخصيتي في هذا العرض. لن تنفعك كل تلك التفاصيل إن لم تظهر شخصيتك في العرض، وسيكون عرضك سريع النسيان. إنه طويل جداألم تلاحظ طول هذا العرض؟ يبدو الأمر وكأنّي أحاول كتابة موضوع إنشاء للمرحلة الثانويّة لأبيّن السبب الذي يجعلني أفضل من ملايين الأشخاص الذين يغرقون بريدك الإلكتروني وهم يطلبون العمل على هذا المشروع. يجب على العميل أن يقرأ ويتفحص عددًا كبيرًا جدًّا من العروض عندما يرغب في توظيف مستقلّ لإنجاز مشروعه الخاصّ. إن طلبت من شخص يتصفّح العديد من رسائل البريد الإلكتروني قراءة عرض مطوّل كهذا العرض فهذا يعني دعوتك إياه إلى المرور على عرضك هذا مرور الكرام أو تجاوزه في أسوأ الأحوال. تفكيك العرض إلى أجزاءبعد أن تعرّفنا على النقاط الأساسية الأربعة التي جعلت العرض غير ذي نفع أو فائدة، دعنا نفكّكه إلى أجزاء ونتفحّص العبارات والجمل التي كانت سبب كلّ هذه المشاكل. ذكر العمر وسنوات الخبرة كنت أعتقد دومًا أن ذكر عمري وسنوات خبرتي من الأمور الجيدة. كنت أظنّ أن العميل سينبهر عندما يرى عمري خصوصًا عندما كنت مراهقًا وأنه سيرغب بالتعامل معي الآن ليؤسس لعلاقة متينة وراسخة ستستمرّ معي إلى الأبد. ولكن كان هذا خطأً فادحًا. عندما تذكر عمرك أو سنوات خبرتك في العرض الذي ستقدمه فإنّك تعطي انطباعًا إلى العميل بالخوف من عدم القدرة على تقديم ما هو جيّد لهذا المشروع. وهذا ما يحدث بالفعل، فأنت كمن يصنع نظّارة بعدسات ورديّة لتظهر بمظهر جيّد قد حدّدته بنفسك مسبقًا. ذكر كل شيء أقوم به إن كنت قاسيًا مع نفسي فمن سيكترث لهذا الهراء؟ هل يبحث العميل عن مصمّم أم مطوّر؟ مدوّنٍ أم كاتب؟ من النادر أن يبحث العملاء عن شخص يمتلك مجموعة من المهارات، لذا فإن المبالغة في عرض خبراتك يجعلك تبدو بمظهر الأحمق. في الواقع، إن شاهدت عرضًا يتضمّن مجموعة من المهارات في التّصميم أو التطوير فمن الأفضل أن تتجاهله، إلا إن كنت تريد أن تبدو أحمقًا كما كنت أنا كذلك بالتأكيد. التكلم بدون فائدة عن جدارتي بهذا الموقع يمكنك مدح نفسك بالطريقة التي تريدها وحسبما تقتضي الحاجة، ولكنّ ذلك لن يغيّر شيئًا من الواقع. إذ يمكن للعميل أن يجد ما ذكرته أو لا يجده بمجرّد النّظر إلى معرض أعمالي؛ لذا أصدقك القول أن كلّ ما حصلت عليه هو أنّي جعلت نفسي أبدو أقلّ خبرة مما أنا عليه في واقع الحال. الأساليب الأفضلبعد أن تعرّفنا معًا على مثال جيّد عن الأمور التي يجب عليك تجنّبها، حان الوقت للتعرف على ما يجب عليك فعله في هذا الصّدد. سأطرح فيما يلي بعض الأمثلة على عروض قوية تستند على أرض ثابتة، عروض تستحق القراءة وتستحق الاختيار. نصائح لصناعة عرض جيدمن المؤكّد أن بعض الأفكار قد تبلورت لديك عن الأمور التي تجعل العرض جيًّدا بعد الاطلاع على الأخطاء التي ارتكبتها في عرضي الفظيع. ولتتشكّل لديك الصورة الكاملة عن الموضوع إليك بعض الإرشادات التي تضمن لك الحصول على عرض جيّد إن التزمت باتباعها. أبقه قصيرًا، فقرتان على الأكثر.لا تخرج عن الموضوع.لا تذكر عمرك وسنوات خبرتك على الإطلاق.لا تتباهى.أبقه بسيطًا.أظهر شخصيتك ولكن كن متواضعًا.تبدو هذه الخطوات سهلة أليس كذلك؟ عظيم، لنلق نظرة الآن على نموذجين من العروض التي يمكنك استخدامها. سيسلّط المثال الأول الضوء على ما ستفعله إن حصلت على طلب قصير لا يوضّح فيه العميل متطلّباته بصورة جيّدة. أما المثال الثاني فسيقدم مخطّطًا للطريقة التي ستجيب بها على الطلب الذي يحتوي على معلومات مفصّلة، مثل التخصّصات والأجر المطلوب والوقت الأمثل للاتصال. المثال الأول المثال الثاني: لماذا تجدي هذه الأمثلة نفعاحقّق هذان المثالان النتائج المرجوّة منهما لأنهما يستوفيان المعايير المطلوبة في الطلبات المُقدَّمة، ومن المؤكّد أن هذين المثالين يتطابقان بشكل تامّ مع الإرشادات التي استخلصناها من دراسة العرض القديم وتحليله ونقده. وللمراجعة فقط سنمرّ بسرعة على تلك الإرشادات: كلاهما قصير.عرض الأعمال، والسيرة الذاتية (إرفاق السيرة الذاتيّة أمر اختياري، أرفقها عندما يّطلب منك ذلك) ومعلومات الاتصال، كلّ ذلك معروض بصورة واضحة.لا وجود لمعلومات غير ذات صلة.كلاهما يدخل في صلب الموضوع بصورة مباشرة.أنت الآن على أتمّ الاستعداد للبحث عن العملاء وتمتلك الطريقة الصحيحة للتعريف عن نفسك، ماذا تنتظر إذًا؟ وقت التحديأرني في التعليقات كيف ستُظهر شخصيتك في الأمثلة السابقة، أتطلّع شوقًا إلى قراءة تعليقاتكم. ترجمة ـ بتصرّفـ للمقال How to Write a Freelance Pitch That Gets Clients لصاحبه Jamal Jackson. حقوق الصورة البارزة: Designed by Freepik.
  13. سمح لي حضوري لأكثر من مؤتمر تقني خلال الأشهر الماضية فرصة التّعرف على بعض الشّركات النّاشئة وأصحابها الموهوبين الذّين جاؤوا من مختلف دول العالم. لكنّني للأسف لم أكن لأفهم ما تقوم به تلك الشّركات إلّا بعد رحلة طويلة لفكِّ رموزِ عروضها المُرْبِكةِ. من بين أهم النشاطات التي نقوم بها مع الشّركات النّاشئة في Y Combinator هو مساعدتها على صقل عروضها التّجريبية ليوم التّقديم Demo Day. طريقتك في العرض مهمّة جدّا لأنّ المستثمرين (وغيرهم مثل الصّحافة ،الموظّفين والعملاء المحتملين) ليس عليهم بذل طاقة ذهنية لاستنباط ما تتكلّم عنه فإذا حاولت توجيه خطابك غير المفهوم لشخص ما فإنّه على الأرجح سيغلق على دماغه بالشّمع الأحمر ثمّ يتفقّد هاتفه (إن كان بين الحضور) أو يومئ لك برأسه مخططّا للهروب (إن كنت فقط أنت وهو). كن على يقين أن تَفَقُّدَ المُسْتَثْمِرِ لهاتفه يعني خسارتك له لأنّه ببساطة قد فقد اهتمامه بعرضك. ستتمكّن في مدة ثلاث دقائق أن تنقل ما بين فكرة واحدة وثلاثة أفكار والتي بإمكانها أن تعلق بأذهان جمهورك ويتذكّروها بعد العرض لذا فإن هدفك إجمالا يتمحور حول جعل تلك النّقاط الثّلاثة مقنعة قدر الإمكان بحيث أنّهم سيريدون متابعة تقديمك. لا تجعل هدفك إقناعهم بالاستثمار معك مباشرة عن طريق تزويدهم بالبيانات التي يُمكنك أن يطلبوها منك لاحقًا إن هم أبدوا اهتمامًا بما تقوم به. في ما يلي أساسيّات حول كيفية تقديم عرض شركة ناشئة : تكلّم ببطء: فهذا هو أهمّ شيء يمكنك القيام به: في اللّحظة التّي يُصبح فيها حديثك غير مفهوم سأبدأ في النّظر إلى هاتفي لأنّني لن أبذل جُهدّا مُضاعفا لمجرّد فهم ما تقو ل. إذا لم تكن تُقدّم بلغتك الأم (كأن تُقدّم بالإنجليزية مثلا والإنجليزية ليست لغتك الأمّ) أو أن هذه اللغة ليست اللغة الأم لجمهورك (كأن تُقدّم عرضًا بالإنجليزية لجمهور من المُستثمرين الصينيين) فأنت مطالب أن تتحدّث أبطأ مما عهدت.على عرضك أن يتّبع التّسلسل التّالي:السّوق والمشكلةالحلّ الذي تقترحهدليلك على أنّ الحلّ الخاصّ بك يعمل أو سيعمل (شعبية الحلtraction، المبيعات، خبرة فريقك... الخ) سبق وأن رأيت عروضا لشركات ناشئة كثيرة تتحدّث عن السّوق بإسهاب لكنّها للأسف لا تخبرنا عن ما تفعله بالضّبط. لا تقع في نفس الخطأ.اشرح كل شيء ببساطة وبلغة واضحة: واعلم أن جمهورك ليس بالضّرورة مجموعة من الخبراء لذا استخدم المفاهيم البسيطة والتّشبيهات لتوضيح فائدة المنتج الخاصّ بك وإلّا فإنّك تخاطر بفقدان اهتمامهم وعودتهم لتفقّد هواتفهم.لا تقم بتجريب منتجك (عمل demo) أمام الجمهور: عادة ما تتوقّف هذه العروض/التّجارب. إن كان منتجك رائعا حقّا (مثل سيّارة تقود نفسها) فاعرض شريط فيديو وعندها سيطالب الجمهور المهتّم بعرض تجريبيّ لاحقًا.لا تقم بإظهار لقطات شاشة كاملة لأنّه أقرب للمستحيل أن يفهم جمهورك واجهة المستخدم (UI) بالكامل للوهلة الأولى، إذا كنت ترغب في تسليط الضّوء على عنصر معين فأظهره بضخامة واعرض الجزء الأهم من واجهة المُستخدم فقط.تأكّد أنّ كل ما تعرضه على الشّاشة سهل القراءة، لا تعرض ملفات Excel الخاصة بأرباحك أو صفحة ويكيبيديا الخاصّة بشركتك فلا أحد سيقرأ ذلك. نعم، هذا يعني الاقتصار على كميّة صغيرة فقط من النّص المكتوب ويجب أن يُستخدم النّص كوسيلة توضيحية لما ستتفوّه به فقط.تأكيد آخر على مسألة الوضوح: تأكّد من انسجام خلفيّات عرضك مع النّص وقم بإزالة الرّسومات والصّور المتحرّكة فهي مجرد إلهاء للجمهور وبهرجة من دون فائدة.يوجد العديد من النّصائح التي يُمكن اتّباعها لتقديم عرض ناجح، ولكن على حسب خبرتي فإنّ كل ما تحتاجه معظم الشّركات النّاشئة هو إتقان الأساسيّة منها وحسب. بغض النّظر عن مدى جودة فكرتك أو مدى تقدّمك فيها، إن لم تتمكّن من التّواصل مع جمهورك فإنّ عرضك سيفشل. ترجمة -وبتصرّف- للمقال How to Pitch Your Startup On Stage لصاحبه Justin Kan. حقوق الصورة البارزة: Designed by Freepik.
  14. ليس لديك الوقت لتهتم بتصميم منتجك قليلاً، ومن لديه؟ يظن الكثير من صانعي المنتجات الرقمية أنه يمكن الاستفادة من الوقت الذي سيقضيه بتصميم المنتج في تحسين أدائه أو إضافة محتوى أكثر، لكن يبدو أنها فلسفة خاطئة فالتصميم من أهم الأشياء التي تساعدك بعمل المنتج على أكمل وجه وزيادة المبيعات بشكل رائع. إذا كنت لاتزال غير مهتم بالتصميم فهذه بعض الأسباب التي ستجعلك تعيد النظر قليلاً. التصميم مسؤول عن الانطباع الأولما لم يكن المنتج عبارة عن تصميمات أو أعمال فنية فإن المنتج سواء (فيديوهات تعليمية أو كتب أو تطبيقات وبرامج) الذي يمتلك شكلاً جذاباً وتصميما مبتكرا يمكن أن يقنع المشتري من أول رؤية له بالشراء، كثير مما تريد أن تقوله في صفحة المبيعات يمكنك أن تختصره بتصميم غلاف الكتاب أو ابتكارية في جرافيكس البرنامج. يعكس دقة الصنعاهتمامك بالتصميم سيعكس دقتك لدى العميل واهتمامك بالتفاصيل لإخراج منتج جيد من جميع الجهات، وهذا بالطبع بعد اهتمامك بجودة المحتوى ودقة أداء المنتج فالتصميم يأتي كشاهد مبدئي على دقة عملك وحرفيتك المذهلة. طبيعة البشر البصريةجزء كبير من العقل مخصص للنشاطات البصرية والعين مما يجعل التصميم من أهم المفاتيح المؤثرة على قرار المستخدم بالشراء من عدمه، لذا فقدرة التأثير على المستخدم أو العميل تقع مسؤوليتها الأولى على التصميم وتجربة المستخدم للمنتج. ميزة جيدة للتسويقالتصميم الجيد يمكن أن يلعب دوراً هاماً في التسويق وبناء هوية منتجاتك عن طريق إضافة بعض اللمسات الاحترافية للشعار والغلاف والمحتوى واستخدامها بشكل متكرر في حملاتك التسويقية ومع التسويق الجيد يمكنك الوصول لجمهورك المستهدف عن طريق تصميم المنتج المخصص لتلك الفئة بطريقة جميلة. كل هذه أمور جيدة يمكنك تحقيقها عن طريق التصميم، والتصميم بحد ذاته لا يقتصر على التصميم الخارجي للمنتج بل يمكنك أيضاً استخدامه بطريقة عرض المحتوى أو عمل بعض النماذج التفاعلية لتضفي حيوية على المنتج خارجياً وداخلياً. لكن لتصنع تصميماً جيدا لمنتجك فإنه يجب الانتباه لصفات التصميم الجيد الذي يجذب المستخدم ويجعله مرتبطا بمنتجك ارتباطاً شخصيا يعكس مفهوم أنه استحق الثمن الذي اشتراه به، وهذه بعض صفات التصميم الجيد التي يمكنك مراعاتها. مميزات التصميم الجيدبسيطالتصميم الخالي من التعقيد هو أجمل التصاميم، لا يجب أن يكون تصميمك مزدحماً ليصبح جيداً، فقط على حسب إمكانياتك وما تريد أن يفهمه المستخدم من التصميم هو ما سيجعلك تعمل على تصميم جيد، إذا كنت ستصمم منتجا بنفسك فلا تفكر بطريقة ماذا أضيف لكي يصبح التصميم جيداً بل فكر بطريقة ماذا أحذف ليصبح التصميم جيداً. مبتكرالابتكارية في التصميم والتعبير عن فكرة المنتج وهدفه سيصب في صالح المنتج بالطبع، فكر بتصميم يحمل رؤيتك أو فلسفتك عن المنتج، قم بعمل تصميم يحمل شيء من ثقافتك بطريقة عصرية، أضف شيئا مميزاً للتصميم كجملة أو صورة أو رمز يوجه رسالة للمستخدم يخبره أن المنتج قيم. يحكي قصةلا شيء يجذب الإنسان مثل قراءة القصص فطبيعتنا تأبى التشتت إلا بعد معرفة نهاية القصة، يمكن للتصميم أن يحكي قصة في نموذج واحد كالغلاف ويمكن أن يحكي قصة مثيرة طوال استخدام المنتج مع إضفاء بعض عناصر التشويق والغموض سيصبح تصميمك مدهشاً بالفعل. تفاعليالتصاميم التفاعلية في ازدياد وإضافة بعض الحيوية للمنتج سيقوي رابطة المستخدم بالمنتج، يمكنك عمل بعض الاستجابات التلقائية عند فعل معين من المستخدم، يمكنك توقع رد فعل المستخدم وترتيب رد فعل يصنعه المنتج للتأثير على مشاعر المستخدم بطريقة إيجابية. لكن كل هذا بالطبع يحتاج منك بعض المعرفة الأساسية ومتابعة الجديد في طرق التصميم، أو اختصار الأمر والدفع لمصمم محترف وإخباره برؤيتك للتصميم وما تريده منه ليقوم لك بالأمر على أتم وجه. سواء قمت بتصميم منتجك بنفسك باستخدام بعض المصادر الأساسية أو قمت بإيكال المهمة لمصمم محترف فالأمر يستحق العناء، منتجك ذو جودة عالية فهو يحتاج تصميم مميز. حقوق الصورة البارزة: Designed by Freepik.
  15. واحدة فقط من تطبيقات الطّقس هذه تسعى لحلّ المشكلة الحقيقيّة: أمورٌ متباينة تقع وسط مجتمع التصميم. لدينا من جهةٍ كتاباتٌ بديعة من أمثال راين سينقر وجولي شو، تدفع بحرفتنا قُدُمًا. ولدينا من الجهة المقابلة عدد متزايد ممّن يضعون أعمالهم ويتناقشونها على Dribbble، ما مُجمل حصيلته الدفع بحرفتنا إلى الوراء. ليس هذا المقال عن Dribbble نفسه، ولكن عمّا يُجلّه مجتمع Dribbble. سأستعمل في ما يأتي مصطلح "تصميم المنتجات" Product Design، ولكنّ ذلك يشمل أيضا تصميم تجربة المستخدم UX وتصميم التفاعل Interaction Design. ”يبدو مذهلًا!“ هي ما يكافئ به مجتمع Dribbble العملَ السّطحيّ خلال مراجعتي ﻷعمال تصميم العديد من المُتقدّمين إلى وظائف التّصميم العام الماضي، لدى فيس بوك والآن في إنتركوم، لاحظت نمطًا مثيرا للقلق. يقوم كثيرٌ من المصمّمين بالتّصميم فقط لينالوا إعجاب نُظرائهم بدل أن يعالجوا مشاكل عمليّة حقيقيّة. طويلا ما كان يمثّل هذا الأمر مشكلة في مجال الإعلان الإبداعيّ (حيث كثيرا ما يميل العمل الإبداعيّ إلى نيل الجوائز أكثر من تحقيق اﻷهداف التّجارية اﻷساسيّة للعملاء) وهو الآن يبرز أكثر فأكثر في مجال تصميم المنتجات. الكثير من أعمال تصميم المنتجات التي رأيت مؤخرا كانت سطحيّة، ومنجزة بعين صوب Dribbble. أشياءٌ تبدو رائعة ولكن لا تعمل بشكل جيّد. تنفيذٌ متقن لبكسلات التّصميم المسطّح، ولكن عملٌ لا يستهدف أغراضا تجارية حقيقية، لا يحلّ مشاكل يواجهها النّاس يوميًّا، ولا يأخذ بعين الاعتبار نظاما تجاريّا بشكل كليّ. Dribbble نفسه يساهم في صياغة الحوار إلى حدٍّ ما، بكونه الواسطة التي تتشكّل من خلالها تلك الرسائل، وبإبرازه للواحات الألوان وغيرها من التفاصيل السّطحية الشائعة في مجال تصميم واجهة المستخدم. النّاس يلاحظون ويقلّدون. الأغلبية السّاحقة من أعمال تصميم المنتجات في Dribbble تبدو متطابقة. سواءً كان برنامجا اجتماعيا، برنامج محاسبة، موقعًا للتسويق، أو تطبيق طقس، يتمّ اعتماد نفس الأساليب. أغلق عينيك قليلا ثمّ حاول أن تحدد الفرق بين هذه التّطبيقات: أهمّ أعمال تصميم المنتجات هي عادةً أشدُّها قبحا في المقابل، أفضل طالبي الوظائف الذين رأيتهم قاموا بإرسال منهجيّة تفكيرهم. رسومات و مخططات بيانية، إيجابيات وسلبيات، مشاكل حقيقية، مساومات وحلول. نماذج مبدئية Prototypes تبين كيفية التفاعل والحركة. أشياء تنتقل، تتغير، وتتحرك. أشياء تستعمل بيانات حقيقية. أسوء المتقدمين أرسلوا ملفات PNG مسطحة. ملفات PDF مليئة بالإطارات الشبكية Wireframes. لا فيها تعبير عن السياق ولا عن المشكل الذي يُقصد حلّه. قد تبدو ملفات PNG المتقنة تلك رائعة على Dribbble، لكنها ستفقد من قيمتها إذا اتُّخذت كأداة تصميم أساسيّة في بيئة صنع منتجات حقيقية. لهذا السبب يُعدّ قيام بعض المُصمّمين بإعادة تصميم أعمال شركات أخرى ونشرها مضيعة وقت (كأن يقترح مُصمم ما إعادة تصميم لموقع أو لشعار)، كما هو الحال في اقتراحات إعادة تصميم شعار ياهوو، نظام iOS، إعادة تصميم واجهة فيس بوك، أو تويتر أو حتّى إعادة تصميم شعار الخطوط الجوية الأمريكية، وغيرها الكثير. لا يدرك الناس السّياق ولا منهجيّة اتخاذ القرارات في تلك المشاريع، ليسوا على علم بالمتطلبات و القيود، ولا بسياسة الشركة. باعتبار أنّ تصميم المنتجات يرمي إلى حلّ مشاكل لمُستخدمين في إطار قيود تجارة معينة، فالأمر ببساطة أنّ الكثير ممّن يطلقون على أنفسهم مصمّمي منتجات/واجهة المستخدم هم في الحقيقة يمارسون الفنّ الرقمي Digital Art. هم فنانون ينجزون أشياء جميلة المظهر، ما يعدّ بالتأكيد مهارة مهمّة، لكنهم ليسوا يمارسون تصميم المنتجات. تصميم المنتجات يُعنى بمهمّة، برؤية، و بهندسة بدءا من التصور العامّ ونزولا إلى تفاصيل مستوى البكسلات، يجب على المصمّمين أن يضعوا نصب أعينهم مهمّة شركتهم، رؤيتها، وهندسة منتجها. يجب أن يمرّ كل شيء يقومون به من خلال هذا الطّريق. ينشأ التصميم من أعلى الشّركة ابتداءً بمهمّتها، ومن ثَمّ برؤيتها. من الصّعب جدّا إنجاز تصميم جيّد في غياب مهمّة ورؤية واضحتين. لا تستهن أبدًا بأهميّة هذا اﻷمر. إذا كانت شركتك تفتقر إلى مهمّة واضحة، فيجدر بك المبادرة إلى خلق واحدة. بعد المهمّة و الرؤية تأتي هندسة المنتج. ليست الهندسة التقنيّة، وإنّما باﻷحرى أجزاء المنتج وعلاقة بعضها ببعض. هي النظام في حدّ ذاته. في صباح أوّل يوم عملٍ لي في فيس بوك، قام كريس كوكس (نائب رئيس المنتجات) بإلقاء كلمة تقديميّة رائعة (بإمكانكم مشاهدة بعض منها هنا). بحضور مُوظّفين من أقسام متنوّعة في الشّركة، وبينما كان بإمكانه الحديث عن الكثير من الأمور، أخذ يركّز على شرح هندسة المنتج، وعلاقته بمهمّة الشّركة. بالنّسبة لفيس بوك، تلك الهندسة هي عبارة عن مجلّد ضخم يضمّ مجموعة من اﻷشخاص، وأصدقائهم، واهتماماتهم؛ يضمّ أيضا مجموعة من الشّركات، ابتداءً من كبرى الشّركات ونزولا إلى المتاجر المحليّة الصّغيرة. وفوق ذلك المجلّد خارطة تظهر العلاقة بين تلك اﻷشياء كلّها. إنّه وصف واضح وضوح الشّمس لهندسة المنتج، ومرتبط مباشرة بمهمّة الشّركة. حسب تجربتي، من الصّعب جدّا القيام بتصميم جيّد في ظلّ غياب هندسة منتج واضحة المعالم. في العديد من الأحيان، وتماما كما هو الحال مع المهمّة، يجدر بالمصمّم أن يساعد على تحديد هذه الهندسة و تطويرها. عندما كنت أصف فيس بوك للشّركاء الخارجيّين، كثيرا ما أرسم على السّبورة مخططات بيانية كهذا: ليست هندسة المنتج هي هندسة معلومات. ليست مجموعة صفحات مرتبطة ببعضها البعض، أو شيئا يظهر النوافذ الفرعية ويشرح ما تفعله اﻷزرار. سيلبّي النموذج المبدئي هذا الغرض بشكل أفضل. هندسة المنتج مستوى أعمق من هذا. إنّها البنية. إنّها اللّبنات. هي تظهر اﻷشياء في النّظام والعلاقة فيما بينها. في انتركوم نتصوّر التصميم وفق هندسة منتجنا: لا أذكر أنّه سبق لي رؤية هندسة منتج على Dribbble. لا زال من النّادر أن ترى مصمّما يتحدث عن كيفيّة ارتباط عمله بمهمّة ما، عن كيفيّة سيره وفق رؤية ما، أو عن موقعه من هندسة منتج ما. يجب أن تكون هذه هي القاعدة وليس الاستثناء. بمجرّد أنّ تكون لديك مهمّة واضحة، ورؤية، وهندسة منتج، بإمكانك أن تبدأ التّفكير في باقي التّفاصيل. في اﻷهداف التي لدى النّاس، فيما يسعدهم، يلبّي احتياجاتهم، ويساهم في نجاحهم. كذلك في الوظيفة التي يؤديها منتجك لهم، أين يعمل بشكل جيد، وأين لا يعمل. الرسومات والخربشات القبيحة والمبعثرة التي تصوّر هذه اﻷشياء هي أهمّ بكثير من ملفّات PNG و PDF التي ينتهي بها المطاف في Dribbble. بالنّسبة لي، ملفّات فوتوشوب و PNG هي الجانب اﻷقلّ أهميّة في العمليّة كلّها من البداية و إلى غاية تقديم منتج جاهز. ما يهمّ أكثر هو حينما تُناقش الإيجابيّات والسّلبيات، حينما تُربط اﻷفكار برؤية الشّركة، أو تُطوّر اﻷشياء بناء على هندسة المنتج. كلّ تلك المخطّطات على السّبورة، كلّ تلك الرّسومات اليدويّة وحلول المشاكل على ظهر المنديل، هي ما يجدر بالمصمّمين أن ينشروه على Dribbble. أروني ذلك. بل إنّ وصفا مكتوبا لما يُقصد بناؤه هو أهمّ بكثير من ملفّات الـ PNG أو PDF. فكّر في أربع طبقات للتّصميم التّصميم عمليّة متعدّدة الطّبقات. من خلال خبرتي، يوجد ترتيب مثاليّ للانتقال بين تلك الطّبقات. أبسطها هو أن تنظر إليها كأربعة طبقات: أرى المصمّم تلو المصمّم يركّزون على الطّبقة الرّابعة دون أن يولوا اهتماما بالطّبقات الأخرى. يعملون من اﻷسفل إلى اﻷعلى، بدل العكس. تُعدّ الشبكة، و نوع الخطّ، و اﻷسلوب الجماليّ أمورا غير مهمّة إذا أُهملت الطّبقات اﻷخرى. يدّعي كثيرٌ من المصمّمين أنّهم يقومون بجميع الطبقات لكّنهم لا يثبتون ذلك تطبيقا، ذلك ﻷنّ رسم صور جميلة والانغماس وسط البكسلات هو أكثر متعة من التّعامل مع قرارات تجاريّة معقّدة وأشخاص بآراء مختلفة. لا بأس في أن تبقى في الطّبقة الرّابعة، لكنّ هذا يعدّ فنًّا لا تصميما. أنت بهذا فنّان ولست مصمّما. سيزداد تصميم اﻷنظمة أهميّة مع وصول الويب إلى المزيد من اﻷشياء سيكون لاختراع الويب أكبر تأثير على المجتمع منذ الثورة الصّناعية. يبلغ الويب كلّ شيء. إنّه في منازلنا، في أماكن عملناـ، عند أسرّتنا حال نومنا، و في جيوبنا أينما ذهبنا. الويب معنا في جميع اﻷوقات. هو ينتقل إلى سيّاراتنا، إلى ملابسنا، إلى اﻷشياء التي نملك، وإلى متابعة صحّتنا. بحلول عام 2020، وإن لم يكن قبله، ستكون جميع الشّركات مبنيّة على الويب. كما قال شارل إيمس مرّة،" في النهاية، كل الأشياء ستتصل ببعضها". تصميم صفحات ويب ساكنة ومرتبطة بعضها ببعض هي مهنة في طريقها إلى الموت. الصّعود الباهر للتكنولوجيات الهواتف والأجهزة المُتحرّكة، واجهات برمجة التطبيقاتAPI ، حزمات تطوير البرمجيّات SDK ، والشّراكات المفتوحة بين مختلف المنصّات والمنتجات يرسم صورة واضحة لمستقبل سنقوم فيه جميعنا بتصميم أنظمةٍ متكاملة. ملفاتُ PDF المليئة بالإطارات الشّبكية هي تسليماتdeliverable في طريقها للاضمحلال، فوتوشوب هو أداة تصميم منتجات في طريق الاضمحلال أيضا. المصمّمون الذين يدفعون حقّا بحرفتنا إلى اﻷمام ينتقلون بين الرّسومات، والسبّورات، وأدوات تصنيع النّماذج اﻷوليّة (Quartz Composer، After Effects، Keynote ، CSS/HTML). هذه إحدى الأسباب للاعتقاد بأنّه يجب على المصمّمين أن يبرمجوا. سواءً وافقت على هذا أم لم توافق، يجب على المصمّمين حتما تحديد المشكلة وحلّها ليس عن طريق البكسلات، ولكن بوصف ما يحصل بين أجزاء النّظام، ثمّ الشّروع في البرمجة وبناء نماذج أوّليّة، ليكون بعدها التّعديل الدّقيق كلّما أظهرت البيانات أمورا لم تكن في الحسبان. يعطي العمل على التّفاعل مع بيانات حقيقيّة تصوّرا أفضل لما عليه اﻷمور. تصميمنا يدور حول الوظائف في انتركوم، نتّبع إطار عمل كلاي كريستنسن للوظائف لتصميم المنتجات. نعمل على حصر كل مشكلة تصميم في وظيفة، مركّزين في ذلك على الحدث المسببّ، على الدافع والغاية، والنتيجة المرجوّة: عندما _______ ، أودّ أن _______ ، حتّى أتسطيع أن _______ . على سبيل المثال: عندما يسجّل مستخدم جديد، أودّ أن أُنبَّه بذلك، حتّى أستطيع أن أبدء معه محادثة. هذا يعطينا وضوحا، ويمكنّنا من ربط هذه الوظيفة بالمهمّة وإعطائها أولويّةً بشكل مناسب. هذا يضمن لنا كذلك التّفكير باستمرار في طبقات التصميم اﻷربع، ويتيح لنا رؤية أجزاء النّظام المتعلّقة بهذه الوظيفة والعلاقات والتفاعلات اللّازمة لتسهيلها. يمكنّنا هذا من التّصميم من اﻷعلى إلى اﻷسفل، مرورا بالنتيجة، فالنظام، فالتفاعلات، قبل الوصول إلى التصميم المرئيّ. بالإضافة إلى استعمال الوظائف، نحن نعمل أيضا على بناء مكتبة أنماط تعكس الطّبيعة المتعلّقة بالنّظام في أعمال تصميمنا. سنقوم بالتّصميم أكثر فأكثر باستخدام شيفرات من المكتبة بدل الاعتماد على الفوتوشوب. ليست هذه الطّريقة مثاليّة، لكنّنا نعمل على تحسينها باستمرار. ترجمة -وبتصرّف- للمقال The Dribbblisation of Design لصاحبه: Paul Adams. tuto-gratuit-photoshop-les-dents-de-la-mer.zip