لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 12/01/15 في كل الموقع
-
عندما يأتي الحديث عن أطقم تحرير المُستندات الأكثر شهرة فإنّ الهيمنة ستكون من نصيب حزمة Office المُقدمة من Microsoft دون منازع، لكن هذا لا يُخفي حقيقة أن المزيد من الحكومات، المنظمات، والأفراد حول العالم ينتقلون للاعتماد على LibreOffice المجاني ومفتوح المصدر، والذي يوفّر ميزاتٍ عديدة تشمل قائمة من بعض أهم ميزات حزمة Microsoft Office. وعلى الرغم من أن قواسم عدّة تجمع بين البرنامجين إلا أنّ فروقاتٍ مُهمة وجوهريّة تُميّز بينهما. سنُناقش في هذا الدرس باختصار بعض القواسم المُشتركة بين LibreOffice و MS.Office كما سنتحدّث عن الفروقات المُهمة بينهما، مُستهلين بذلك سلسلة دروس أكاديميّة حسوب عن حزمة LibreOffice. نشأة LibreOfficeتعود بداية القصّة إلى عام 1985 عندما كتب المُبرمج الألماني Marco Börries المُحرّر النصيّ StarWriter لأنظمة Dos، وكان عمره آنذاك ستّة عشر عامًا. في السنة التاليّة أسّس Marco شركة StarDivision للبرمجيات ضمن مرآبٍ له في مدينة لونبورغ - ألمانيا، اشتهرت الشركة بإصدار طقم أدوات المكتب StarOffice. في عام 1995 أصدرت الشركة النسخة الثالثة من حزمة StarOffice، حيث أعيد كتابتها بالكامل لتُصبح عابرة للمنصّات تعمل على كلّ من أنظمة Windows، OS/2، و Solaris Sparc، وذلك بهدف منافسة طقم المكتب Microsoft Office 95. وهذه هي أقدم شيفرة برمجيّة لا تزال مُضمّنة في تطبيق LibreOffice. في نهاية الربع الثاني من عام 1999 استحوذت شركة Sun على StarDivision بصفقة بلغت قيمتها 73.5 مليون دولار أمريكي، لتفتح بعد ذلك الشيفرة المصدريّة للبرنامج بهدف بناء مجتمع مفتوح لتطويره، مُطلقة الإصدارة المبدئية من OpenOffice.org بناء على النسخة 5.2 من طقم StarOffice بُرخصة مُزدوجة LGPL/SISSL. سارت عملية التطوير بأسلوب مشابه لما تتبعه Google اليوم مع متصفح chrome، حيث تفتح الشركة الجزء الأكبر من الشيفرة المصدريّة للبرنامج باسم chromium وتقود عملية تطوير يُشارك فيها مجتمع مفتوح المصدر، ثم تأخذ الشيفرة وتُضيف عليها ميزاتٍ خاصّة مُتقدّمة لتُعيد إصدارها بشكل مُغلق، أكثر تفوقًا من البرنامج الأساس باسم chrome. لم يأتِ العام التالي (2000) حتى أضيف دعم أنظمة لينكس إلى الحزمة، علاوة على تحسين التوافقيّة مع MS.Office. في عام 2005 تمّ إلغاء الترخيص المُزدوج للبرنامج والاكتفاء بترخيصه تحت رخصة غنو العمومية الصغرى، وفي تشرين الأول من عام 2009 صدرت النسخة الثالثة بتغييرات جوهرية وجذرية بهدف تحسين الأداء، زيادة سرعة الاستجابة، والتقليل من حجم الذاكرة المُستخدمة. ومع بداية عام 2010 استحوذت شركة Oracle على Sun، ما أنتج ثلاث تغييرات بارزة: إنهاء مسيرة حياة StarOffice.إعادة تسمية مشروع OpenOffice.org باسم Apache OpenOffice.انشقاق المجتمع مفتوح المصدر والمُهتم بتطوير OpenOffice.org عن العمل برعاية شركة Oracle والذين كانوا يرغبون منذ فترة طويلة بالتمتع باستقلاليّة عن المشروع التجاري لشركة Sun وقيادتها لعملية التطوير، وإطلاقهم مشروع LibreOffice بالاعتماد على الكود المصدري لطقم Open Office 3.3.اليوم وبعد أربع سنوات على تطوير LibreOffice وصل البرنامج إلى الإصدارة الخامسة، وتمّ اعتماده من قبل غالبية توزيعات لينكس الكبرى، وأعداد متزايدة من الحكومات، المنظمات، والأفراد. فروقات عامةيرى البعض أنّ مقارنة مُنتج مدفوع مثل MS.Office مع آخر مجاني يعمل عليه فريق تطوعي مثل LibreOffice أمرٌ غير عادل، إلا أن المُنتَجين يملكان العديد من الخصائص المُتشابهة. بل ما هو أكثر من ذلك؛ ففي حين أن MS.Office 2013 متوافق مع كلٍ من إصدار Windows السابع (وما يليه)، ونظام OSX؛ فإنّ المكتب الحرّ يدعم كافة إصدارات Widows علاوةً على توزيعات لينكس ونظام OSX. بكل الأحوال فإنّ مقارنتنا هنا لن تدور حول أيّ واحدٍ منهما هو "الأفضل" أو "صاحب الميزات الأكثر"، وإنما لتتحقّق فيما إذا كان عملك يتطلّب ما تُقدّمه Microsoft أو أنّه يمكنك الحصول على ما تريد من بديل مجانيّ ومفتوح المصدر لتوفّر بعض المال. تُقدّم حزمة MS.Office عددًا من البرامج الأساسيّة أهمها؛ محرّر نصي (Word)، مُحرر جداول حسابية (Excel)، العروض التقديميّة (PowerPoint)، إدارة قواعد البيانات (Access)، مدير معلومات شخصيّة وعميل بريد (Outlook)، تدوين الملاحظات ومدير تعاون جمعي (OneNote)، برنامج للنشر المكتبي (Publisher). إلى جانب عدد من الأدوات الأخرى الأقل شهرةً واستخدامًا. في المقابل تشمل حزمة LibreOffice على محرّر نصي (Writer)، مُحرر جداول حسابية (Calc)، العروض التقديميّة (Impress)، إدارة قواعد البيانات (Base)، ويغيب عنها بدائل للأدوات الأخرى، إلا أنها تشمل علاوةً على ما سبق برنامج (Draw) للرسم المُتجهي والذي يُمكن اعتباره مُشابهًا لبرنامج Microsoft Visio بالإضافة لاحتوائه على إمكانيات تُرشحّه كبديل أيضًا لبرنامج النشر المكتبي (Publisher) الخاص بـ Microsoft. كما تشمل الحزمة برنامج (Math) لكتابة الصيغ الرياضية والعلميّة وتصديرها لباقي أدوات الحزمة، بينما يشمل برنامج Word على إمكانيات كتابة الصيغ الرياضيّة مباشرة بداخله. نُوضّح في الجدول التالي أهم الخصائص العامة التي تُميّز كل طقم أدوات عن الآخر، يمكنك الإطلاع على القائمة كاملةً من هنا (أغفلنا المزايا المُشتركة بين الحزمتين): ميزات عامة LibreOffice 5.0 Microsoft Office 2013 واجهة المُستخدم GUI تقليديّة مع دعم تشغيل شريط جانبي واجهة Ribbon المُعتمدة على الألسنة توفّر نسخ 64 بت نعم، لجميع المنصّات لمنصّة Windows فقط توفّر نسخة محمولة Portable نعم، قابلة للتشغيل من وسيط usb لا التوطين المحليّ Localization 111 لغة 96 لغة استيراد الصيغ الرسومية svg. psd نعم لا دعم ملفات Microsoft OOXML files دعم جيد دعم ممتاز ومُتقدّم دعم الصيغ الرسومية MEZ, WMZ, PCZ, CGM لا نعم دعم العمل الجماعي المتزامن لا نعم مُعاينة حيّة للتنسيقات لا نعم المحرر النصييتشابه كلّ من Word و Writer في المزايا الرئيسية وحتى الثانويّة كذلك، بدءًا من التدقيق الإملائي والنحوي، الحفظ التلقائي، القوالب، التصدير إلى صيغة pdf وغيرها الكثير، لذا سيكون التفضيل بين البرنامجين أمرًا صعبًا حقيقة. يتميّز Writer بدعمه طُرز التنسيقات Styles format، هذا يُشبه أن تتعامل مع ملف css، فما إن تُعيّن قاعدة تنسيق للفقرات (p) مثلًا حتى تُطبّق بشكل تلقائي على كامل المُستند، دعم الإكمال التلقائي auto completion للكلمات المُستخدمة ضمن المُستند، دعم التصدير إلى XHTML و صيغة MediaWiki وكذلك تصدير المُستند على هيئة صور (jpg, png)، دعم التعامل مع أحجام صفحات تصل حتى (300سم*300سم)، دعم استبدال تلقائي للإيموجي، إمكانية تنسيق نصوص التعليقات وغيرها. في المقابل يتميّز Word بدعمه التدقيق النحوي لـ 21 لغة بشكل تلقائي (مقابل 4 لغات فيWriter)، دعم التعديل على الصور المُدرجة في المُستند بتأثيرات ووضعيات عديدة (كالتدوير بمُختلف الزوايا)، دعم تصاميم وتعديلات مُتقدّمة للجداول المُدرجة، دعم وضع القراءة، دعم طوي وبسط أجزاء المُستند، دعم إضافة علامة مائية للصفحات، دعم اختصارات لوحة المفاتيح بشكل أكبر، دعم النشر الفوري إلى منصات التدوين الشهيرة وغيرها. الجداول الحسابيةفي المقارنة بين Excel و Calc سيعتمد الأمر على استخدامك، في العموم فإنّ كلا البرنامجين يعملان بأسلوبٍ واحد، فإذا كنتَ مُستخدمًا بسيطًا تُنظّم بعض الحسابات، تجري عمليات رياضيّة، وتستخدم المعلومات لإنشاء مُخططات بيانية إلخ فلن تجد فرقًا يُذكر بينهما. أما إذا كنتَ قد استثمرت الكثير من الموارد لإنشاء وبرمجة وحدات ماكرو macros لعملك فغالبًا ما ستُفضّل البقاء مع Excel، إذ يملك Calc لغته الخاصة لكتابة الماكرو والتي لا تتوافق تمامًا مع لغة VBA الخاصة بـ Excel، وهذا ما سيُرتّب عليك إعادة كتابة كل شيء أو توفير الوقت والجهد والاستمرار في استخدام Excel. يتميّز Calc بإمكانية مُقارنة ملفي جداول حسابية معًا، دعم طرز التنسيقات (بما في ذلك تنسيقات الخليّة)، دعم التدقيق الإملائي، دعم التصدير إلى صيغة CSV، دعم التعابير النمطيّة في البحث والاستبدال، القدرة على تدوير الجدول بالكامل، دعم تنسيقات أكثر للخلايا، وغيرها. في المُقابل يتميّز Excel بدعم أكثر من 16 ألف عمود في الورقة الواحدة (مُقابل ألف في Calc)، دعم إدراج رسوم بيانيّة graphic في ترويسة وتذييل الجدول، دعم الرسوم البيانية التفاعلية (PivotChart)، دعم نشر الجداول إلى الويب لإجراء الاجتماعات، خيارات مُتعدّدة لخلفية الخلايا، نسخ الخلايا المرئية، طباعة الخلايا المُحدّدة فقط، وغيرها. العروض التقديميةيكاد اسم PowerPoint يختزل معنى ودلالة العروض التقديميّة؛ فهو برنامج أكثر من رائع يمكنه صناعة عروض مذهلة بمستوى أفضل من مُعظم المنافسين، وبينما يسعى Impress جاهدًا لتقليص الفجوة بينهما فلا يزال هناك عدّة خطوات لاعتبار الفجوّة بحجمٍ معقول. إذا كنتُ تُخطّط لإنشاء عرض تقديمي من الصفر فسيكون Impress خيارًا مُعتبرًا ومناسبًا إلى حدٍ كبير، وإن لم يشمل ذلك على لمسات PowerPoint الجمالية، لا سيما مع إمكانيه تصدير العرض بصيغ عديدة تُسهّل عليك مُشاركة الملف دون أن تطلب من الآخرين تثبيت PowerPoint. أما إن كنتَ تعمل مع فريق يعتمد PowerPoint في مشاريعه فسيكون من الصعوبة استيراد الملف إذ ستعاني من فقدان بعض الخطوط، ومشاكل أخرى مهمة في التصيير rendering لإجراء التعديلات المطلوبة عليه. يتميّز Impress بدعمه تصدير المشروع إلى صيغ (swf, svg, eps)، دعم إدراج وحدات ثلاثيّة الأبعاد 3D، دعم حتى 12 طبقة للشريحة الواحدة (مقابل 9 في PowerPoint)، دعم استيراد ملفات Apple Keynote وغيرها. بينما يتميّز PowerPoint بدعمه للتأثيرات التفاعلية والمتحرّكة، إمكانية تعديل الشرائح أثناء العرض، مقارنة العروض، بثّ العرض مباشرة إلى الوِب، العمل الجماعي على نفس الملف، دعم تعديلات مُتقدمة أكثر على الشرائح، دعم تصدير المشروع كصيغة فيديو وغيرها. قواعد البياناتعندما نأتي إلى المقارنة بين برنامجي قواعد البيانات Access و Base فإنّه سيصعب علينا حقًا تفضيل أحدهما على الآخر، فالتطبيقان مُمتازان لإدارة قواعد البيانات، يعملان بأسلوبٍ متشابه، ويتمتعان بخصائص متقاربة للغاية، فإذا كنتَ تعمل على Access يُمكنك أن تبدأ بتجريب Base على الفور والشعور وكأنك في منزلك. يتميّز Base بدعم مُذهل لـ MySQL، PostgreSQL و Thunderbird، بينما يتكامل Access بشكلٍ أفضل مع Outlook و Paradox، لذا قد يتحدّد خيارك بناءً على التقنيّات المُعتمدة في مكان عملك. أما إذا كنتَ تعمل لحسابك الخاص فيمكنك الاعتماد على Base دون قلق. خاتمةيمكننا القول إجمالًا بأنّ حزمة Office المُقدمة من Microsoft تتميّز بنقطتين أساسيتين: احتوائها على عميل البريد Outlook، وتقديمها خيارًا أكثر موائمة للتعامل مع العروض التقديميّة فيما يتعلق بالعمل الجماعي. في المقابل يمكنك –مجانًا– تركيب حزمة LibreOffice والحصول على أكثر ممّا تحتاجه من ميزات وخصائص، بالإضافة إلى إمكانية تشغيل ملفات Microsoft Office بأسلوب جيّدٍ في أغلب الأحيان. بهذه المقدمة أتمنى أن أكون قد قدّمت تصورًا متوازنًا عن حزمة LibreOffice ما لها وما عليها، وكليّ أمل أن تقرّروا الانضمام معنا في سلسلة الدروس هذه حول أدوات المكتب الحرّ.1 نقطة
-
سنتعرّف في هذا الدّرس على أداة nw (سابقًا node-webkit) المُخصّصة لتطوير تطبيقات سطح المكتب العابرة للمنصات؛ باستخدام مُتصفّح كروميوم [Chromium [1 و node.js. حيث أصبح بالإمكان استخدام تقنيات الوِب الحديثة لتطوير برمجيات قادرة على الاستفادة من موارد النظام؛ كالتحكّّم بالملفات، استعمال قواعد البيانات وغيرها من الأمور. في هذا الدّرس سنتعلّم كيفية كتابة تطبيق لسطح المكتب باستخدام nw لتشغيل ملفّات الفيديو. لنبدأ. تثبيت node.js إذ كنت تَستخدم نظام التشغيل Windows أو Mac OS عندها استعمل معالج التثبيت الرسمي، أما في حال عملك على نظام لينكس فقم بتثبيتها من خلال مدير الحزم. تثبيت nw بعد تركيب node.js من خلال مدير حزم node.js نحتاج إلى تركيب nw، للقيام بذلك نفّذ ما يلي من خلال الطرفية: npm install nw -g أهلا بالعالم أنشئ مُجلدًا مُخصصًا لمشروعنا الأول باسم helloworld ثم أنشئ بداخله ملفّين: package.json إن سبق لك التطوير باستخدام node.js فستعرف بالتأكيد أن هذا هو الملف الخاص بمعلومات و خصائص التطبيق أو الحزمة، يمكنك إنشاءه بسهولة من خلال سطر الأوامر: npm init سنضيف إلى الملفّ بعض خصائص nw (حجم النافذة و الرابط للملف الرّئيسيّ) ليصبح شكل الملف بالكامل هكذا: { “name”: “helloworld”, “version”: “1.0.0”, “description”: “”, “main”: “index.html”, “window”: { “width”: 600, “height”: 400 }, “scripts”: { “test”: “echo \”Error: no test specified\” && exit 1” }, “author”: “hsoubAcademy”, “license”: “MIT” } index.html هو ملف nw الرئّيسيّ الذي قمنا بتحديده من ملف الحزمة (package.json)، سنُنشئ مُستند بسيط لطباعة أهلًا بالعالم. تشغيل التطبيق من خلال سطر الأوامر انتقل إلى ملف المشروع وشغّل nw: cd helloworld nw يجب أن تظهر لك نافذة بحجم 600X400px وبداخلها نص "أهلًا بالعالم". سياق شفرة javascript يوجد بـ nw سياقان لشِفرة javascript: سياق المُتصفّح وسياق node.js، عند استدعائك لملف javascript أو تشغيلك لشيفرة من خلال مستند html فإن هذه الشفرة تُمرر إلى المتصفح ليقرأها، أما عند تشغيلك لملفّ javascript من خلال خاصية node-main في ملفّ الحزمة (package.json) أو استدعائه من خلال الدّالّة require فإنه يُمرر إلى سياق node.js، حيث يوجد بعض الاختلافات الطفيفة بين هذين السياقين في الكتابة: 1. سياق المتصفح في هذا السياق تعمل الشيفرة بالأسلوب الذي تعمل به في المتصفح، المُتغيّر العام هو window مثلًا، هذه الشيفرة ستعمل بشكل صحيح فقط في سياق المُتصفح: myVar = “test”; // تعريف مُتغير بشكل عام alert(window.myVar); // إخراج نافذة بالمتغير ولتمرير المُتغيرات بشكل عام إلى سياق node.js يجب تعريفها كتابع للمُتغير window.global مثال ليعمل مثال: // ملف window.js // هذا الملف يجب أن يعمل من سياق المُتصفح window.global.myVar = “test”; // تعريف مُتغيّر بشكل عام إلى سياق المُتصفح require(“node.js”); // استدعاء ملف node.js بداخل سياق node.js // ملف node.js // هذا الملف يجب أن يعمل من سياق node.js window.alert(myVar); // عرض المُتغير الّذي تم تعريفه بشكل عام من سياق المُتصفح 2. سياق node.js في هذه السياق تعمل الشيفرة بأسلوب عملها باستخدام node.js، المُتغير العام هو global مثال: myVar = “test”; // تعريف مُتغير بشكل عام window.alert(global.myVar); // إخراج نافذة بالمتغير العام الّذي قمنا بتعريفه يُمكن استخدام سياق المتصفح والتمرير إليه من خلال المُتغير window. استدعاء الحزم التي كتبت للمتصفح بداخل سياق node.js عند استدعاء حزم تمت كتابتها للمُتصفح بداخل سياق node.js عن طريق الدّالّة require فقد لا تعمل، حيث تحدثنا سابقًا أن المتغيّر العام في سياق node.js هو global و ليس window مما يسبب مشكلة إن تم استدعاء أحد توابع window، عمومًا فالمثال لن يعمل في سياق node.js: var div = document.createElement(“div”); لجعل هذه الشيفرة تعمل يجب تعريف مُتغير document بشكل عام في سياق node.js: global.document = window.document; بشكل مبدئي سيجعل هذين السطرين أغلب الحزم تعمل: global.document = window.document; global.navigator = window.navigator; إن كنت تبحث عن حل تلقائي لنقل جميع المُتغيرات إلى سياق node.js (قد لا يُنصح بهذا الحل بسبب حذف المُتغيرات المتطابقة في الاسم): var Var; for(Var in window) if(Var != “require”) global[Var] = window[Var]; ملاحظة: لم ننقل مُتغير require لأن التابع window.require يستخدم global.require في استدعاء الحزم. لاحظ أيضًا أنه لا يمكن استدعاء حزمة nw.gui الخاصة بواجهة المستخدم من خلال سياق node.js عن طريق الدّالّة require فكما ذكرنا؛ التابع window.require يختلف عن global.require. هذا هو النص المصدري للتابع: window.require = function (name) { if (name == ‘nw.gui’) return nwDispatcher.requireNwGui(); return global.require(name); } وكما تلاحظ إن كان اسم الحزمة node.js فإنه يستخدم هذه الدّالّة لاستدعائها: nwDispatcher.requireNwGui(); إذًا لاستدعائها من خلال سياق node.js استخدم الدّالّة السابقة أو استخدم window.require. إنشاء تطبيق لتشغيل الفيديو ملفات المشروع هذه قائمة لملفات المشروع: ملف الحزمة (package.json) حجم النافذة الافتراضي هو 800x600px، الملفّ الرّئيسيّ هو index.html، مبدئيًا سيكون الملف بهذا الشكل: { “name”: “nw-video-player”, “version”: “1.0.0”, “description”: “تطبيق بسيط لتشغيل الفيديو”, “main”: “index.html”, “window”: { “width”: 800, “height”: 600 }, “scripts”: { “test”: “echo \”Error: no test specified\” && exit 1” }, “author”: “hsoubAcademy”, “license”: “MIT”, “dependencies”: { “videojs”: “^4.12.15” } } الملف الرئيسي index.html سنكتب مستند بسيط يحتوي على زر وعنصر، نضيف المشغّل ضمنه من خلال شيفرة javascript: <!doctype html> <html> <head> <meta charset="utf-8"> <title>تطبيق بسيط لتشغيل الفيديو</title> <!-- ملف شفرة js الرّئيسية للتطبيق --> <script src="src/app.js"></script> </head> <body> <button id="play">فتح</button> <div id="player"></div> </body> </html> نافذة فتح الملفات لا يوجد طريقة مباشرة لفتح الملفات باستخدام نافذة النظام، لكن يُمكننا استخدام مدخل input من نوع file لفتح الملفّات: لكن كخلاف المتصفح للمستخدم يُتاح لنا بعض الأشياء عند التطوير بـ nw كجلب المسار الكامل الحقيقي للملفّ، ويتاح لنا فتحه من خلال javascript: document.querySelector(“input”).click(); من خلال هذا سنكتب دالّة بسيطة لفتح ملفّات الفيديو وإرجاع مسار الملف مع إضافة بروتوكول file لاستخدامه من خلال المُتصفح، الدّالّة: // فتح ملف var openFile = function openFile (callback) { var input = window.document.createElement(“input”); input.setAttribute(“type”, “file”); input.setAttribute(“accept”, “.mp4, .ogg, .ogv, .webm”); input.addEventListener(“change”, function () { // عند إختيار ملف callback(“file://”+this.value); }); input.click() // فتح مُختار الملفات } تجربة استخدام: openFile(alert); مشغل الفيديو سنستخدم video.js لتسهيل تصميم المشغّل من خلال سطر الأوامر، اتجه إلى مجلّد المشروع ثم قم بتنصيب video.js من مدير الحزم الخاص بـnode.js: npm install videojs –save كما تحدثنا في بداية الدرس عن استدعاء الحزم في سياق node.js سنحتاج إلى كتابة هذين السطرين: global.document = window.document; global.navigator = window.navigator; من ثم سيمكننا استدعائها بشكل عادي: var videojs = require(“videojs”); من خلال هذا والدّالّة السابقة لفتح الملفات سنكتب دالّة لإنشاء مشغل فيديو من خلال مسار ملف الفيديو من ثم إضافته إلى عنصر المشغّل في المستند الذي كتبناه من قبل: var playVideo = function playVideo (src) { var videojs = require("videojs"), ext = /[^.]+$/.exec(src)[0], // صيغة الملفّ video = document.createElement("video"), // عنصر الفديو source = document.createElement("source"), // عنصر المصدر للفديو player = document.querySelector("#player"); // عنصر المشغل في وثيقة html ext = (ext == "ogv") ? "ogg" : ext; // ملفات ogg قد تملك صيغة ogv source.type = "video/"+ext.toLowerCase(); // نوع mime للفديو source.src = src; // مسار الفديو video.controls = true; // عناصر التحكّم video.autoplay = true; // تشغيل تلقائي video.classList.add("video-js", "vjs-default-skin"); // الclass الخاصة بvideojs video.appendChild(source); // إضافة عنصر المصدر إلى الفديو player.innerHTML = ""; // إزالة جميع العناصر السّابقة player.appendChild(video); // إضافة الفديو إلى وثيقة html videojs(video) // إستخدام video.js } مشكلة nw مع الصيغ مُغلقة المصدر: بشكل افتراضي سيمكنك تشغيل ملفات ogg و webm فقط لكن بسبب مشكلة مع التراخيص، لا تتضمن nw مشغّل لصيغة mp4 و الصوت mp3 اطلع على طريقة تضمين الملفّات المُشغلة. الآن تبقى فتح الملفّ عند الضغط على الزر: window.addEventListener(“load”, function () { window.document.querySelector(“button#play”).addEventListener(“click”, function () { openFile(playVideo) }); }); ليصبح كامل ملف app.js: "use strict"; global.document = window.document; global.navigator = window.navigator; var nwGui = require("nw.gui"), Window = nwGui.Window.get(); (function(window, nwGui, Window){ var maximized; // فتح ملف var openFile = function openFile (callback) { var input = document.createElement("input"); input.setAttribute("type", "file"); input.setAttribute("accept", ".mp4, .ogg, .ogv, .webm"); input.addEventListener("change", function () { // عند إختيار ملف callback("file://"+this.value); }); input.click() // فتح مُختار الملفات } // تشغيل فديو var playVideo = function playVideo (src) { var videojs = require("videojs"), ext = /[^.]+$/.exec(src)[0], // صيغة الملفّ video = document.createElement("video"), // عنصر الفديو source = document.createElement("source"), // عنصر المصدر للفديو player = document.querySelector("#player"); // عنصر المشغل في وثيقة html ext = (ext == "ogv") ? "ogg" : ext; // ملفات ogg قد تملك صيغة ogv source.type = "video/"+ext.toLowerCase(); // نوع mime للفديو source.src = src; // مسار الفديو video.controls = true; // عناصر التحكّم video.autoplay = true; // تشغيل تلقائي video.classList.add("video-js", "vjs-default-skin"); // الclass الخاصة بvideojs video.appendChild(source); // إضافة عنصر المصدر إلى الفديو player.innerHTML = ""; // إزالة جميع العناصر السّابقة player.appendChild(video); // إضافة الفديو إلى وثيقة html videojs(video) // إستخدام video.js } window.addEventListener("load", function () { // زر فتح فديو window.document.querySelector("button#play").addEventListener("click", function () { openFile(playVideo) }); }); }) (window, nwGui, Window); تصميم التطبيق بداخل مُستند html أضف مسار ملفّ css الافتراضي لـvideo.js الموجود داخل مجلد node_modules: ثم سنلغي شريط الأدوات الخاص بـnw بداخل ملف الحزمة (package.json) وبداخل العنصر window أضف ما يلي: “toolbar”: false من ثم سننشئ ملف تصميم src/style.css: html, body{ width: 100%; height: 100%; background: #ccc; direction: rtl; margin: 0 } /* زر التشغيل */ #play{ height: 25px; background: white; padding: 2px 20px; box-sizing: border-box; border: 1px #ccc solid } #play:hover{ box-shadow: inset 0 0 1px #333 } /* المُشغل */ #player{ background: black; width: 100%; height: calc(100% - 25px) } #player > .video-js{ width: 100% !important; height: 100% !important } إضافته من خلال مُستند html: كان من الأفضل استخدام قائمة النظام لعرض زر تشغيل الفيديو لكن nw لا تدعم الاتجاه من اليمين إلى اليسار بشكل كامل إلى الآن، لذا سنضيف السطر التالي إلى ملف الحزمة كي تظهر من اليمين إلى اليسار: “chromium-args”: “–lang=ar” بدلًا من ذلك سنقوم بإنشاء إطار مُخصص للنافذة لتبدو بشكلٍ أفضل في مختلف الأنظمة. تخصيص إطار النافذة بداخل ملف الحزمة (package.json) وبداخل عنصر window سنلغي الإطار الافتراضي: “frame”: false من ثم بداخل مستند html سنضيف أزرار النافذة في أول عنصر جسم الصفحة (body). سنضيف و نحذف بعض الخصائص من ملف src/style.css ليصبح شكل النافذة شبيه بنافذة نظام OS X: html, body{ width: 100%; height: 100%; background: #ccc; direction: rtl; margin: 0 } /* زر التشغيل */ #play{ -webkit-app-region: no-drag; height: 25px; background: white; padding: 2px 20px; box-sizing: border-box; border: 1px #ccc solid; position: absolute; right: 5px; top: 2px } #play:hover{ box-shadow: inset 0 0 1px #333 } /* المُشغل */ #player{ background: black; width: 100%; height: calc(100% - 25px) } #player > .video-js{ width: 100% !important; height: 100% !important } /* النافذة */ body{ box-sizing: border-box; border: #DDDDDC 5px solid } .window-toolbar{ -webkit-app-region: drag; background: -webkit-linear-gradient(#DDDDDC, #C2C2C2); height: 25px; direction: ltr; padding: 2px 5px; box-sizing: border-box } .window-toolbar > label.title{ position: absolute; left: 50%; transform: translate(-50%, 0) } .window-toolbar-button{ -webkit-app-region: no-drag; width: 12px; height: 12px; border-radius: 100%; display: inline-block; cursor: pointer; margin-right: 2px } .window-toolbar-button.close{ background: #FD4E4E } .window-toolbar-button.maximize{ background: #96D16F } .window-toolbar-button.minimize{ background: #F3BB55 } مُلاحظة: الخاصية webkit-app-region- المسؤولة عن جعل العنصر قابل للسحب والإفلات أيضًا يُمكن التحكّم بموقع النافذة من هذا العنصر لهذا استخدمناه في شريط أدوات النافذة لكن هذا العنصر لن يكون قابل للضغط أو المرور عليه لذلك يجب تعطيلها لعناصر التحكّم بداخله. لنكتب بعض الشيفرات بداخل ملفّ src/app.js لإضافة الحياة لشريط الأدوات. توفّر nw بعض التوابع للتحكم بالنافذة ما سنحتاجه للعمل: require(“nw.gui”).Window.get().close(); // إغلاق النافذة الحالية فقط require(“nw.gui”).App.quit(); // إغلاق التطبيق بجميع النوافذ require(“nw.gui”).Window.get().minimize(); // تصغير النافذة إلى شريط التطبيقات require(“nw.gui”).Window.get().maximize(); // ملء الشاشة بالنافذة require(“nw.gui”).Window.get().unmaximize(); // إرجاع النافذة أولًا زر الإغلاق: var nwGui = require(“nw.gui”); // زر إغلاق التطبيق window.document.querySelector(“.close”).addEventListener(“click”, function () { nwGui.App.quit(); }); ثانيًا زر إخفاء النافذة إلى شريط التطبيقات: var nwGui = require("nw.gui"), Window = nwGui.Window.get(); // زر تصغير النافذة إلى شريط التطبيقات window.document.querySelector(".minimize").addEventListener("click", function() { Window.minimize() }); زر ملء النافذة لكن أولًا سنضيف مراقب للحدثين maximize و unmaximize لمعرفة هل النافذة بكامل الحجم أو لا، حيث لا توفّر nw أيّة API لمعرفة ذلك: var nwGui = require(“nw.gui”), Window = nwGui.Window.get(), maximized = false; // مراقب للحدث maximize Window.on("maximize", function(){ maximized = true; }); // مراقب للحدث unmaximize Window.on("unmaximize", function(){ maximized = false; }); من خلال هذا وعند الضغط على زر الملئ إما أن تذهب النافذة لكامل الحجم أو تعود لحجمها الطبيعي: window.document.querySelector(“.maximize”).addEventListener(“click”, function () { maximized ? Window.unmaximize() : Window.maximize() }); يجب أن يكون كامل ملف src/app.js بهذا الشكل: "use strict"; global.document = window.document; global.navigator = window.navigator; var nwGui = require("nw.gui"), Window = nwGui.Window.get(); (function(window, nwGui, Window){ var maximized; // فتح ملف var openFile = function openFile (callback) { var input = document.createElement("input"); input.setAttribute("type", "file"); input.setAttribute("accept", ".mp4, .ogg, .ogv, .webm"); input.addEventListener("change", function () { // عند إختيار ملف callback("file://"+this.value); }); input.click() // فتح مُختار الملفات } // تشغيل فديو var playVideo = function playVideo (src) { var videojs = require("videojs"), ext = /[^.]+$/.exec(src)[0], // صيغة الملفّ video = document.createElement("video"), // عنصر الفديو source = document.createElement("source"), // عنصر المصدر للفديو player = document.querySelector("#player"); // عنصر المشغل في وثيقة html ext = (ext == "ogv") ? "ogg" : ext; // ملفات ogg قد تملك صيغة ogv source.type = "video/"+ext.toLowerCase(); // نوع mime للفديو source.src = src; // مسار الفديو video.controls = true; // عناصر التحكّم video.autoplay = true; // تشغيل تلقائي video.classList.add("video-js", "vjs-default-skin"); // الclass الخاصة بvideojs video.appendChild(source); // إضافة عنصر المصدر إلى الفديو player.innerHTML = ""; // إزالة جميع العناصر السّابقة player.appendChild(video); // إضافة الفديو إلى وثيقة html videojs(video) // إستخدام video.js } window.addEventListener("load", function () { // زر فتح فديو window.document.querySelector("button#play").addEventListener("click", function () { openFile(playVideo) }); // زر إغلاق التطبيق window.document.querySelector(".close").addEventListener("click", function () { nwGui.App.quit() }); // مراقب للحدث maximize Window.on("maximize", function(){ maximized = true; }); // مراقب للحدث unmaximize Window.on("unmaximize", function(){ maximized = false; }); // زر تصغير النافذة إلى شريط التطبيقات window.document.querySelector(".minimize").addEventListener("click", function() { Window.minimize() }); // زر الملء window.document.querySelector(".maximize").addEventListener("click", function () { maximized ? Window.unmaximize() : Window.maximize() }); }); }) (window, nwGui, Window); صورة للشكل النهائي: إن لم يظهر التطبيق بنفس الشكل فإليك ملفات التطبيق النهائية. بناء الملف التنفيذي لو أردنا إتباع الأسلوب التقليدي فنحن نحتاج إلى أنظمة التشغيل الثلاثة لبناء التطبيق في كل واحد منها على حدى، بدلًا من ذلك سنستخدم nwbuild لبناء التطبيق من خلال نظام تشغيل واحد إلى جميع أنظمة التشغيل. من مدير حزم npm قم بتركيب nwbuild : npm install nwbuild -g أنظمة التشغيل المتوفرة لـnwbuild: win32 # Windows 32bit win64 # Windows 64bit win # Windows 64bit مع 32bit osx32 # Mac OS 32bit osx64 # Mac OS 64bit osx # Mac OS 64bit مع 32bit linux32 # Linux 32bit linux64 # Linux 64bit linux # Linux 64bit مع 32bit ليعمل على أنظمة التشغيل الثلاث سنبنيه لـlinux ، osx64 و win32، اتّجه إلى مجلد التطبيق ونفّذ: nwbuild -p linux,osx64,win32 ./ سيعمل أولًا على تحميل ملفات البناء لأنظمة التشغيل من ثم بناء الملفات التنفيذية، ستلاحظ أن متوسط الحجم 50 ميغابايت للملفّ الواحد بسبب تضمين المتصفحات والملفات التشغيلية. التالي سيكون من الرائع تعلم react لبناء تطبيقات سطح مكتب رائعة باستخدام nw مع react. مصادر nw window nw App nw javascript contexts nw build هوامش 1 - كروميوم (Chromium) هو متصفح ويب مفتوح المصدر، يأخذ متصفح Google كروم الكود المصدري منه. المتصفحان يشتركان في أغلبية الشِفرة البرمجية والميزات، وإن كانت هناك بعض الاختلافات الطفيفة في ملامح كلا منهما وفي تراخيص الأستخدام أيضا. المصدر: ويكيبيديا.1 نقطة