لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 10/18/15 في كل الموقع
-
يُعتبر مربع البحث أحد المكونات التي لا غنى عنها في أي موقع، وفي هذا الدرس سوف تتعلم كيف يمكنك إنشاء مربع بحث يظهر ويختفي عند النقر عليه. قد تعتقد أنّ القيام بذلك سيكون سهلًا جدًا ولكنك سوف ترى أنّ الأمر ليس كذلك، فسوف نحتاج إلى تطبيق بعض الخدع حتى نجعل كل شيء يعمل بشكل صحيح. هذه هي المتطلبات التي نريدها مبدئيًا: ما نريده مبدئيًا هو ظهور زر يحتوي على أيقونة بحث. عند النقر على ذلك الزر نريد أن يظهر مربع البحث. نريده أن يكون متجاوبًا مع جميع الأجهزة. عند كتابة أي شيء في مربع البحث نريد أن يقوم المربع بالقيام بالبحث فور النقر على مفتاح الدخول (enter) من لوحة المفاتيح أو النقر على الأيقونة نفسها. إذا كان مربع البحث ظاهرًا ولكنه كان فارغًا فإننا نريده أن يختفي عند النقر على أيقونة البحث (أي أننا إذا قمنا بالنقر على أيقونة البحث وكان المربع فارغًا فإننا لا نريده أن يقوم بالبحث وإنما يقوم بإخفاء مربع البحث). نريد أيضًا أن يختفي مربع البحث عند النقر خارجه سواء كان فارغًا أم لا. لو كانت الجافاسكربت معطلة لدى المستخدم فإننا نريد لمربع البحث أن يكون ظاهرًا (أي دون الحاجة إلى النقر على أيقونة البحث). نريد أيضًا أن ندعم الأجهزة التي تعمل باللمس. يمكنك معاينة النتيجة النهائية لهذا الدرس. بما أننا بتنا الآن نعرف ما نريد فلنقم بذلك. بنية ملف HTML كل ما نحتاجه من وسوم HTML هو حاوٍ رئيسي (main container) وسوف يكون عبارة عن وسم <div> وسوف نحتاج إلى وسم <form> وإلى حقلي إدخال (inputs)؛ واحد من نوع "text" والآخر من نوع "submit" وأخيرًا سوف نحتاج إلى وسم <span> ليحتوي على أيقونة البحث: <div id="sb-search" class="sb-search"> <form> <input class="sb-search-input" placeholder="Enter your search term..." type="search" value="" name="search" id="search"> <input class="sb-search-submit" type="submit" value=""> <span class="sb-icon-search"></span> </form> </div> لنبدأ الآن بتنسيق العناصر باستخدام CSS. تنسيقات CSS بناءً على المتطلبات التي ذكرناها سابقًا فإنه يجب في البداية أن يكون لدينا زر يحتوي على أيقونة بحث وباقي العناصر يجب أن تكون مخفية. دعونا الآن نتخيل ما الذي سيحصل عند تمدد مربع البحث وجعله ظاهرًا (الذي هو نفسه سيكون الحاوي الرئيسي الذي ذكرناه سابقًا). كيف نقوم بذلك؟ سوف نستخدم الخاصية overflow: hidden وتكبير العرض الخاص بالعنصر الحاوي (sb-search) يجب أن يقوم بإظهار حقل البحث. دورة تطوير واجهات المستخدم ابدأ عملك الحر بتطوير واجهات المواقع والمتاجر الإلكترونية فور انتهائك من الدورة اشترك الآن إذًا أول شيء نقوم به هو تنسيق العنصر الحاوي (sb-search) بحيث سوف نجعله يطوف إلى اليمين باستخدام الخاصية float: right ونعطيه الخاصية overflow: hidden، والعرض يجب أن يكون 60px ولكن بما أننا نريد أن يزيد العرض إلى 100% فإننا سنواجه بعض المشاكل في متصفحات iOS فهي لا تقبل التغيير من عرض يعتمد على الـpixels إلى عرض يعتمد على النسب المئوية. لذلك سوف نقوم بتعريف خاصية min-width بالقيمة 60px وخاصية width بقيمة 0%. يمكنك قراءة المزيد عن هذا الحل العبقري من خلال هذا الرابط. سوف نستعمل أيضًا الخاصية transition والخاصية webkit-backface-visibility: hidden- لتلافي بعض الآثار للحقول في متصفحات الهواتف iOS: .sb-search { position: relative; margin-top: 10px; width: 0%; min-width: 60px; height: 60px; float: right; overflow: hidden; -webkit-transition: width 0.3s; -moz-transition: width 0.3s; transition: width 0.3s; -webkit-backface-visibility: hidden; } أي شيء يتجاوز/يفيض عن هذا المربع الصغير لن يكون ظاهرًا. لنقم الآن بموضعة حقل البحث. سوف نستعمل قيمة مئوية بالنسبة للعرض حتى نسمح للحقل بأن يتمدد مع تمدد العنصر الحاوي. ومع إضافة الارتفاع (height) وحجم الخط (font-size) والـpadding المناسبة يمكننا توسيط النص داخل العنصر (استعملنا padding بدل line-height لأن الخاصية line-height لا تعمل بشكل جيد في متصفح IE8). قد يبدو استعمالنا للخاصية position: absolute غير ضروري، ولكن استعمالها يقوم بحل مشكلة تظهر عند إغلاق مربع البحث بحيث يبدو الحقل وكأنه ظاهر في الجانب الأيمن لفترة قصيرة جدًا. .sb-search-input { position: absolute; top: 0; right: 0; border: none; outline: none; background: #fff; width: 100%; height: 60px; margin: 0; z-index: 10; padding: 20px 65px 20px 20px; font-family: inherit; font-size: 20px; color: #2c3e50; } input[type="search"].sb-search-input { -webkit-appearance: none; -webkit-border-radius: 0px; } قمنا أيضًا بإزالة التنسيقات الإفتراضية لحقل البحث في متصفحات WebKit. دعونا نقوم الآن بتعريف لون الخط بالنسبة للـplaceholder (الـplaceholder هو نص يظهر داخل حقل البحث قبل أن يقوم المستخدم بكتابة أي شيء بداخله حتى يُعطي المستخدم لمحة عما يجب عليه كتابته في ذلك الحقل): .sb-search-input::-webkit-input-placeholder { color: #efb480; } .sb-search-input:-moz-placeholder { color: #efb480; } .sb-search-input::-moz-placeholder { color: #efb480; } .sb-search-input:-ms-input-placeholder { color: #efb480; } دعونا الآن نقوم بتنسيق زر أيقونة البحث وحقل التأكيد/الإرسال (submit input)، فنحن نريدهما أن يظهرا في نفس المكان لذلك يجب أن نضعهما في الجانب الأيمن ونعطيهما نفس الأبعاد. وبما أنهما سيظهران فوق بعضهما فسوف نعطيهما الخاصية position: absolute: .sb-icon-search, .sb-search-submit { width: 60px; height: 60px; display: block; position: absolute; right: 0; top: 0; padding: 0; margin: 0; line-height: 60px; text-align: center; cursor: pointer; } نريد في بداية الأمر أن تكون الأيقونة قابلة للنقر، وعند فتح حقل البحث فإننا نريد لحقل التأكيد/الإرسال (submit input) أن يكون قابلًا للنقر. لذلك سوف نُعطي حقل التأكيد الخاصية z-index: -1 ونجعله شفافًا/مخفيًا حتى يمكننا رؤية أيقونة البحث: .sb-search-submit { background: #fff; /* IE needs this */ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; /* IE 8 */ filter: alpha(opacity=0); /* IE 5-7 */ opacity: 0; color: transparent; border: none; outline: none; z-index: -1; } لاحظ أننا لم نقم بجعل الخلفية شفافة وذلك لأن الأمر لا يعمل بشكل جيد في متصفح IE فالعنصر لا يكون قابلًا للنقر عند ذلك، لذلك قمنا باستعمال لون معين (الأبيض) وجعلنا الشفافية (opacity) تساوي صفر. وبما أننا نريد لأيقونة البحث أن تظهر فوق كل شيء فإننا سوف نقوم بإعطائها الخاصية z-index بقيمة عالية، وسوف نقوم باستخدام الفئة الزائفة ::before لإضافة الأيقونة: .sb-icon-search { color: #fff; background: #e67e22; z-index: 90; font-size: 22px; font-family: 'icomoon'; speak: none; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; -webkit-font-smoothing: antialiased; } .sb-icon-search:before { content: "\e000"; } ودعونا لا ننسى إضافة خط الويب (web font) في بداية ملف الـCSS: /* Search icon by IcoMoon, made with http://icomoon.io/app/ */ @font-face { font-family: 'icomoon'; src:url('../fonts/icomoon/icomoon.eot'); src:url('../fonts/icomoon/icomoon.eot?#iefix') format('embedded-opentype'), url('../fonts/icomoon/icomoon.woff') format('woff'), url('../fonts/icomoon/icomoon.ttf') format('truetype'), url('../fonts/icomoon/icomoon.svg#icomoon') format('svg'); font-weight: normal; font-style: normal; } يمكننا الآن إعطاء العنصر الحاوي (sb-search) عرضًا بقيمة 100% وذلك في حالتين؛ الأولى عند النقر على أيقونة البحث وذلك عن طريق إضافة فئة (class) بالاسم "sb-search-open" باستخدام الجافاسكربت والثانية عندما لا يكون الجافاسكربت مفعّلًا لدى المستخدم: .sb-search.sb-search-open, .no-js .sb-search { width: 100%; } لنقم الآن بتغيير لون الخط الخاص بعنصر أيقونة البحث ونضعه أسفل حقل التأكيد/الإرسال وذلك عن طريق إعطائه قيمة z-index أقل من 90 (وهي القيمة التي أعطيناها للعنصر "sb-icon-search"): .sb-search.sb-search-open .sb-icon-search, .no-js .sb-search .sb-icon-search { background: #da6d0d; color: #fff; z-index: 11; } وأخيرًا لنقم بإضافة الخاصية z-index لحقل التأكيد/الإرسال ولكن بقيمة أكبر من 11 حتى يمكننا النقر عليها: .sb-search.sb-search-open .sb-search-submit, .no-js .sb-search .sb-search-submit { z-index: 90; } انتهينا الآن من تنسيقات CSS وبقي علينا الجافاسكربت. بعض الجافاسكربت لنبدأ بإضافة وإزالة الفئة "sb-search-open". بحيث سوف يتم إضافة الفئة عند النقر على الحاوي الرئيسي (sb-search) وإزالته عند النقر على حقل التأكيد/الإرسال ولكن فقط إذا كان حقل البحث فارغًا، أمّا إذا لم يكن فارغًا فإننا نريد تأكيد عملية البحث. وحتى لا نقوم بإزالة الفئة عند النقر على الحقل (لأن الحاوي بأكمله قابل للنقر) فإننا نحتاج إلى منع حدث النقر (click event) من الانتشار على ذلك العنصر. هذا يعني أنّ النقر على الحقل لن يؤدي إلى إثارة حدث النقر على العناصر الحاوية له. ;( function( window ) { function UISearch( el, options ) { this.el = el; this.inputEl = el.querySelector( 'form > input.sb-search-input' ); this._initEvents(); } UISearch.prototype = { _initEvents : function() { var self = this, initSearchFn = function( ev ) { if( !classie.has( self.el, 'sb-search-open' ) ) { ev.preventDefault(); self.open(); } else if( classie.has( self.el, 'sb-search-open' ) && /^\s*$/.test( self.inputEl.value ) ) { self.close(); } } this.el.addEventListener( 'click', initSearchFn ); this.inputEl.addEventListener( 'click', function( ev ) { ev.stopPropagation(); }); }, open : function() { classie.add( this.el, 'sb-search-open' ); }, close : function() { classie.remove( this.el, 'sb-search-open' ); } } window.UISearch = UISearch; } )( window ); سوف نحتاج أيضًا إلى إضافة الأحداث التي تقوم بإزالة الفئة "sb-search-open" عند النقر خارج مربع البحث، وحتى يعمل ذلك فإننا نريد أن نتعامل مع انتشار الأحداث (event bubbling) عند النقر على الحاوي الرئيسي. ;( function( window ) { function UISearch( el, options ) { this.el = el; this.inputEl = el.querySelector( 'form > input.sb-search-input' ); this._initEvents(); } UISearch.prototype = { _initEvents : function() { var self = this, initSearchFn = function( ev ) { ev.stopPropagation(); if( !classie.has( self.el, 'sb-search-open' ) ) { ev.preventDefault(); self.open(); } else if( classie.has( self.el, 'sb-search-open' ) && /^\s*$/.test( self.inputEl.value ) ) { self.close(); } } this.el.addEventListener( 'click', initSearchFn ); this.inputEl.addEventListener( 'click', function( ev ) { ev.stopPropagation(); }); }, open : function() { var self = this; classie.add( this.el, 'sb-search-open' ); // close the search input if body is clicked var bodyFn = function( ev ) { self.close(); this.removeEventListener( 'click', bodyFn ); }; document.addEventListener( 'click', bodyFn ); }, close : function() { classie.remove( this.el, 'sb-search-open' ); } } window.UISearch = UISearch; } )( window ); وشيء آخر علينا الاهتمام به وهو قصّ مصطلح البحث. عندما نقوم أيضًا بالنقر على أيقونة البحث فإننا نريد أن يكون الحقل مفعّلًا (focused)، ولأنّ هذا يسبب بعض المشاكل في متصفح iOS (لوحة المفاتيح تظهر في نفس الوقت) فإننا نريد تلافي ذلك في هذه الحالة، وعندما يتم إغلاق مربع البحث فإننا نريد أن يكون مربع البحث غير مفعل (blur). هذا سوف يحل بعض المشاكل في بعض الأجهزة التي تُظهر بأنّ المؤشر يومض حتى بعد أن يكون الحقل مغلقًا. ملاحظة جانبية: كلمة focus تدل على أنّ مربع البحث مفعّل (أي أنّ المؤشر بداخله) وكلمة blur تدل على عكس ذلك. ;( function( window ) { // http://stackoverflow.com/a/11381730/989439 function mobilecheck() { var check = false; (function(a){if(/(android|ipad|playbook|silk|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera); return check; } // http://www.jonathantneal.com/blog/polyfills-and-prototypes/ !String.prototype.trim && (String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); }); function UISearch( el, options ) { this.el = el; this.inputEl = el.querySelector( 'form > input.sb-search-input' ); this._initEvents(); } UISearch.prototype = { _initEvents : function() { var self = this, initSearchFn = function( ev ) { ev.stopPropagation(); // trim its value self.inputEl.value = self.inputEl.value.trim(); if( !classie.has( self.el, 'sb-search-open' ) ) { ev.preventDefault(); self.open(); } else if( classie.has( self.el, 'sb-search-open' ) && /^\s*$/.test( self.inputEl.value ) ) { self.close(); } } this.el.addEventListener( 'click', initSearchFn ); this.inputEl.addEventListener( 'click', function( ev ) { ev.stopPropagation(); }); }, open : function() { var self = this; classie.add( this.el, 'sb-search-open' ); // focus the input if( !mobilecheck() ) { this.inputEl.focus(); } // close the search input if body is clicked var bodyFn = function( ev ) { self.close(); this.removeEventListener( 'click', bodyFn ); }; document.addEventListener( 'click', bodyFn ); }, close : function() { this.inputEl.blur(); classie.remove( this.el, 'sb-search-open' ); } } window.UISearch = UISearch; } )( window ); وحتى يعمل كل شيء بشكل سلس في أجهزة الهواتف فإننا سوف نحتاج إلى إضافة أحداث اللمس (touch events). كما أنّ إضافة preventDefault في دالّة initSearchFn سوف يمنع حدث النقر واللمس من أن يتفعّلا مع بعضهما في أجهزة اللمس. ;( function( window ) { // http://stackoverflow.com/a/11381730/989439 function mobilecheck() { var check = false; (function(a){if(/(android|ipad|playbook|silk|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera); return check; } // http://www.jonathantneal.com/blog/polyfills-and-prototypes/ !String.prototype.trim && (String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); }); function UISearch( el, options ) { this.el = el; this.inputEl = el.querySelector( 'form > input.sb-search-input' ); this._initEvents(); } UISearch.prototype = { _initEvents : function() { var self = this, initSearchFn = function( ev ) { ev.stopPropagation(); // trim its value self.inputEl.value = self.inputEl.value.trim(); if( !classie.has( self.el, 'sb-search-open' ) ) { ev.preventDefault(); self.open(); } else if( classie.has( self.el, 'sb-search-open' ) && /^\s*$/.test( self.inputEl.value ) ) { ev.preventDefault(); self.close(); } } this.el.addEventListener( 'click', initSearchFn ); this.el.addEventListener( 'touchstart', initSearchFn ); this.inputEl.addEventListener( 'click', function( ev ) { ev.stopPropagation(); }); this.inputEl.addEventListener( 'touchstart', function( ev ) { ev.stopPropagation(); } ); }, open : function() { var self = this; classie.add( this.el, 'sb-search-open' ); // focus the input if( !mobilecheck() ) { this.inputEl.focus(); } // close the search input if body is clicked var bodyFn = function( ev ) { self.close(); this.removeEventListener( 'click', bodyFn ); this.removeEventListener( 'touchstart', bodyFn ); }; document.addEventListener( 'click', bodyFn ); document.addEventListener( 'touchstart', bodyFn ); }, close : function() { this.inputEl.blur(); classie.remove( this.el, 'sb-search-open' ); } } window.UISearch = UISearch; } )( window ); وأخيرًا، للأجهزة التي لا تدعم addEventListener وremoveEventListener فإننا سوف نستعمل polyfill. // EventListener | @jon_neal | //github.com/jonathantneal/EventListener !window.addEventListener && window.Element && (function () { function addToPrototype(name, method) { Window.prototype[name] = HTMLDocument.prototype[name] = Element.prototype[name] = method; } var registry = []; addToPrototype("addEventListener", function (type, listener) { var target = this; registry.unshift({ __listener: function (event) { event.currentTarget = target; event.pageX = event.clientX + document.documentElement.scrollLeft; event.pageY = event.clientY + document.documentElement.scrollTop; event.preventDefault = function () { event.returnValue = false }; event.relatedTarget = event.fromElement || null; event.stopPropagation = function () { event.cancelBubble = true }; event.relatedTarget = event.fromElement || null; event.target = event.srcElement || target; event.timeStamp = +new Date; listener.call(target, event); }, listener: listener, target: target, type: type }); this.attachEvent("on" + type, registry[0].__listener); }); addToPrototype("removeEventListener", function (type, listener) { for (var index = 0, length = registry.length; index < length; ++index) { if (registry[index].target == this && registry[index].type == type && registry[index].listener == listener) { return this.detachEvent("on" + type, registry.splice(index, 1)[0].__listener); } } }); addToPrototype("dispatchEvent", function (eventObject) { try { return this.fireEvent("on" + eventObject.type, eventObject); } catch (error) { for (var index = 0, length = registry.length; index < length; ++index) { if (registry[index].target == this && registry[index].type == eventObject.type) { registry[index].call(this, eventObject); } } } }); })(); خاتمة هذا كان كل شيء فيما يخص هذا الدرس، أتمنى أن تكون قد استفدت منه وتعلمت منه شيئًا جديدًا. ترجمة -وبتصرّف- للمقال Expanding Search Bar Deconstructed لصاحبته Mary Lou.1 نقطة
-
بعد أن شرحنا في المقال السابق عن أهمية التحليل الرقمي (Digital Analytics) سَنشرح الآن كيفية عمل مَشروع تحليلي باستخدام (Google Analytics) من إنشاء حساب وعمل الإعدادات الأولية لتَتَبُع موقعك وتجميع (Collection) البيانات وكل ما عليك هو تَتَبُع الشرح مع تطبيق الخطوات بِدقة. أولاً: إنشاء حساب في Google Analytics:عليك التوجه إلى موقع Google Analytics، ثم الضغط على زر انشاء حساب كما هو مبين في الشكل التالي: سَيطلُب منك Google Analytics تسجيل الدخول على حسابك في جوجل (إن لم تكن مُسجّلاً دخولك)، بإمكانك تغيير لغة العرض إلى العربية بالضغط على "إعدادات المستخدم" أعلى يسار الشاشة (أيقونة المُسنّن) كما هو مُوضح في الصورة التالية: ثانياً: إضافة موقعك الالكتروني وربطه مع Google Analytics بشفرة تَتَبُع:عليك التوجّه إلى القائمة الإدارية بالضغط على زر "مسؤول" (Admin) في حِسابك ثُم الانتقال إلى قائمة "موقع ويب"، إضافة موقع جديد ثُم تقوم بِتعبئة طلب تَتَبُّع موقعك الالكتروني أو تطبيق جوّال بكتابة اسم الموقع – الرابط – اهتمامات / فئة الموقع – المنطقة الزمنية لإعداد التقارير ثُم تضغط على زر" الحصول على مُعرِّف التتبُّع"، عندها ستحصل على شفرة برمجية من نوع Javascript، سيتوجب عليك نسخها على ولصقها على موقعك حَسب نظام إدارة المحتوى المُستخدم. مثلاً: إن كان موقعك من نوع (Wordpress) فإن أسهل طريقة لإضافة شفرة التَتَبُع هي بالدخول على لوحة تحكم موقعك الالكتروني والذهاب إلى "الإضافات" وضغط على زر " إضافة جديد" ثم في مربع بحث الأدوات تكتب اسم الإضافة التالية: "Insert Headers and Footers" ونَصّبها على موقعك كما في الصورة التالية: ثُم انتقل إلى قائمة الإعدادات ستظهر لك الإضافة السابقة، اضغط عليها وأضِف شفرة التَتَبُع في قسم "Scripts in Footer" ثُم اضغط على حفظ "Save" كما في الصور التالية: وهناك طُرُق أخرى لإضافة شفرة التَتَبُع على موقع "Wordpress" أو أي موقع مُبَرمَج على لُغة PHP كإنشاء ملف برمجي فارغ مِن نوع PHP وتسميته "analyticstracking.php" ثم نسخ شفرة التَتَبُع فيه (يمكنك استخدام برنامج Dreamweaver أو notepad لإنشاء الملف) ثُم ارفع هذا الملف في مجلد موقعك افتح كُل صفحة تُريد تَتَبُعها مِن نوع PHP ثُم أضف السطر التالي في بدايتها: <?php include_once("analyticstracking.php") ?>مُلاحظة: يُمكن أن تستغرق عملية تَتَبُع موقعك وعَرض النتائج على Google Analytics فترة زمنية تتراوح من 12 إلى 24 ساعة. أما إن كنت تستخدم موقعا يدعم نظام Google Analytics كمُدونات Blogger أو قناة YouTube فإنك لا تحتاج إلى نسخ شفرة التَتَبُع كاملة، فقط عليك نسخ "رقم مُعرّف التَتَبُع" الخاص بحساب موقعك على Google Analytics (والذي عادة ما يكون من الشكل التالي: UA-12210000-2) ولصقه في المكان المخصص له في لوحة تحكم Blogger أو إعدادات قناة YouTube كما هو موضّح في الصورتين التاليتين: بالنسبة لـ Blogger بالنسبة لـ Youtube بعد تركيب شفرة التَتَبُع على موقك الإلكتروني أنصحك بتفعيل وإعداد المُميزات التالية: ميزة مُعرّف المستخدم (User-ID): تتيح لك إمكانية ربط بيانات المشاركة من أجهزة مختلفة وجلسات متعددة، حتى يمكنك اكتشاف كيفية تفاعل المستخدمين مع محتوى موقعك على مدار فترة زمنية ممتدة، ولتفعيل هذه الميزة انتقل لعمود موقعك في حساب Google Analytics ثم معلومات التَتَبُع (Track Info) في أسفل شفرة التَتَبُع اضغط على User-ID ملاحظة: يتطلب إعداد User-ID إجراء تغيير على شفرة التَتَبُع وننصحك إتمام هذا الإجراء بمُساعدة أحد مطوّري الويب (راجع دليل Google بخصوص هذه الميزة).إعدادات الجلسة (Session Settings): وهي تعيين مدة استمرار الجلسات والحملات ، وقبل تخصيص طول الجلسة عليك التفكير في اختلاف سلوك المستخدم بين مواقع ذو طبيعة نصية (textbased) ومواقع الفيديو، فإن من المنطق أن في الموقع النصي يُمكن للمستخدم قراءة بِضع صفحات وترك الأُخرى فترة قصيرة، فإن وضعنا مُدة مُهلة الجلسة لذلك الموقع 30 دقيقة تبدو معقولة أما مواقع الفيديو يُمكن للمستخدم مشاهدة شريط فيديو طويل وهذا أكثر من 30 دقيقة، مع تحليلات التطبيق الافتراضي لـ Google سوف تنتهي جلسة عمل المستخدم تلقائيا بعد 30 دقيقة من الخمول ولكن في الواقع لا يزال المُستخدمُ نشطاً على الموقع، في هذه الحالة فمن المنطقي تعيين طول مهلة جلسة أطول من مدة أطول فيديو على الموقع، ولتعيين هذه الخاصية انتقل إلى عمود موقع الويب. إذا لم تكن في قائمة الإعدادات، فانقر على المسؤول (Admin) حدد الموقع الذي ترغب في تعديله ، انقر على معلومات التَتَبُع ثم إعدادات الجلسة. تَخصيص مصادر البحث المجاني (Organic Search Sources): يُميّز برنامج Google Analytics الزيارات التي تصل موقعك من خلال محرك بحث عن الزيارات التي تصلك من خلال قنوات إحالة أخرى، مثل الإعلانات المدفوعة أو موقع آخر يرتبط بموقعك ، وفي تقاريرك يُطلق على شريحة الزيارات هذه زيارات البحث المجاني، يُصنف برنامج Google Analytics أشهر محركات البحث افتراضياً و تظهر الزيارات التي تصل إلى موقعك من خلال أية محركات بحث افتراضية كنتائج بحث مجاني في تقاريرك، وأما الزيارات التي تصل لموقعك من خلال أي محرك بحث غير مدرج في هذه القائمة، فتعتبر زيارة إحالة (وليست زيارة بحث مجاني) في تقاريرك، يمكنك إضافة، حذف وإعادة ترتيب قائمة محركات البحث المشهورة لتعديل كيفية إحالة زيارات البحث المجاني في حسابك وكيفية ظهور البيانات في تقاريرك، يحيل Google Analytics الزيارات الواردة لمصدر واحد. ملاحظة: يَتم تعيين زيارات البحث المجاني لأول مُحرك بحث في القائمة والذي يُطابق اسم النطاق ومُعلّمات طلب البحث (parameter search query) للزيارة الواردة، ومُعلّمات البحث هي عبارة عن رموز تكون في رابط (URL) للموقع للدلالة على حدث مُعين مثل رمز لغة العرض في نهاية رابط في بعض المواقع، مثال: https://www.google.com/webhp?hl=ar&q=what+is+a+google+advanced+searchفي الرابط السابق هناك مُعلمات بحث بعد رمز "؟"وهي " hl=ar" وهي تدل على لغة العرض العربية وعادة اذا غيرتها الى " hl=en" تكون لغة العرض الإنجليزية ورمز "&" تدل على إضافة مُعلّمة أُخرى وهي "q" وتدل على استعلام البحث ، لذلك إن كُنت تَعرف معلمات البحث فإنه يُمكنك فهم طبيعة عمل الرابط السابق بكل سهولة من غير استعراضه في المُتصفح ففي المثال السابق يكون معنى الرابط كالتالي: الدخول على محرك بحث جوجل (www.google.com) ثم تكون لغة العرض العربية (? hl=ar) مع البحث عن الجملة التالية "What is a google advanced search" أي (q=what+is+a+google+advanced+search) والصورة التالية توضح مثالا آخرا على مُعلمّات البحث (query parameter search) في رابط (URL) الموقع: وإن أردت مزيدا من المعلومات عن المُعلّمات يُمكنك مراجعة دليل المُعلّمات لمحركات البحث. على سبيل المثال، إذا أدرجت "http://www.google.ps" كأول محرك بحث في القائمة و "images.google.ps" الثاني ، (مع العلم أن كلا منهما يستخدم نفس معلمات طلب البحث (query parameter) مثل مُعلّم "q" فإن كل عمليات البحث التي تَتِم على (images.google.ps) ستتم إحالتها إلى "google.ps" ولتغيير هذه الإحالة، يُمكنك إعادة ترتيب مُحركات البحث هذه في القائمة لتحديد أولويات كيفية إحالة الزيارات. و في هذا المثال، يُمكنك إدراج (images.google.ps) قبل (google.ps) لتتم إحالة الزيارات بصورة سليمة وإن قُمت بإزالة محركات البحث مِن هذه القائمة سوف تظهر كل زيارة واردة منها كزيارة إحالة بدلاً من زيارة بحث مجاني. ملاحظة: إذا كنت تتحكم في محرك بحث يتداخل مع محرك بحث آخر في هذه القائمة يستخدم نفس مُعلّمة طلب البحث. فأنصحك بتغيير مُعَلّمَة البحث إلى عنصر فريد لكي تتجنب هذا الوضع. والخطوات العملية لتغيير هذا الإعداد هي: من عمود الموقع، انقر على معلومات التتبع ثم مصادر البحث المجاني. انقر على +إضافة محرك بحث. في النموذج، حدد ما يتضمنه اسم النطاق ومُعَلّمَة طلب البحث ويمكنك أيضًا تحديد اسم محرك البحث وما يتضمنه المسار. انقر على إنشاء (Create). أُنقر على تعديل أو حذف لتغيير أو إزالة مُحرك بحث أضفته من قبل و يُمكنك السحب والإفلات لترتيب كُل صَف باستخدام الفأرة. إن كُنت تُريد الحصول على طرق أكثر لإضافة وإزالة مُحركات البحث من هذه القائمة، و دليل كل محرك بحث ومُعَلّمَاته، راجع دليل Google والمرجع كامل حول إدارة محركات البحث والإحالات. استبعاد بعض النطاقات من مصادر الإحالة (Referral Exclusion List): يُمكنك استبعاد نطاقات مُحددة بحيث لا يتم تمييزُها كمصادر زيارات إحالة في تقاريرك على Google Analytics يَتمثل الاستخدام الشائع لهذه الميزة في استبعاد زيارات من موقع خارجي متصل بموقعك بخدمة ما ، مثل طلب تسجيل او استبيان أو عربة تسوق، ومنع احتساب جلسة جديدة (New Session) كإحالة عندما يَتِم إعادة توجيه الزوّار إلى موقعك مرة أخرى. حساب عدد الجلسات (Sessions): هو عدّاد جلسات يَتم تشغيله كُلما دَخل أحد المُستخدمين على موقك، على سبيل المثال: إذا دخل المستخدم "س" إلى موقعك لأول مرة في الأسبوع الماضي، فإن عدد جلسته يكون 1، وإذا كرّر هذا المُستخدم الزيارة في هذا الأسبوع فسيكون عدد جلسته 2، ويَتزايد العدد على هذا النحو في كل مرة يَرجع فيها المستخدم لموقعك. والأن سنتعرف على كيفية إضافة أو إزالة مصادر زيارات الإحالة في حساب Google Analytics. أولاً: إضافة مَصادر استبعاد الإحالة:سجِّل الدخول إلى حسابك في Google Analytics. 1. انقر على المسؤول في شريط القائمة أعلى أي صفحة. 2. في عمود الحساب، استخدم القائمة المنسدلة لتحديد حساب Analytics الذي يحتوي على الموقع الذي تريد التعامل معه. 3. في عمود الموقع، استخدم القائمة المنسدلة لتحديد أحد المواقع. 4. انقر على معلومات التتبع. 5. انقر على قائمة استبعاد الإحالات. 6. لإضافة نطاق، انقر على +إضافة استبعاد إحالة. 7. أدخل اسم النطاق. 8. انقر على إنشاء للحفظ. ثانياَ: إزالة مصادر زيارات الإحالة إذا كنت قد أضفت نطاقًا إلى قائمة الاستبعادات، يمكنك إعادة تقديم تلك الزيارات كمصدر إحالة في تقاريرك مرة أخرى قُم بإزالة النطاق من قائمة النطاقات المستبعدة. اتبع الخطوات من 1 إلى 6 أعلاه، انقر على إزالة في صف النطاق الذي تريد إزالته. انقر على حذف النطاق للحفظ. كيفية تأثير استبعاد زيارات الإحالة على بياناتكإن لم تَستَبِعد زيارات الإحالة تبدأ الإحالة بجلسة جديدة تلقائيًا. ولكن عند استبعاد مصدر إحالة فإن الزيارة التي تصل إلى موقعك من النطاق المستبعد لن تبدأ بجلسة جديدة وإذا أردت أن تبدأ الزيارات التي تصل إلى موقعك من موقع محدد بجلسة جديدة فاستبعد هذا النطاق من ذلك الجدول. مثال، انتقل أحد المستخدمين على (my-site.com) إلى(your-site.com) ، ثم عاد إلى (my-site.com) فإذا لم تستبعد (your-site.com) كنطاق إحالة، سيتم احتساب جلستين، بواقع جلسة واحدة لكل حالة وصول إلى (my-site.com)، أما إذا أدرجت النطاق your-site.com في حالة استبعاد الإحالات، فإن حالة الوصول التالية إلى (my-site.com) لن تبدأ جلسة جديدة، وسيتم احتساب جلسة واحدة فقط، وبالتالي سيكون لديك دقة أكبر في عرض نتائج التحليل الحقيقية للموقع. استبعادات عبارات البحث (Search term exclusions): لاحتساب بعض زيارات البحث كزيارات مباشرة. يتعرف Google Analytics على العبارات التي استخدمها المستخدمون للعثور على موقعك من خلال محركات البحث، ويعرض هذه الكلمات الرئيسية (بما في ذلك العبارات) في تقاريرك. يمكنك استبعاد عبارات بحث محددة من حسابك في Analytics، وعندما يَعثر المُستخدمون على موقعك باستخدام عبارة مستبعدة، لا يتم إدراج تلك الزيارة كزيارة بحث في تقاريرك، وبدلاً من ذلك ستُحتسب على أنها زيارة مباشرة وربما ترغب على سبيل المثال في استبعاد اسم شركتك أو نطاقك كعبارات بحث, وعندها فإن أية زيارات تصل إلى موقعك من خلال البحث باستخدام هاتين العبارتين ستظهر كزيارات مباشرة في تقاريرك. عند استبعاد زيارات بحث تصل إلى موقعك باستخدام كلمات رئيسية محددة، فإن الأنشطة الأخرى من تلك الزيارات - مثل عرض الأحداث أو إكمال الأهداف - ستُحتسب في تقاريرك. استبعاد عبارات البحث في حساب Google Analytics يكون كالتالي: - انتقل إلى موقع الويب. إذا لم تكن في شاشة الإعدادات، فانقر على "المسؤول". - انقر على "معلومات التتبع" ثم على علامة التبويب "قائمة استبعاد عبارات البحث". - انقر على "+إضافة عبارة بحث". - أدخل كلمة، عبارة أو سلسلة ما بصفتها "عبارة بحث". - انقر على "إنشاء" للحفظ. دعنا نُراجع ما تَم شرحه في هذا المقال باختصار شديد كالتالي: إنشاء حساب Google Analytics . إضافة شفرة التَتَبُع على موقعك بما يتناسب مع نظام إدارة المحتوى لديك. إمكانية ربط بيانات المشاركة من أجهزة مُختلفة وجلسات مُتعددة أو مُعرّف المستخدم User-ID) ) . تعيين مدة استمرار الجلسات والحملات (Session Settings) . تَخصيص مصادر البحث المجاني (Organic Search Sources) . إستبعاد بعض النطاقات من مصادر الإحالة (Referral Exclusion List). إستبعادات عبارات البحث (Search term exclusions). إلى هنا، نكون قد نعرفنا على إعدادات التَتبُع الأولية لحساب Google Analytics بتقنية Universal Analytics التي تُتيح لك إعدادات ابتدائية -عن طريق الأدوات التي تم عرضها- لتخصيص طُرق تجميع البيانات (Collection) على Google Analytics وهي أحد أولى مراحل التقفي وتحليل البيانات لـ Google Analytics.1 نقطة
-
دَعني أختصر لك المقال كاملًا في جملةٍ واحدة: ستحقّق ربحًا إن أنفقت أقلّ مما تَجنيه من المال. الأمرُ بديهيٌّ وواضح، أليس كذلك؟ الرّبح (أي ما تجنيه مطروحًا منه ما تنفقه) يُحقَّق بيُسرٍ إذا كان ما تنفقه شيئًا يسيرًا. قد تعتقد أن الأيسَر والأقلَّ مشقّةً عندما تعمل كمستقلٍّ أن تقدم لعملائك عملًا ذا كفاءةٍ عاليةٍ وإبداعٍ أخّاذ بدلًا من التفكير في الإدارة المالية ونفقات العمل، فأنت بهذا تفعلُ ما تحبُّ وتقبض ثمنًا جيّدًا لذلك في نفس الوقت، وقد تعتقد أن إعداد ميزانيةٍ ماليّة خاصٌّ فقط بأولئك المستقلين الواقعين تحت وطأةِ أزمةٍ ماليّةٍ ما، لكنَّ هذا منطقٌ مغلوطٌ وغيرُ سليم. عندما لا تعيرُ الإدارة الماليّة اهتمامًا، ولا تنتبه لما تنفقه سواءً على الصعيد الشخصيّ أو فيما يتعلّق بأمور العمل، سينتهي بك الأمرُ مضطرًا للعملِ أكثر حتى تحافظ على نفس مستوى الرّبح، أو ستجد نفسك تنفقُ أكثر مما تجني مما قد يعرّضك لأزمةٍ ماليّة، أو ستعجَز عن عملِ موازنة للأمور البسيطة الأساسيّة كتكاليف السكن والمواصلات. وفقًا لـ statsCan (اختصارًا لـ statistics Canada وهي منظّمة تهتم بعمل إحصائيّات متعلّقة بالمجتمع الكنديّ ) فإنَّ العائلات الكنديّة التي تُسجّل دخلًا سنويًّا يتجاوز 100 ألف دولار هي المسؤولةُ عن 37 بالمئة من الديون. سنة 1982 كنّا نحتفظ بحوالي 20% من مداخيلنا كمدّخراتٍ أو استثمارات، لكن بحلول 2014 تهاوت هذه النسبة لتصل إلى 4% من المداخيل فقط. لا يمكنك أن تقول للعميل "الميزانيّة مفتوحةُ، ستدفع بعض المال مقابل خدماتنا وسنتكفّل نحن بالعمل". إذًا لماذا تهمل وضعَ ميزانيّةٍ لك؟ مهمٌّ جدًّا أن تركّز جيّدا لما يتعلّق الوضع بأمورك الماليّة، عندها فقط تستطيع أن تقدِّر كلَّ شيءٍ قدره فيما يتعلّق بالإنفاق أسرار عمل ميزانية ناجحة في العمل الحر1. حدد لنفسك راتباكونُكَ تعمل كمستقل لا يعني عدم تحديد راتبٍ شهريٍّ ثابتٍ لك. وإن كنت لا تعرف كيف تقدّره فاحسب متوسط عوائدك الماليّة في السنة الماضية وقدّر راتبك ب70% من هذه القيمة، أما الـ30% الباقية فاجعلها للضرائب، وإن كانت الضرائب قليلة فاستثمر باقي الـ30% ووظّفها. هذه الطريقة سوف تقنّن تعاملك مع المال وتجعلك على درايةٍ تامّةٍ بكمِّ المال الذي معك، لأنّ لك راتبًا شهريًّا ثابتًا الآن. 2. ابق على اطلاع بكل شاردة وواردة فيما يتعلق بالأمور الماليةسواءً استعملت البرمجيّات باهظة الثمن المتعلّقة بإدارة الميزانيّة وإجراء الحسابات، أو تطبيقات الجَدْوَلَة المجّانيّة- سجل جميع عوائدك ونفقاتك الشهرية، هذا سيساعدك على معرفة الأمور التي تنُفق فيها أكثر مما يجب. 3. اعرف الضروريات التي لا يمكن الاستغناء عنهاحدّد مقدار المال الذي تحتاجه لأمور السكن والطّعام وحدّد ضِعفَ ذلك المال تقريبًا كميزانيّةٍ شهريّةٍ لعملك. وإن لم تستطع ذلك فحاوِل الاقتصاد في مصروفاتك المنزليّة والشخصيّة كمتعلّقات السيّارة والسّكن، كُن عمليًّا فيما يتعلّق بهذين الأمرين بالتحديد لأنّهما يكلّفان الكثير من حيث الصيانة والإصلاح. 4. هيء نفسك للأيام الصعبة.أحبُّ أن أدّخر 10% من راتبي للحالات الطارئة، كعدم مقدرتي على العمل لأشهر، أو عدم سير العمل على ما يرام، أو حتى الأزمات الاقتصاديّة العالميّة. ادّخار 10% من راتبك الشّهري لسنةٍ كاملة يجعلك تنعم بنومٍ هانئٍ ليلًا لأنّك تعرف أنه إذا ساءتِ الأمور، ستملكُ مالًا يكفيكَ لمدّة سنةٍ كاملة. 5. رتب النفقات حسب الأولوية.إذا كان لديك الكثير من الأمور التي تحتاج المال (سواءً على الصَّعيد الشخصيّ أو على صعيد العمل) رتّبها حسب الأولوية في قائمة. حدّد ما الذي يجب شراؤه الآن وما الذي يمكنك تأجيله لشهرٍ أو اثنين. معظمُ الأمور لا يكون من الضروريِّ شراؤها أو الدَّفع فيها بشكلٍ مُستعجِل (باستثناء إصلاح السِّباكة مثلًا! ). ليس من الضَّروري أن تمتلك أعظمَ وأحدَث المُعِدّات والأدوات أو البرمجيّات أو تجدّد خدمات الاشتراك غير الضّروريّة. 6. استعمل طرقا بسيطة لادخار المال.لا يهمُّ مقدار المال الذي تجنيه، جِد طُرُقًا في كلّ الأحوال للتّوفير والادّخار. تخلَّ عن الهاتف الثابت (استعِض عنه بسكايب)، توقَّف عن الأكلِ في المطاعم (الطَّبخُ ممتعٌ، خاصَّةً إن كنت تطبخٌ للآخرين!)، لا تشترِ ثيابًا جديدةً طالما ثيابك لم تبلَ بعد، توقّف عن شراء القهوة والشاي من المقاهي والمحلّات (القهوة المنزليّة رائعة)، افصِل الأجهزة التي تستهلك طاقةً احتياطيّة. كلّما أنفقت أقلَّ على الأمور التي تستطيع العيشَ دونها، كلّما قلَّ اضطرارك للعمل وقتًا أطول وكلَّما امتلكتَ متّسعًا أكبر من الوقت للاستمتاع بالحياة. حدّد الأمور غير الضّروريّة التي أنفقت عليها مالك في الشُّهور القليلةِ الماضية. وانتبه، كلُّ شيءٍ محسوب! 7. نوع مصادر دخلك.طالما كنت تعملُ عملًا حرًّا، أنتَ المسؤول الوحيد عن وسائل جَنيِكَ للمال ولك كاملُ الحريّة في تنويعها، فلا شيءَ يعترضُ طريقكَ للبحثِ عن مصادر دخلٍ متنوّعة. أجني المال حاليًّا بطرقٍ متعددة: عملُ التصميمات للعملاء، توفير خدمات الاستشارات، إذاعةُ البرامج، إقامةُ دوراتٍ تدريبيّة وتأليفُ الكتب. بهذه الطّريقة، أستطيع الاعتمادَ على مصادرٍ دخلٍ أخرى في حالةِ عدم سيرعملي الأساسيّ على ما يرام. أحبُّ أن أقدِّم مزيجًا من المنتجات والخَدَمات، وهذا يجعل منتجاتي (إذا وضعتُ لها أساسًا جيِّدًا وعملت على تطويرها باستمرار) تقدِّم لي عوائد ماليّةً حتى إن توقّف عملي لبعض الوقت. تمامًا كالمحفظة الاستثماريّة، التنوُّع هو مفتاحُ وسِرُّ النمو. ما الذي تعلمته من ممارسة العمل الحر لثمان عشرة سنةأعلمُ أنّ الحديث عن المال ليس أمرًا مستساغًا لدى بعض الناس، لكنّ الخوض في الأمور الماليّة ضروريٌّ ولا مناصَ منه، خاصةً في مجال الحرّ وبالنّسبة للمستقلين. خلال سنوات عمليَ الحر، تصالحتُ مع عدم كوني باذخ الثّراء، لا يلزمُني شراءً سيّارةٍ فارِهةٍ أو منزلٍ باهظِ التّكاليف، أستغلُّ كلَّ دولارٍ أربحه بشكلٍ صحيح وأدّخرُ بفعاليةٍ فلا يلزمني أن أصرف المزيد من الوقت لكسب مزيدٍ من المال، يمكنني الاستمتاعُ بحياتي بدلًا من ذلك! اعتبار عمل الميزانيّة والادّخار تحدٍّ تستطيع ربحه كلّ شهرٍ بدلًا من التذمّر والسخّط يجعل ذلك أمرًا مسليًا. أُخضع نفسي أحيانًا لتحدّياتٍ على غرار: لنرى هل سأستطيع ألا أتسوّقَ للطعام وأكتفي بما هو موجودٌ في الثلاجة؟ هل سيمكنني أن أتخلّى عن طلب قهوةٍ مرتفعةِ السّعر من أحد المقاهي؟ أو حتى هل سأستطيع ادّخار مصروفات الإيجار والطعام والوقود لمدة ستة أشهر؟ اخلُق لنفسك تحدٍّ خاص بادّخار المال! اكتشفتُ أيضًا أنني أستمتع بالأشياء المجّانية التي لا تطلب إنفاقًا للمال أكثر من غيرها إن أعطيتها فرصة! المشي، العمل في الحديقة، السباحة في البحر/البحيرة، النزه البريّة، لعبة الطاولة، ودعوةُ الأصدقاء للعشاء في المنزل (بدلًا من تناول الطعام في مطعمٍ فاره) جميعها أشياءٌ مبهجة. لا نهدي أنا وزوجتي هدايا لبعضنا في أعياد ميلادنا أو في المناسبات! بدلًا من ذلك، نخطّط لإعداد وجبةٍ رائعةٍ سويًّا. لا نحتاجُ الماديّات، لكنّ حاجتنا للأوقات الممتعةِ لا محدودة. خلاصة القولأكرّرُ مرّةً أخرى لما قُلتُه في السّطور الأولى: ستحقّق ربحًا إن أنفقت أقلّ مما تَجْنيه من المال. وأساسيٌّ لذلك أن تفعل الآتي: ادفع لنفسك راتبًا شهريًّا حتى وإن كانت عوائد عملك تختلف من شهرٍ لآخر، وحتى إن كنت تعمل مستقلًّا بذاتك تمامًا.كن على درايةٍ تامّة بعوائدك ومصاريفك الشهريَّة. خطّط للضرائب والأزمات والأمور غير السارّة التي قد تفاجئُك بها الحياة.كن واعيًا لهدفك الأساس لجمع المال، لأنَّ الحياة أكثر من مجرَّد عملٍ وربحٍ وبرامج جدولة.الآن عجِّل بإدارةِ مالك، الأمرُ ليس بمتعةِ أداء العمل بإبداعٍ وكفاءةٍ عظيمَين، لكنّه بنفس الأهميّة. ترجمة –وبتصرّف- للمقال: The surefire way to turn a profit when you work for yourself. حقوق الصورة البارزة: Designed by Freepik.1 نقطة
-
انّ معدّلات التحويل وأنماط الاستخدام تعني قضاء العديد من الليالي بالعمل المستمر. يطلق فريقك خاصيّة جديدة، ينشر إعلان عنها، ثم يجلس منتظرًا المجد. وفي النهاية لا تحصل على أي شيء. تتساءل مباشرةً: "لماذا لا يستخدم الناس المنتج؟"، لكنّ هذا ليس هو السؤال المناسب. السؤال المناسب والمفيد هو: "كيف يمكنني أن أجد كل أسباب استخدام الناس للمنتج وتحديد الأولوية فيها؟". اللماذات الخمس والسبب الجذريأوجد المخترع الياباني Sakichi Toyoda تقنية اللماذات الخمس لإيقاف الناس عن حل ظواهر المشكلة ومعالجة الأسباب الجذرية بدلًا من ذلك. عندما تعترضك مشكلة، يمكنك ببساطة أن تسأل "لماذا" خمس مرّات، ثم تحلّ المشكلة الجذرية. تأكّد من أنّ المشكلة لن تتكرر فيما إذا طبّقت هذه التقنية بشكل صحيح. يشير الباحث والكاتب الأمريكي Jared Spool إلى مخاطر افتراض أنّك تعرف الإجابة على "لماذا" دون التحقق من صحة افتراضك. قد يبدو المخطط أعلاه مرتّبًا ومُنظّمًا، ولكنّه يحمل مجموعة واسعة من الافتراضات. وفي الواقع، هذا ما يبدو عليه: هنالك العديد من الإجابات الكامنة في كل "لماذا"، وكلما كررت هذا السؤال، كلما استنبطت بشكل أعمق. هنالك المئات من المسارات التي تظهر عند تطبيق تقنية اللماذات الخمس، وسيكون من السيئ والمبتذل استخدام المعلومات الظاهرية والأدلّة القوليّة التي تسمعها عن منتجك في اتخاذ القرارات بدلًا من اتخاذها على أساس البيانات. البحث يؤثر على قرارك في التحسينمن الضروري أن تفهم الأسباب الجذرية عندما لا يقوم المستخدمون بفعل أي شيء بمنتجك، سواء كان ذلك الشيء الاطلاع على المنتج، استخدام خاصيّة ما، أو دعوة صديق؛ اسألهم عن السبب. إنّ اختبارات A/B تساعدك على إجراء التغييرات التي توصل منتجك إلى مرحلة الحد الأقصى المحلي Local Maxima، لكنّها لا تتيح لك الفهم الحقيقي. غيّر لون أي زر من الأخضر إلى الأحمر وسترى فرقًا دقيقًا في الإنتاجيّة، لكنّ هذا الفرق تعود جذوره إلى الجماليات، وليس إلى رغبة المستخدم، دافعه، أو فهمه للمنفعة من المنتج. صنف المشاكل افهم وحدّد السبب الجذري، لأنّ ذلك يحدد أولويات مشاكلك، ويتيح لك تحديد المشاريع حسب تجربة المستخدم، مثلًا،" يجب أن يكون المشترك الجديد قادرًا على توليد تقرير بنجاح بدون الاتصال بالدعم" (الأمر الذي يمكنك إجراء اختبارات المستخدم من أجله التحقق منه)، وحسب المقاييس، على سبيل المثال "يجب أن يتناقص عدد طلبات الدعم لكل تقرير يتم توليده" (الأمر الذي بإمكانك رصده). من الأفضل أن تقوم بإلغاء الخاصيّة إذا كانت أغلب مشاكلك تتمحور حول دوافع المستخدم، ثم تتحرى عن سبب إضافتك لهذه الخاصيّة من البداية؛ على الأرجح سيكون السبب هو أنّك لا تقول “لا” إلا نادرًا وتُحاول إضافة جميع الاقتراحات التي تصلك . أمّا إذا كانت أغلب المشاكل تتعلّق بالواجهة، فيجب أن تفكّر في تصميم جديد (بدلًا من التّمحور حول تصميم عاطل). إذا كان تصميمك لا يفعل شيئًا سوى إرباك العملاء فهذا بسبب أنّك لم تحصل على ردود فعل المستخدمين قبل إطلاقه. إنّ السؤال باستمرار "لماذا حدثت تلك المشكلة؟"، "كيف يمكنني حلّها؟" يساعدك على فهم وحلّ المشاكل ذات المستوى العالي عندما تكون صغيرة في بدايتها. أنت تريد أن تنمّي كل شيء عندما تمتلك شركة ناشئة، باستثناء المشاكل. لأنّ نمو المشاكل ليس جيّدًا على الإطلاق. ترجمة -وبتصرّف- للمقال Analyzing Abandonment in Your Product لصاحبه: Des Traynor.1 نقطة
-
بالنسبة لخدمتي الترجمة والتدوين غالباً لا يتم شراء هذه الخدمة بشكل مباشر إلا إذا كانت مشهورة جداً ولديها تقييم وعدد مشترين كبير، المفتاح هنا هو التسويق للخدمة وسأذكر طريقتين فعالتين أستخدمهما شخصياً بما أنني أقدم نفس الخدمة وتمكنت من بيع 22 خدمة خلال 3 أسابيع الطريقة الأولى : متابعة مجتمع الخدمات غير الموجودة وعند وجود طلب ترجمة تقديم عرض مع مراعاة التالية : - ترجمة عينة من النص في حال كان مرفق مع الطلب أو اخبار الزبون برغبتك في ترجمة عينة - وضع رابط لاعمالك السابقة - تحديد السعر + الكمية + المدة بوضوح - الابتعاد عن العروض الخرافية مثل ترجمة 20 مقال مقابل 5 دولار وفي يوم واحد! هذه العروض تشعر المشتري بعدم الاحترافية وبأنه سيحصل على جودة منخفضة. - الطريقة الثانية هي وضع رابط خدمتك في نهاية مقالاتك المترجمة المنشورة على مواقع الويب او المدونات إذا كان يسمح الموقع بذلك. - طريقة أخرى لم أجربها هي استخدام إعلانات حسوب ولكنك ستضطرين للدفع أولا قبل تحقيق دخل.1 نقطة
-
يدهشني كم تُذكر كلمة "الحظ" عندما يعلم الناس أنني بدأت SmartBear. "أنت محظوظ لأنك تدير عملك الخاص، فأنا أكره مديري!""أنت محظوظ لأن عملك بخير رغم الأزمة الاقتصادية.""أنت محظوظ لأنك بعت شركتك." إن كنت تحسب أن جهدك الذي بذلته على مشروعك، والساعات الطوال التي قضيتها في بناءه، والأفكار التي خرجت بها، والطريقة التي تعاملت بها مع الزبائن؛ إن كنت تحسب أن هذا كله سيُبهرهم، فأنت مخطئ! النجاح كله "حظ". تصرف الناس بهذا الأسلوب لا يحطّ من قدرك فحسب، بل يُهينك كذلك، فهو يعني ضمنيًّا أنّ نجاحك ليس بسبب جهدك، وإنما هو ضربة حظ.قراراتك لم تكن مهمّة، وأفكارك لم تكن مميّزة؛ كل ما في الأمر أنك محظوظ. يستطيع أي شخص عمل ما عملته. من السّهل كذلك أن تكون ردّة فعلك حاقدةً ومشابهة لذلك التصرّف: استقالتي من وظيفتي وعملي 60 ساعة في الأسبوع دون أجر لسنوات، حتى لقيت جزاء ما بذلته من جهد… كل هذا حظ إذًا؟ابتكاري منتجًا فريدًا من نوعه أحبه الناس، وبناؤه من الصفر… حظ؟عندما كوّنت علاقات حميدة مع الزبائن وأصغيت لما يريدون… حظ؟وعندما سنحت لي الفرص ببيع شركتي بسعر مُرضٍ ضمن صفقة وضعت في جيوب موظّفيَّ من المال ما لم تكن أي وظيفة لتضعه؟ هل هذا حظ؟هذه الردود ليست ظالمة، وهي تبيّن أنّ الأمر ليس حظًّا فقط، ولكن لأكون صادقًا معك، فالحظ كان له دور! بلى، علاقاتي بالزبائن كانت حميدة، لكن وجود الزبائن بحد ذاته ينطوي على شيء من الحظ! بلى، هم تعرفوا على منتجي من إعلانات Google، لكن أليس من الحظ اختياري لإعلانات Google في بداياتها وهي رخيصة ولمّا تمتلئ بالإعلانات السخيفة؟ نعم رسائل التسويق الّتي اخترتها كانت فعّالة ومُوجَزة، لكن ألم يكن من الحظ أن كان لديّ من يُعلمني كيف أفعل ذلك؟ يمكنني في الواقع اختيار أي قرار في تاريخ Smart Bear وستلاحظ أن القصة السابقة تُعاد بالنمط ذاته. الخلاصة؟ الحظ والاختيار لا ينفصلان. ما أعنيه بالتحديد: الحظ السعيد والحظ السيئ يُحيطان بك باستمرار، أما كيف تستخدم حظك، فهذا ليس حظًّا! ألاحظ نمط قرار/حظ/قرار/حظ هذا في كل قصص النجاح. ولكن ماذا عن قصص الفشل؟ حملات إعلانية كثيرة فشلت في شركتي. الإعلانات لم تُفلح في بعض المجلات (دون ذكر أسماء، لأن الصحافة المطبوعة تواجه ما يكفيها من المشاكل!). أنفقت في بعض الحالات آلاف الدولارات -رقم يعني نسبة كبيرة من العوائد في ذلك الوقت- على إعلانات لم تجلب زبونًا واحدًا! بعض الإعلانات فشلت في مجلة ونجحت في آخرى. هذا حظ سيئ فقط. خيار إلغاء بعض الإعلانات دون غيرها لم يكن حظًّا. الحقيقة، كان قرارنا قياس كفاءة كل إعلان بمفرده في المطبوعات. لو لم نفعل هذا لم نكن لنستطيع تمييز النجاح من الفشل، وعندها كان مصيرنا سيعتمد على الحظ فقط. النجاح النهائي في العمل لا يعني أنك "كنت محظوظًا"، بل يعني أنّك استخدمتالحظ، مستغلًّا النوع الجيّد منه، ومتجنّبًا النوع السيّئ بعد تمييزه. لن تسمعَ كلمة "محظوظ" كثيرًا عندما أتحدّث إلى رياديّين آخرين، فهم مهتمّون بالقصص والنصائح وطريقة العمل، وكيف نُفكّر، لا كيف يُقلّدوننا. السؤال "من أين جئت بالفكرة؟" خاطئ، والصواب "كيف علمت أن الوقت مناسب لهذه الفكرة؟"، أو بالتحديد: "كيف يعلم المرء أن الإعلان المطبوع يؤتي ثماره؟" أفضل رهان على النجاح هو أن تُعامل كل قراراتك على أساس أنها تجارب؛ فالثقة بالنفس والتجربة أمران لا يتعارضان. جرّب أيّ شيء، وقِس كلّ شيء، استمر في ما ينجح، وإن كان معنى هذا تغيير كل شيء! ربما يكون الحظ حليفك بعد كل هذا! ترجمة -وبتصرف- للمقال How much of success is luck لصاحبه: Jason Cohen. حقوق الصورة البارزة: Designed by Freepik.1 نقطة