PDA

View Full Version : آموزش: جست وجو در حین تایپ در تکست باکس و نمایش نتیجه با استفاده از jQuery Ajax (Instant search, Autocomple



mbasirati
چهارشنبه 25 شهریور 1394, 12:16 عصر
سلام
توی این پست تصمیم دارم نحوه پیاده سازی autosuggest search رو آموزش بدم. توی اینترنت آموزشایی دیدم که یا خیلی پیچیده توضیح داده بودن یا برای پیاده سازی از ابزارای آماده ای مث ابزاری موجود توی ajax control toolkit استفاده کرده ولی من به شخصه خیلی اعتقادی به استفاده از این ابزارا ندارم. چون هم صفحه رو سنگین میکنن هم کاستمایز کردنشون خیلی سخته.

برای نمونه میتونید سایت دیجیکالا رو ببینید. وقتی توی کادر سرچش شروع به تایپ میکنید زیرش نتیجه سرچ رو نمایش میده. یه همچین چیزی رو قراره پیاده سازی کنیم.
من با استفاده از jQuery ajax این کارو انجام میدم. خیلی راحت و البته سریع و کاربردی.

خب برای شروع اول باید فایل جی کوئری رو به صفحه تون الحاق کنید:

<script src='<%= ResolveUrl("~/js/jquery-2.1.1.min.js") %>'></script>


توی مرحله بعدی تابعی که عمل سرچ رو انجام میده رو مینویسیم. من این تابع رو توی فایل index.aspx.cs می نویسم:

[System.Web.Services.WebMethod]
public static string Search(string keywords)
{
DataTable dt = Product.Search(keywords);
string html = "";
for (int i = 0; i < dt.Rows.Count; i++)
{
html += "<li><a href='/product/" + dt.Rows[i]["ProductId"] + "/" +
dt.Rows[i]["ProductName"].ToString() +"'><img class='img-thumbnail img-polaroid' src='" + dt.Rows[i]["picName"] + "?w=40&h=43&mode=crop'><h5 class='pTitle'>" + dt.Rows[i]["ProductName"] + "</h5></a></li>";
}
return html;
}



اما توضیح کد بالا:
از اونجایی که ما میخوایم از این متد توی جی کوئری استفاده کنیم پس باید اونو از نوع WebMethod در نظر بگیریم.

نکته دیگه اینکه حتما این متد باید public و static باشه. خروجی این متد هم string هست که در واقع برای ما کد html خروجی رو تولید میکنه. یه پارامتر ورودی هم داره که در واقع همون عبارتی هست که کاربر برای جست وجو وارد میکنه و از نوع رشته ست.
اما خط بعدی:

DataTable dt = Product.Search(keywords);



توی این خط من تابع Search که توی کلاس Product هست رو فراخوانی کردم که توی این تابع استاتیک کار جست وجو توی جدولی که مد نظر من هست انجام میشه و نتیجه به صورت DataTable برگردونده میشه. دیگه از توضیح بدنه این تابع صرف نظر میکنم چون طولانی میشه و بحث ما هم روی این مباحث نیست.



اما اصل بحث ما روی ادامه هست. معمولا توی جی کوئری ای جکس کاری که می کنیم اینه که کد اچ تی ام ال رو میسازیم و بعد با استفاده از جی کوئری اون رو توی بخشی که مد نظرمون هست نمایش میدیم. منم توی ادامه این متد همین کارو کردم. شما با توجه به پروژه خودتون کد اچ تی ام ال مورد نظر خودتون رو میسازید. من با توجه به پروژه خودم اون چیزی که قراره نمایش بدم به صورت لیست هست برای همین از li استفاده کردم و لابه لاش هرجا که نیاز داشتم اطلاعات رو از دیتاتیبل خوندم و توی کد اچ تی ام الم قرار دادم.

در نهایت هم این کد اچ تی ام الی که توی متغیر رشته ای html ریختم رو return میکنم.

حالا میریم سراغ استفاده از این خروجی و نمایش اون توی سایت. من از اونجاییکه کادر سرچم توی مسترپیجم هست پس کدهای جی کوئری رو هم همونجا مینویسم. البته میتونید توی یه فایل js قرار بدید و بعد اونو توی صفحه تون الحاق کنید. پس میریم سراغ صفحه مسترپیج.

تکست باکسی که قراره توش تایپ بشه:



<input autocomplete="off" type="text" id="schBox" placeholder="جستجو" />
<div class="instant-search">
<ul id="product-items"></ul>
</div>


دوستان دقت کنید هیچ نیازی نیس از کنترل TextBox استفاده کنید. پس من از input اچ تی ام ال استفاده کردم. در ادامه هم یه تگ div گذاشتم که در حالت عادی نمایش داده نمیشه (display:none) و به محض تایپ توی تکست باکس به نمایش در میاد و نتیجه سرچ توش نشون داده میشه.



اما کدهای جی کوئری:


$(function () {
$('#schBox').keyup(function (event) {
var text = $(this).val();
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "/index.aspx/Search",
data: "{'keywords':'" + text + "'}",
dataType: "json",
success: function (response) {
if (response.d == '') {
$("#product-items").html('<li class="empty">هیچ موردی یافت نشد.</li>');
$('.instant-search').fadeIn(200);
return;
}
$("#product-items").html(response.d);
$('.instant-search').fadeIn(200);
}
});
});
});



در ادامه کدهای بالا رو توضیح میدم:


برای اینکه با شروع تایپ توی تکست باکس عمل جست وجو انجام بشه من از رویداد keyup استفاده کردم. پس تکست باکس رو با id که قبلا براش تعریف کردم انتخاب میکنم و رویداد keyup رو براش فراخوانی میکنم:


$('#schBox').keyup(function (event) {

});


حالا میریم سراغ کدای درون این قسمت:



توی خط اول مقداری که کاربر توی تکست باکس وارد کرده رو داخل یه متغیر به نام text میریزیم تا بعدا راحت تر ازش استفاده کنیم:


var text = $(this).val();


حالا وقتش رسیده که عملیات ای جکسی رو شروع کنیم. کاری که باید بکنیم اینه که مقداری که الان کاربر وارد کرده رو بفرستیم به تابع Search که قبلا توی فایل index.aspx.cs نوشته بودیم. پس میریم سراغ متد $.ajax()


$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "/index.aspx/Search",
data: "{'keywords':'" + text + "'}",
dataType: "json",
success: function (response) {
if (response.d == '') {
$("#product-items").html('<li class="empty">هیچ موردی یافت نشد.</li>');
$('.instant-search').fadeIn(200);
return;
}
$("#product-items").html(response.d);
$('.instant-search').fadeIn(200);
}
});


داخل متد $.ajax() چندتا پارامتر تعریف شده که به صورت name:value هستش. من فقط اونایی رو که مهمه و باهاش کار داریم رو توضیح میدم. بقیش برای ما مهم نیست. بذارید به همین شکلی که هست باشه.



یکی از پارامترایی که مهمه پارامتر url هست که باید آدرس تابع Search رو بهش بدیم. چون این تابع رو توی صفحه index.aspx.cs نوشتیم پس مقدار پارامتر url به شکل زیر میشه:


url: "/index.aspx/Search"


دقت کنید که نباید آدرس صفحه index.aspx.cs رو بدید.



پارامتر بعدی که خیلی هم مهمه پارامتر data هست که کارش اینه که ما آرگومانهای تابعی که نوشتیم رو بهش پاس بدیم. تابع Search یه پارامتر به نام keywords داشت که باید مقدار وارده شده توی تکست باکس رو بهش ارسال کنیم.


data: "{'keywords':'" + text + "'}"



متغیر text که بالاتر تعریف کردیم و مقدار وارد شده توسط کاربر رو توش ذخیره کردیم اینجا استفاده میشه. دقت کنید که کوتیشن و دابل کوتیشن ها رو دقیقا به همین شکل بذارید.

خب یه پارامتر دیگه به نام success داریم که یه تابع براش تعریف میشه. در صورتی که کد ما خطایی نداشته باشه تابع پارامتر success اجرا میشه.

همونطور که گفتم این پارامتر یه تابع میگیره.


success: function (response) {
if (response.d == '') {
$("#product-items").html('<li class="empty">هیچ موردی یافت نشد.</li>');
$('.instant-search').fadeIn(200);
return;
}
$("#product-items").html(response.d);
$('.instant-search').fadeIn(200);
}


این تابع یه پارامتر میگیره که اسمش هرچیزی میتونه باشه. من اسمش رو response گذاشتم. خروجی تابع Search به صورت json هست که یه آبجکت به نام d داره. پس ما هم از طریق همین آبجکت به صورت response.d به خروجی اچ تی ام ال دسترسی پیدا میکنیم.

ابتدا بررسی میکنیم اگه نتیجه جست وجو هیچی نبوده پیام مناسب به کاربر نشون داده بشه. پس توی div که قبلا توی کد اچ تی ام ال تعریف کرده بودیم و به صورت پیش فرض مخفی بود (با سی اس اس) و داخل ul با استفاده از متد html پیام رو به کاربر نشون میدیم و بعد div رو هم با متد fadeout() نمایش میدیم:


if (response.d == '') {
$("#product-items").html('<li class="empty">هیچ موردی یافت نشد.</li>');
$('.instant-search').fadeIn(200);
return;
}

و در ادامه اگر جست وجو نتیجه ای داشته پس خروجی تابع Search رو توی ul با id=product-items نمایش میدیم. و div رو نمایش میدیم.

اما چندتا نکته:


سعی کردم تقریبا تمامی جزئیات رو توضیح بدم تا اگر کسی هم مبتدی هست به دردش بخوره.
تنها کاری که میمونه نحوه نمایش المانها هست که این دیگه با سی اس اس انجام میشه. اینکه اون Div دقیقا زیر تکست باکس نشون داده بشه و ...
هرجایی رو که متوجه نشدید بپرسید، اگه بلد بودم توضیح میدم.
من یه سری کدها رو از این آموزش حذف کردم که خیلی شلوغ نشه. مثلا اون چیزی که من خودم نوشتم این امکانات رو هم داره:

تا زمانی که تعداد کاراکترهای واردشده توسط کاربر کمتر از 3تا باشه عمل سرچ انجام نمیشه.
عملکرد دکمه اینتر رو غیرفعال کردم که اگه کاربر اینتر رو زد صفحه رفرش نشه
اگه کاربر دکمه escape رو زد کادر نتیجه سرچ بسته بشه.
کاربر اگه بیرون از div کلیک کرد، div مخفی بشه.
و اینکه چون منطقی نیس با تایپ هرکاراکتر بلافاصله عمل سرچ انجام بشه، من یه delay خیلی کوتاه در حد یه ثانیه ایجاد کردم که تعداد requestها کمتر بشه.


امیدوارم این آموزش به دردتون خورده باشه.
این اولین پست آموزشی من هست و مطمئنا ایراداتی توش هست. خوشحال میشم ایراداتش رو هم بگید.


موفق باشید.

1000333
چهارشنبه 09 دی 1394, 18:20 عصر
اگر در ویو خود یک مدل دارم شبیه زیر داشتیم
<lable id="1">مقداری که پاس می دهیم </lable>
چگونه می توانیم مدل بالا به صورت json پاس دهیم و چند خروجی دریافت کنیم (مدلهای مورد نظر خود را آپدیت کنیم ) مثل دو مدل زیر

<lable id="2">مقداری می گیریم و آپدیت شود </lable>
<lable id="3">مقداری می گیریم و آپدیت شود </lable>


پارامتر d نام دلخواه است آیا نام d با پارامتر خاصی باید مطابقت داشته باشد

$("#product-items").html(response.d);

sajad_boj71
پنج شنبه 10 دی 1394, 10:41 صبح
سلام
اگه بخوایم جستجوی سایت مثل دیجی کالا دارای بخش های مختلف(که در عکس به رنگ قرمز مشخصه) باشه باید چکار کنیم؟


138062

mbasirati
جمعه 11 دی 1394, 01:51 صبح
هر دو سوال بالا یکیه.
راهی که من به ذهنم میرسه اینه که وب متد یه آرایه رشته ای رو برگردونه و بعد توی کد جی کوئری با اندیس میتونید به سلولهای این آرایه دسترسی داشته باشید:

response.d[0]
response.d[1]
...



پارامتر d نام دلخواه است آیا نام d با پارامتر خاصی باید مطابقت داشته باشد
نه، d دلخواه نیست. asp.net اشیاء json رو در پروپرتی به نام d برمیگردونه.

1000333
جمعه 11 دی 1394, 10:39 صبح
نه، d دلخواه نیست. asp.net اشیاء json رو در پروپرتی به نام d برمیگردونه.

چگونه نشخیص دهیم با چه پروپرتی مقدار برگشت داده می شود

sg.programmer
جمعه 11 دی 1394, 15:08 عصر
سلام تشکر
اگه ممکنه بصورت یک سمپل قرار بدید

mbasirati
جمعه 11 دی 1394, 17:41 عصر
چگونه نشخیص دهیم با چه پروپرتی مقدار برگشت داده می شود

از طریق console مرورگر کروم میتونید. درخواست های ای جکسی توی کنسول مرورگر لاگ میشن. طبق شکل زیر:

138100

138101

138102



سلام تشکر
اگه ممکنه بصورت یک سمپل قرار بدید

فرصت کنم حتما.

1000333
جمعه 11 دی 1394, 18:16 عصر
شما در این خط این مقدار پاس داداید

data: "{'keywords':'" + text + "'}",
و در خط زیر مقادیر خروجی دریافت کردید

$("#product-items").html(response.d);

اگر بخواهیم فیلدهای دلخواه خود را دریافت کنیم چگونه چنین کاری امکان پذیر است مثلا دیتابیس 10 فیلد دارد می خواهیم 5 فیلد نمایش دهیم به چه صورتی می توان چنین کاری انجام داد

mbasirati
جمعه 11 دی 1394, 23:06 عصر
شما در این خط این مقدار پاس داداید

data: "{'keywords':'"+ text + "'}",
و در خط زیر مقادیر خروجی دریافت کردید

$("#product-items").html(response.d);

اگر بخواهیم فیلدهای دلخواه خود را دریافت کنیم چگونه چنین کاری امکان پذیر است مثلا دیتابیس 10 فیلد دارد می خواهیم 5 فیلد نمایش دهیم به چه صورتی می توان چنین کاری انجام داد

ببینید. مقدار خروجی من کد اچ تی ام الی هست که فیلدهای دیتابیس درونش قرار داره. من توی این تابع:

[System.Web.Services.WebMethod]
public static string Search(string keywords)
{
DataTable dt = Product.Search(keywords);
string html = "";
for (int i = 0; i < dt.Rows.Count; i++)
{
html += "<li><a href='/product/" + dt.Rows[i]["ProductId"] + "/" +
dt.Rows[i]["ProductName"].ToString() +"'><img class='img-thumbnail img-polaroid' src='" + dt.Rows[i]["picName"] + "?w=40&h=43&mode=crop'><h5 class='pTitle'>" + dt.Rows[i]["ProductName"] + "</h5></a></li>";
}
return html;
}

یه سلکت به دیتابیسم زدم و مقادیر رو دریافت کردم و بعد توی متغیر html مقادیر فیلدهام رو قرار دادم. مثلا dt.Rows[i]["ProductName"]
این یه فیلد از دیتابیسم هست. یعنی من کوئری به دیتابیس زدم و مقادیر رو دریافت کردم و کد اچ تی ام الم رو هم ساختم و پاس دادم به جی کوئری. و توی کد جی کوئری این مقدار اچ تی ام ال رو توی صفحه نمایش دادم.
کاری که شما میخواید بکنید دقیقا چیه؟

1000333
جمعه 11 دی 1394, 23:23 عصر
می خواهم مقدار یک لیبل پاس بدهم و براساس مقدار پاس شده لیبل یک دستور سلکت بنویسم و خروجی دستور سلکت نمایش دهم (5 فیلد های دیتابیس می خواهم نمایش دهم) هر کدام از فیلدها در یک لیبل مشخصی نمایش دهم فیلد اول در لیبل اول فیلد دوم در لیبل دوم ..........تا فیلد پنجم در لیبل پنجم

mbasirati
شنبه 12 دی 1394, 10:30 صبح
خب شما اول مقدار لیبل خودتون رو باید با جی کوئری بگیرید.
var text=$('#YourLabelID').text()

و بعد با استفاده از وب متدی که مینویسید مقادیری که از دیتابیس واکشی میکنید درون چندتا لیبل بذارید و بعد توی صفحه نمایش بدید:

[System.Web.Services.WebMethod]
public static string Search(string keywords)
{
DataTable dt = Product.Search(keywords);
string html = "";
html = "<label>"+dt.Rows[0]["FieldName"]+"</label"+"<label>"+dt.Rows[0]["AnotherFieldName"]+"</label>"+...;
return html;
}

1000333
شنبه 12 دی 1394, 12:14 عصر
مقدار لیبل با جی کوئری پاس می دهم

vartext=$('#YourLabelID').text()

در پست بالا لیبل را در خود متد درست می کردیم می خواهم مقادیر جدیدی که واکشی می شود در همان لیبل که مقادیری که پاس می دهم جایگزین شود در صفحه اصلی پنج تا لیبل وجود دارد حالا مقادیر جدیدی که واکشی در پنج تا لیبلی که در صفحه وجود دارد نمایش داده شود

1000333
یک شنبه 13 دی 1394, 17:31 عصر
از طریق console مرورگر کروم میتونید. درخواست های ای جکسی توی کنسول مرورگر لاگ میشن. طبق شکل زیر:

138100

138101

138102




فرصت کنم حتما.
هیچ مقداری نمایش نمی دهند:متفکر: