Posts Tagged ‘iphone’

Kzalek for iPhone

17/03/2011

السلام عليكم و رحمة الله و بركاته

قمت بحمد الله بإصدار Kzalek for iPhone أمس ، هل ستصدقوا إن قلت لكم انه ١٠٠٪ جافاسكربت بإستخدام Appcelerator Titanium Mobile ، قد كتبت تدوينة فى مجلة Catazine أتحدث فيها عن Appcelerator و كيفية العمل به ، هل مازلت لا تنوى تعلم جافاسكربت ؟

HTML5 storage الجزء الثانى

14/08/2009

السلام عليكم و رحمه الله تعالى و بركاته

فى هذا الجزء أتناول كيفيه تخزين البيانات فى قاعده بيانات SQLite من خلال local JavaScript Database api

مقدمه
إنشاء و فتح قاعده البيانات
إنشاء جدول جديد
إضافه بيانات للجدول
إستخدام العبارات الجاهزه
إختيار بيانات من الجدول
التعامل مع اخطاء تنفيذ ال SQL
أرقام الأخطاء و مدلولاتها
التعامل مع اخطاء ال transaction
التعامل مع اصدارات قاعده البيانات
الدعم من المتصفحات
للمزيد

مقدمه

تحتوى مواصفات HTML5 على وصف ل Local JavaScript Database قاعده بيانات محليه تمكنك من تخزين البيانات داخل متصفح المستخدم فى قاعده بيانات SQlite بدلا من الكوكيز التى تقتصر مساحتها التخزينيه على 4 كيلو فقط ، قاعده البيانات SQLite على ملايين اجهزه المحمول و الاجهزه الكفيه و السيرفر و الكثير من تطبيقات سطح المكتب لصغر حجمها و مرونتها و تدعيمها شبه الكامل ل SQL ANSI ، للمزيد عن SQL و SQLite داخل المتصفح من هنا ، العمليات التى تتم على قاعده البيانات تكون غير تزامنيه asynchronous اى تتطلب كل عمليه تسجيل وظيفه تستمع لحدث نجاح العمليه او حدوث خطأ ، كما ان العمليات كلها تتم بنظام transaction لأن بيئه المتصفح غير مستقره ، يمكن لأى عمليه ان يقطعها refresh او اغلاق نافذه المتصفح ، اى انه إذا حدث خطأ فى عمليه مكونه من عده خطوات فإن قاعده البيانات لن تتأثر بأى من هذه الخطوات ، مثلا اذا كنت تغير بعض البيانات من جدول A ثم تضيف بيانات فى جدول B و تحذف بيانات من جدول C و قمت بإغلاق المتصفح فى منتصف خطوه اضافه البيانات للجدول B ، فإن خطوه تغيير البيانات من الجدول A سيتم التراجع عنها و لن يحدث اى تأثير ، إلا اذا تمت جميع عمليات ال transaction بنجاح .

إنشاء و فتح قاعده بيانات

قبل ان تتمكن من إستخدام قاعده البيانات عليك اولا فتح اتصال بها ، عندما تقوم بفتح اتصال سيتم انشاء قاعده بيانات جديده فارغه اذا لم يتم انشائها من قبل ، لذلك فإن عمليه فتح و انشاء قاعده البيانات متماثله ، يتم فتح الاتصال بقاعده البيناات عن طريق عن طريق الوظيفه openDatabase التى تقبل اربع عبارات : العباره الاولى هى إسم قاعده البيانات ، العباره التانيه هى إصدار قاعده البيانات للمزيد انظر الجزء الخاص بالتعامل مع اصدارات قاعد البيانات ، العباره الثالثه هى الإسم الذى يستخدمه المتصفح للتفاعل مع المستخدم مثلا عند طلب إذن بزياده الحجم المتاح لقاعده البيانات ، العباره الرابعه هى الحجم الذى تتوقع ان تشغله قاعده البيانات التى تقوم بالعمل عليها و اذا تعدت هذا الحجم المتفق عليه سيتم أخذ إذن المستخدم بأعطاء المزيد من الحجم لقاعده البيانات ، المثال التالى يوضح إنشاء قاعده بيانات بإسم keepondev إصدار 1.0 و حجمها 64 كيلوبايت و لها الإسم keepondev database لإستخدامه عند التفاعل مع المستخدم :

var db = openDatabase("keepondev", "1.0", "Keepondev database", 65536);

إنشاء جدول جديد

بقيه امثله هذا الموضوع تعتمد على جدول بإسم goals يحتوى على عمودين id و name :

CREATE TABLE IF NOT EXISTS goals (
    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL
);

يمكنك انشاء هذا الجدول من خلال تنفيذ جمله ال SQL السابقه على قاعده البيانات keepondev عن طريق الوظيفه executeSql التابعه للكائن SQLtransaction – فى المثال بإسم tx – الذى يتم تمريره للوظيفه التى تمرر للوظيفه transaction 8O التابعه للكائن الناتج من openDatabase كما يوضح الكود التالى :

var db = openDatabase("keepondev", "1.0", "Keepondev database", 65536);

function resultHandler(){
    alert("success");
};
function errorHandler(){
    alert("fail");
};
db.transaction(function(tx){
    var sql = "CREATE TABLE IF NOT EXISTS goals(";
    sql += "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
    sql += "name TEXT NOT NULL DEFAULT 'secret goal');";
    tx.executeSql(sql, [], resultHandler, errorHandler);
});

الوظيفه transaction تقبل وظيفه يمرر لها كائن من نوع SQLTransaction بإسم tx فى المثال السابق ، الكائن tx يحتوى الوظيفه executeSql التى تقبل اربع عبارات ، العباره الاولى هى جمله ال SQL التى قمت بوضعها فى المتغير sql و كتبتها على اكثر من سطر حتى لا تخرج عن عرض المدونه ، العباره التانيه مصفوفه تقبل قيم العبارت الجاهزه للمزيد انظر الجزء الخاص بإستخدام العبارات الجاهزه prepared statements ، العباره الثالثه وظيفه يتم إستدعائها اذا تم تنفيذ جمله ال SQL بنجاح ، و العباره الرابعه وظيفه يتم إستدعائها اذا حدث خطأ اثناء تنفيذ جمله ال SQL ، تلك الوظيفتين ستقوم بإظهار نافذه منبثقه ب success او fail فقط ، للمزيد انظر الجزء الخاص بأخطاء تنفيذ ال SQL و الجزء الخاص بأخطاء ال transaction ، يمكنك التأكد من انشاء الجدول و قاعده البيانات بنجاح داخل المتصفح Safari 4 من خلال فتح ال tab الخاص ب database الذى يمكن الحصول عليه من Sesstings > preferences > advanced > show develop menu in menu bar ، ستجد قائمه جديده بإسم develop دخلت فى القائمه file ، قم بقتح tab ال database كما توضح الصوره التاليه :

Safari Database tab

داخل tab ال database ستجد قاعده بيانات بإسم keepondev تحتوى على جدول فارغ بإسم goals ، يالا بينا نملاه .

إضافه بيانات للجدول

إضافه بيانات للجدول ماهى إلا تنفيذ جمله SQL من نوع INSERT بعد فتح قاعده البيانات و عمل transaction بنفس ترتيب الخطوات السابقه ، كما يوضح المثال البسيط التالى :

var db = openDatabase("keepondev", "1.0", "Keepondev database", 65536);
db.transaction(function(tx){
    var sql = "INSERT INTO goals (name) VALUES ('world domination')";
    tx.executeSql(sql, [], resultHandler, errorHandler);
});

الشىء الوحيد المختلف فى المثال السابق هى جمله ال INSERT التى تقوم بإضافه صف جديد فى الجدول goals و تظبط قيمه العمود name الى world domination اما العمود id فيأخذ رقم تلقائى ، هناك مأخذ على طريقه الاضافه السابقه : لو احتوت القيمه على ‘ سيحدث error و يمكن ايضا حقن جمله SQL و عمل هجمه من نوع SQL injection ، الطريقه الافضل لإضافه البيانات هى إستخدام العبارت الجاهزه .

إستخدام العبارات الجاهزه

إستخدام العباره الجاهزه يمكنك من إستخدام ال ‘ و ال ” داخل القيم بدون الخوف على كسر جمله ال SQL ، ثم انه يستحيل حقن SQL داخل العبارت الجاهزه و عليه لا يمكن حدوث هجمات SQL injection ، و تزيد كفائه تنفيذ عمليه اضافه اكثر من صف فى الجدول .

قم بوضع علامه استفهام ؟ بدلا من وضع قيمه العمود فى جمله ال SQL ، و بداخل المصفوفه [] التى هى العباره التانيه للوظيفه executeSql قم بإضافه القيمه ، او ضيفها من ناتج مدخل المستخدم كما يوضح الكود البسيط التالى :

var db = openDatabase("keepondev", "1.0", "Keepondev database", 65536);
db.transaction(function(tx){
    var sql = "INSERT INTO goals (name) VALUES (?)";
    tx.executeSql(sql, ["Conference speaker"], resultHandler, errorHandler);
    tx.executeSql(sql, ["technology innovator"], resultHandler, errorHandler);
    tx.executeSql(sql, ["JavaScript evangelist"], resultHandler, errorHandler);
    tx.executeSql(sql, ["most infeluence person of all time"], resultHandler
    , errorhandler);
    tx.executeSql(sql, ["space trip"], resultHandler, errorhandler);
});

يمكنك منع التكرار فى الكود بإستخدام partial function و النتيجه كما تظهر فى الصوره التاليه :

database tab showing keepondev goals table

إختيار بيانات من الجدول

اختيار بيانات من الجدول عباره عن استخدام جمله SQL من نوع SELECT بالإضافه إلى إستقبال البيانات من خلال الوظيفه resultHandler التى كانت وظيفتها فى الامثله السابقه عمل alert بالنص Success فقط ، عند نجاح تنفيذ جمله ال SQL على قاعده البيانات ، يتم تمرير عبارتين للوظيفه resultHandler ، العباره الاولى هى كائن من نوع SQLtTansaction و العباره التانيه كائن من نوع SQLResultSet يحتوى على الصفوف الناتجه من تنفيذ جمله ال SQL ، حيث يحتوى على الخاصيه rows التى هى بمثابه مصقوفه تمثل صفوف الجدول التى رجعت ، يمكننا استخلاص البيانات منها كما يوضح المثال البسيط التالى :

function resultHandler(tx, result){
    var rows = result.rows;
    var rowsLen = rows.length;
    for(var i = 0; i < rowsLen; i += 1){
        var row = rows.item(i);
        var id = row["id"];
        var name = row["name"];
        alert(id + " : " + name);
    }
};

var db = openDatabase("keepondev", "1.0", "Keepondev database", 65536);
db.transaction(function(tx){
    var sql = "SELECT * FROM goals";
    tx.executeSql(sql, [], resultHandler, errorHandler);
});

فى المثال السابق قمت بإستخلاص جميع البيانات من الجدول goals و استقبلت الناتج داخل الوظيفه resultHandler و قمت بعمل alert للصف لكن يمكنك حقنه فى ال DOM و عمل pagination و عمل LIMIT داخل جمله ال SQL حتى لا تتأثر كفائه التطبيق .

إذا كانت الجمله السابقه INSERT يمكنك معرفه ال id الجديد للصف من خلال result.insertId و عدد الصفوف التى تأثرت من result.rowsModified من داخل resultHandler .

التعامل مع اخطاء تنفيذ ال SQL

يتم إستدعاء الوظيفه errorHandler عند حدوث خطأ فى تنفيذ جمله ال SQL مع تمرير عبارتين لها ، العباره الاولى هى كائن من نوع SQLTransaction ، و العباره التانيه كائن من نوع SQLError يحتوى على معلومات عن الخطأ الذى حدث ، الوظيفه errorHandler اذا قامت بإرجاع true سيتم الغاء جميع العمليات فى ال transaction الحالى ، و اذا قامت ب return false سيتم التغاضى عن الخطأ و لن يتم الغاء ال transaction ، الكائن SQLError يحتوى على خاصيتين ، الخاصيه الاولى message و هى رساله توضح الخطأ الذى حدث يمكنك استخدامها فى ال debugging ، اما الخاصيه التانيه هى code فهى رقم يدل على الخطأ الذى حدث ، انظر الجزء الخاص بأرقام الاخطاء .

function errorHandler(tx, error){
    alert(error.message); // unrecognized token: 3awzo
    alert(error.code); // 1
};
db.transaction(function(tx){
    var sql = "SELECT elly ana 3awzo yabni";
    tx.executeSql(sql, [], resultHandler, errorHandler);
});

أرقام الاخطاء و مدلولاتها

داخل الوظيفه errorHandler ناتج error.code رقم يوضح طبيعه الخطأ ، ال 0 يوضح ان الخطأ غير متعلق بقاعده البيانات ، و 1 يوضح ان الخطأ له علاقه بقاعده البيانات ، 2 يوضح ان الخطأ اصدار قاعده البيانات ليس اصدار القاعده التى طلبتها للمزيد انظر الجزء الخاص بإصدارات قاعده البيانات ، و 3 يوضح ان نتيجه جمله ال SQL كبيره جدا و فى هذه الحاله عليك إستخدام LIMIT و OFFSET حتى تحدد عد الصفوف الناتجه من جمله ال SQL ، و 4 توضح ان الحجم المتاح لقاعده البيانات قد تعدى و ان المستخدم رفض اعطاء المزيد من الحجم عند سؤال المتصفح له ، و 5 يدل على ان الخطأ من نوع lock contention error و عليك اعاده تنفيذ ال transaction ، و 6 يل على constraint error مثلا عند تكرار قيمه فى صفين لعمود معلم ك UNIQUE او عدم اعطاء قيمه لعمود NOT NULL .

التعامل مع اخطاء ال transaction

كما تمكننا من التعامل مع اخطاء تنفيذ جمله ال SQL ، يمكنك ايضا اتخاذ اجراءات عند وقوع خطأ فى تنفيذ ال transaction الذى قد يحتوى على تنفيذ عده جمل SQL ، الوظيفه transaction تقبل ثلاث عبارات ، فى الامثله السابقه كلها رأينا العباره الاولى فقط و هى عباره عن وظيفه يمرر لها الكائن SQLTransaction ، اما العباره الثانيه التى تمرر للوظيفه transaction هى وظيفه يتم استدعائها عند حدوث خطأ فى ال transaction و العباره الثالثه يتم استدعائها عند نجاح ال transaction كما يوضح المثال البسيط التالى :

function txError(error){
    alert(error.message);
    alert(error.code);
};
function txSuccess(){
    alert("transaction succeed");
};

db.transaction(function(tx){ 
    // execute some sql queries here
}, txError, txSuccess);

فى المثال السابق سيتم استدعاء txSuccess اذا نجح ال transaction بدوت اى اخطاء ، و سيتم استدعاء الوظيفه txError مع تمرير كائن SQLError لها ، يمكن استخلاص بيانات منها من خلال error.message او error.code للمزيد انظر أرقام الاخطاء و مدلولاتها .

التعامل مع اصدارات قاعده البيانات

الوظيفه openDatabase التى تقوم بفتح قاعده البيانات تقبل العباره التانيه لها إصدار قاعده البيانات ، اذا قمت بتحديد اصدار خطأ سيتم استدعاء الوظيفه المرتبطه بحدوث الخطأ ، انظر الجزء الخاص بأرقام الاخطاء و مدلولاتها ، و اذا اعطيت اصدار القاعده عباره عن نص فارغ ، سيتم فتح قاعده البيانات بغض النظر عن إصدارها كما يوضح الكود البسيط التالى :

var db = openDatabase("keepondev", "", "Keepondev database", 65536);

يمكنك معرفه اصدار قاعده البيانات بعد ذلك من خلال الخاصيه verison كما يلى

alert(db.version); // 1.0

الكود السابق نتج عنه 1.0 لأنه لا يوجد إصدارات من قاعده بيانات بإسم keepondev إلا الاصدار 1.0 الذى قمنا بإنشاءه و اضافه فيه بيانات من قبل .

يمكنك ترقيه قاعده البيانات إلى اصدار احدث مع الحفاظ على البيانات بداخها كما هى او تغيرها من خلال الوظيفه changeVersion التى تقبل اربع عبارات ، العباره الاولى هى اصدار قاعده البيانات التى تريد تغيرها ، العباره التانيه هى الاصدار الجديد ، العباره التالته هى الوظيفه التى تقوم بتغير الجداول او تغير ال schema و تقبل كائن من نوع SQLTransaction ، العباره الرابعه هى الوظيفه التى يتم استدعائها اذا حدث خطأ اثناء الترقيه مع تمرير الكائن SQLError لها ، اما العباره الخامسه و الاخيره هى الوظيفه التى يتم استدعائها اذا نجحت عمليه الترقيه ، كما يوضح المثال البسيط التالى :

function upgrade(tx){
    var sql = "ALTER TABLE goals RENAME TO targets";
    tx.executeSql(sql, [], resultHandler, errorHandler);
};
function upgradeError(error){
    alert("upgrade error :" + error.message);
};
function upgradeSuccess(){
    alert("upgrade completed");
}
db.changeVersion("1.0", "2.0", upgrade, upgradeError, upgradeSuccess);

فى المثال السابق تم ترقيه قاعده البيانات إلى الاصدار 2.0 مع تغيير إسم الجدول goals إلى targets مع الاحتفاظ بالبيانات كما هى كما توضح الصوره التاليه :

keepondev database version 2.0 and goals table converted to targets

الدعم من المتصفحات

وقت كتابه التدوينه ال local javascript database api مدعم فى safari 3.1+ و iphone os 2.0+ و المتصفحات الاخرى قريبا ان شاء الله .

للمزيد

ADC > using JavaScript Databases

Geolocation

18/07/2009

السلام عليكم و رحمه الله تعالى و بركاته

مقدمه
الكائن geolocation
الحصول على الموقع الحالى للمستخدم
مراقبه تحركات المستخدم
التعامل مع الاخطاء
الدعم من المتصفحات
المزيد

مقدمه

ال Geolocation api هى وسيله من خلالها يتعرف تطبيق الانترنت على موقع المستخدم بعد إذن منه من خلال المتصفح ، يتم تحديد موقع المستخدم عن طريق إرسال عنوان ال ip و مناطق الاتصال اللاسلكيه إلى خدمه تحديد المواقع – فايرفوكس يتعامل مع Google location service – بعد ذلك يحصل المتصفح على موقع تقريبى للمستخدم ، فى بعض الأحيان لا يتعدى الفرق امتار قليله و فى بعض الاحيان الاخرى قد بتجاوز الكيلومترات لذلك لا يمكن الإستعانه به فى إستخدامات حساسه مثل الإغاثه و غيره ، و يتم ذلك فى سريه و بعد اذن المستخدم حيث لا يتم تعقب المستخدم عن طريق هذه الخدمه :) ، لنفرض انك تقوم ببرمجه تطبيق يقوم بإخبار المستخدمين عن الخدمات المجاوره لهم فى موقعهم كالفنادق و المطاعم و محطات الوقود … الخ ، بدلا من ملىء العديد من المدخلات لمعرفه الموقع ، يمكنك استخدام ال geolocatio API مباشره لمعرفه موقع المستخدم ، و يمكن أيضا إستخدامه  فى عمل worm او هجمه من نوع XSS شديده المكر و الدهاء .

الكائن geolocation

الكائن geolocation موجود داخل الكائن navigator ضمن ال browser object model لذلك يمكن الإستعلام عن وجوده من خلال الكودالبسيط التالى :

if(navigator.geolocation){
    /*do something with geolocation api*/
}else{
    /* geolocation api isn't available*/
}

الحصول على الموقع الحالى

بعد التأكد من وجود الكائن geolocation يمكنك الحصول على الموقع الحالى للمستخدم من خلال الوظيفه getCurrentPosition حيث تقبل اكثر من عباره ، العباره الاولى هى وظيفه يتم إستدعائها عند الحصول على الموقع ويتم  تمرير الكائن position لها الذى يحتوى على العديد من البيانات عن موقع المستخدم ، و العباره التانيه يتم إستدعائها عند حدوث خطأ مثل المستخدم رفض مشاركه التطبيق بيانات موقعه ، و العباره الثالثه هى اقصى وقت لإنتظار بيانات الموقع بعدها سيحدث خطأ و سيتم إستدعاء العباره التانيه ، كما يوضح المثال البسيط التالى :

navigator.geolocation.getCurrentPosition( function(position){
    position.timestamp; //time at which position was taken
    position.coords.latitude; //user's current latitude in degrees
    position.coords.longitude; //user's current longitude in degrees
    position.coords.alatitude;
    //user's current latitude in meters, zero if not supported
    position.coords.accuracy; //the accuracy of position information in meters
    position.coords.alatitudeAccuracy;
    //the accuracy of alatitude info, zero if alatitude not supported
    position.coords.heading;
    //the current heading at which the user's moving to in degrees
    position.coords.speed; //seed at which user's moving, meter/sec
} );

يتم تمرير الكائن position للعباره الاولى التى يتم إستداعئها عند تحديد موقع المستخدم ، يحتوى الكائن position على خاصيتين : الاولى هى timestamp وقت تحديد الموقع ، و الخاصيه الثانيه coords عباره عن كائن يحتوى على العديد من خصائص الموقع مثل latitude خط العرص بالدرجه و longitude و alatitude و accuracy و alatitudeAccuracy و accuracy و heading و speed ، يمكنك إستخدام قيمتى latitude و longitude للحصول على خريطه من جوجل بإستخدام google maps api

مراقبه تحركات المستخدم

يمكنك مراقبه تحركات المستخدم عن طريق الوظيفه watchPosition التى يتم إستدعاءها دوريا و ينتج عنها اى تغير فى موقع المستخدم ، تقبل نفس العبارات التى تقبلها الوظيفه getCurrentPosition كما يوضح المثال البسيط التالى :

var watcherID = navigator.geolocation.watchPosition( function(position){
    alert(position.coords.latitude); //user's current position latitude
});

الوظيفه watchPosition ينتج عنها معرف ID يمكنك إستخدامه لإيقاف مراقبه حركات المستخدم عن طريق الوظيفه clearWatch كما يوضح المثال البسيط التالى :

navigator.geolocation.clearWatch(watcherID);

التعامل مع الاخطاء

كما ذكرت كلا من الوظيفتين getCurrentPosition و watchPosition تقبل العباره التانيه وظيفه يتم إستدعائها عند حدوث خطأ ، يتم تمرير كائن من نوع PositionError له خاصيتين الاولى code و هو عباره عن رقم يدل على نوع الخطأ الذى حدث ، و الخاصيه الثانيه message و هى رساله مقرؤه توضح طبيعه الخطأ الذى حدث . الخاصيه code قد تكون 0 وتدل على خدوث خطأ غير معروف UNKNOWN_ERROR ، اما اذا كانت قيمته 1 فإن الخطأ بسبب ان المستخدم لم يعطى إذن لمشاركه بيانات موقعه PERMISSION_ERROR ، اما اذا كانت قيمته 2 فإن الخطأ بسبب عدم امكانيه الحصول موقع المستخدم بسبب خطأ فى خدمه تحديد المواقع ، و اخيرا إذا كانت قيمه الخاصيه code تساوى 2 فإن الوقت المسموح به للحصول على بيانات الموقع قد فات قبل الحصول على البيانات TIMEOUT ، كما يوضح المثال البسيط التالى :

navigator.geolocation.getCurrentPosition(function(position){
    alert(position.coords.latitude); //user's current position latitude
}, function(positionError){
    if(positionError.code == 1){
        alert("give me permission please");
    }
});

الدعم من المتصفحات

الكائن geolocation موجود فى FireFox 3.5 و iphone 3.0 safari و Opera 10

للمزيد :

MDC using geolocation API
W3C geolocation API
Mozilla location aware browsing


تابع

Get every new post delivered to your Inbox.