السلام عليكــم ورحمـة الله وبركاتــه ،،
1- مقدمة:
في البداية لاحظت أن الكثيرين من مديري المواقع (Webmasters) يتساءلون باستمرار عن كيفية رصد الزوار المتواجدين للموقع, وكان أقصى حلمهم أن يعرفوا الأي بي ثم بعد ذلك يقومون بفتح مواقع أخرى لمعرفة الدولة/المدينة, ويوجد الكثير من هذه المواقع تقدم هذه الخدمة بشكل مجاني, ويوجد من يقدمها نظير مبالغ خيالية.
على سبيل المثال:
وموقع
2- ما هو الحل الأمثل لرصد إحداثيات الزوار لموقعك دون الاستعانة بمواقع خارجية ؟
قبل أن نتكلم عن هذا الحل أود أن أقول أن هذه الفكرة ليست جديدة بل هي موجودة على المنتديات الأجنبية, ولكن للأسف فإننا كمبرمجين عرب لا نكلف أنفسنا كثيراً بالبحث فيها والموقع الشهير
يعد موقع رائد في مجال البرمجة على مستوى العالم ويجب على أي مبرمج متابعة الجديد فيه باستمرار
المهم
كيف تظهر الخريطة داخل موقعك ؟
يوجد طريقتين شهيرتين للتعامل مع الخرائط:-
1- Google Map:
وذلك عن طريق الاشتراك - مجاني - داخل الجوجل, ثم يقوم الجوجل بتزويدك بـ API الخاص بالخرائط لتضعها في موقعك
حقيقة أنا لم أجربها بعد, لأن الاشتراك لا يمكن تجربته على الأجهزة العادية, بل يجب نشر الموقع على شبكة الانترنت حتى يمكنك أن تجربها
2- Virtual Earth:
وهي منتج مجاني من شركة مكروسوفت يعتمد على تقنية الـ Ajax + Java Script يعني يمكن تطبيقها حتى على المواقع التي تعمل بالـ PHP وليس شرطاً أن تعمل على تقنية الدوت نت
وهذا هو الموقع الرئيسي للـ Virtual Earth
http://www.microsoft.com/virtualearth/
أما هذا فهو موقع الخرائط لكي تشاهدها مباشرة:
http://www.microsoft.com/maps/isdk/ajax/
إذا فتحتم الرابط السابق فستشاهدون العديد من الخرائط 2D, 3D أو حتي صور الستالايت, وستجدون أيضا الـ Source Code الخاص بها وهو جافا سكريبت كما قلنا سابقا.
يمكنك نسخ الكود الموجود من الرابط السابق ووضعه حتى في صفحة HTML عادية جدا, لا تندهش نعم صفحة HTML
جرب هذا الكود واحفظه بصيغة HTML وشاهد الخريطة
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2"></script>
<script type="text/javascript">
var map = null;
function GetMap()
{
map = new VEMap('myMap');
map.LoadMap();
}
</script>
</head>
<body onload="GetMap();">
<div id='myMap' style="position:relative; width:400px; height:400px;"></div>
</body>
</html>كما شاهدتم فإن الكود سهل وبسيط وليس فيه أي صعوبة
3- كيف يمكن استعمال الخريطة السابقة لإظهار إحداثيات الزوار والمستخدمين الحاليين لموقعك ؟
قبل البداية في هذا الشرح أود أن أوكد أن هذا المشروع مصمم من قبل على المواقع الأجنبية ولكن الـ Source Code الخاص به كان صعباً جداً على الكثير من المبرمجين وخاصة المحترفين ومن أراد أن يشاهد الكود الأصلي فهذا هو الرابط:
http://www.codeproject.com/KB/ajax/WhosOnlineAspNet.aspx
هذا الرابط للمحترفين فقط, أما المثال الذي سنوضحه فهو يؤدي نفس العمل تماما ولكن بكود أقل تعقيداً, وقد ظللت أعمل عليه يوم كامل لكي يظل محافظاً على نفس الكفاءة, نسأل الله القبول
تعال نتابع خطوة بخطوة
أ- افتح الدوت نت (2005, 2008, VB, C#) وصمم موقع جديد, ولا توجد مشكلة إذا وضعت ماستر بيج, وضع ملف Global.asax
ب- إذهب إلى ملف Global.asax واكتب الأكواد التالية:
الكود الخاص بفتح السيشن
protected void Session_Start(object sender, EventArgs e)
{
XmlDocument xHostIPLookup;
XmlNamespaceManager xnsManager;
XmlNode xnHostIP;
string sCountryName;
string sCityName;
string sCoordinates;
Hashtable hUserInfo;
hUserInfo = new Hashtable();
Session.Timeout = 10;
if (!Session.IsNewSession)
{
return;
}
if (Application["CurrentUsers"] == null)
{
Application["CurrentUsers"] = new ArrayList();
}
for (int i = 0; i < ((ArrayList)(Application["CurrentUsers"])).Count; i++)
{
if (((Hashtable)(((ArrayList)(Application["CurrentUsers"]))))["SessionID"].ToString() == Session.SessionID)
{
return;
}
}
try
{
Application.Lock();
xHostIPLookup = new XmlDocument();
xHostIPLookup.Load("http://api.hostip.info/?ip=" + Request.UserHostAddress);
xnsManager = new XmlNamespaceManager(xHostIPLookup.NameTable);
xnsManager.AddNamespace("gml", "http://www.opengis.net/gml");
xnHostIP = xHostIPLookup.DocumentElement.SelectSingleNode("gml:featureMember", xnsManager).FirstChild;
if (xnHostIP != null)
{
sCityName = xnHostIP.ChildNodes[0].InnerText;
sCountryName = xnHostIP.ChildNodes[1].InnerText;
if (xnHostIP.ChildNodes.Count > 3 && xnHostIP.ChildNodes[4] != null)
{
sCoordinates = xnHostIP.ChildNodes[4].InnerText;
//sCoordinates = "46,26"; إحداثيات مدينة الرياض للتجربة
if (sCoordinates != string.Empty)
{
hUserInfo["SessionID"] = Session.SessionID;
hUserInfo["IPAddress"] = Request.UserHostAddress;
hUserInfo["Location"] = sCityName + " " + sCountryName;
hUserInfo["Coordinates"] = sCoordinates;
((ArrayList)(Application["CurrentUsers"])).Add(hUserInfo);
}
}
// الإحداثيات مجهولة
else
{
hUserInfo["SessionID"] = Session.SessionID;
hUserInfo["IPAddress"] = Request.UserHostAddress;
hUserInfo["Location"] = sCityName + " " + sCountryName + " Unknown Coordinates";
hUserInfo["Coordinates"] = "0,0";
((ArrayList)(Application["CurrentUsers"])).Add(hUserInfo);
}
}
}
catch (Exception Exc)
{
//service is unavialable, ignore error.
}
finally
{
Application.UnLock();
}
}أما هذا فهو الكود الخاص بغلق السيشن
protected void Session_End(object sender, EventArgs e)
{
try
{
Application.Lock();
if (Application["CurrentUsers"] != null)
{
for (int i = 0; i < ((ArrayList)(Application["CurrentUsers"])).Count; i++)
{
if (((Hashtable)(((ArrayList)(Application["CurrentUsers"]))))["SessionID"].ToString() == Session.SessionID)
{
((ArrayList)(Application["CurrentUsers"])).RemoveAt(i);
}
}
}
}
catch (Exception Exc)
{
// move on
}
finally
{
Application.UnLock();
}
}أرجو ألا تنزعجوا من تعقيد الكود, لو رأيتم الكود الأصلي فستنسون هذا الموضوع من أصله :D
جـ- اذهب إلى صفحة الـ Default.aspx وضع هذا الكود داخلها
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WhoIsOnline.aspx.cs" Inherits="WhoIsOnline.WhoIsOnline" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Who is Online</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2"></script>
<script type="text/javascript">
var map = null;
function GetMap()
{
map = new VEMap('myMap');
map.LoadMap(null,1);
}
</script>
<style type="text/css">
.ero
{
z-index: 100002 !important;
}
.ero-progressAnimation
{
z-index: 100002 !important;
}
.VE_Message
{
z-index: 100002 !important;
}
</style>
</head>
<body onload="GetMap();ShowPins();">
<form id="frmWhoIsOnline" runat="server">
<asp:Literal ID="ltrlUsersOnLine" runat="server"></asp:Literal>
<center>
<div id="myMap" style="position: relative; top: 0px; left: 0px; width: 800px; height: 800px;">
</div>
</center>
</form>
</body>
</html>انتبه جيدا لأهمية هذا السطر
<body onload="GetMap();ShowPins();">
لأنه هو الذي يعرض الخريطة ويظهر الإحداثيات عليها
د- اذهب إلى الحدث الخاص بـ Page_Load الخاص بصفحة Default وضع هذا الكود:
protected void Page_Load(object sender, EventArgs e)
{
StringBuilder sb;
// عدد المتواجدين حاليا
ltrlUsersOnLine.Text = ((ArrayList)(Application["CurrentUsers"])).Count.ToString();
// ضبط الدالة الخاصة بإحداثيات المستخدم
sb = new StringBuilder();
sb.AppendLine("function ShowPins()");
sb.AppendLine("{");
for (int i = 0; i < ((ArrayList)(Application["CurrentUsers"])).Count; i++)
{
sb.AppendLine("var pinID = " + (i + 1).ToString() + ";");
sb.AppendLine("var pin = new VEPushpin(");
sb.AppendLine("pinID, ");
// انتبه جيداً
// هنا يتم عكس أو قلب الإحداثيات
// Coordinates(Y, X)
sb.AppendLine("new VELatLong(" +
((Hashtable)(((ArrayList)(Application["CurrentUsers"]))))["Coordinates"].ToString().Split(new char[] { ',' })[1] +
"," +
((Hashtable)(((ArrayList)(Application["CurrentUsers"]))))["Coordinates"].ToString().Split(new char[] { ',' })[0] + "), ");
sb.AppendLine("null, ");
sb.AppendLine("'" + ((Hashtable)(((ArrayList)(Application["CurrentUsers"]))))["IPAddress"].ToString() + "', ");
sb.AppendLine("'" +
((Hashtable)(((ArrayList)(Application["CurrentUsers"]))))["Location"].ToString().Replace("'", "’") + "','pinEvent', 'Century 16'");
sb.AppendLine(");");
sb.AppendLine("");
sb.AppendLine("map.AddPushpin(pin);");
}
sb.AppendLine("}");
// هذا مثال لنتيجة الدالة الموجودة بالأعلى
//function ShowPins()
//{
// var pinID = 1;
// var pin = new VEPushpin(
// pinID,
// new VELatLong(0,0),
// null,
// '127.0.0.1',
// '(Private Address) (Private Address) Unknown Coordinates','pinEvent', 'Century 16'
// );
// map.AddPushpin(pin);
//}
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "MapScript", sb.ToString(), true);
}خلاص لقد انتهي العمل ولكنك لن تستطيع تجريب هذا المشروع بشكل فعال مثلما لو وضعته على الانترنت, هذه الصورة توضح شكل الناتج النهائي:

إذا أردت أن تجربه لقد وضعته على موقعي:
4- الخاتمة:
الموضوع لايزال في البداية وهناك استفسارات سأجيب عنها لاحقاً إن شاء الله, المشروع مرفق
نسأل الله القبول