پنجشنبه ۰۴ اردیبهشت ۱۴۰۴

Thursday, April 24, 2025 GMT +3:30

لیست داینامیک پیشنهاد کلمات، مبتنی بر ای جکس، PHP و MySQL

ajax-dynamic-list

ای جکس (Ajax) فناوری است که امروزه در صفحات وب و به ویژه در برنامه ها و سرویس هایی نظیر شبکه های اجتماعی، چت روم ها، دیکشنری های آنلاین، موتورهای جستجو و... به وفور مورد استفاده قرار می گیرد، به فرض اگر در سایتی مانند موتور جستجوی گوگل بخواهیم کلمه ای را وارد کنیم، معمولا بلافاصله پس از تایپ یک عبارت، پرس و جوی ما به طور خودکار به سرور ارسال شده و گوگل متناسب با عبارت درخواستی لیستی از کلمات پرکاربرد را به عنوان پیشنهاد نمایش می دهد، این قابلیت چیزی است که به کمک ای جکس و فریم ورک (Framework) های مبتنی بر آن تحقق می یابد، با توجه به جنبه کاربردی این شیوه در این مطلب قصد داریم نمونه برنامه ای کم حجم و مفید را معرفی کنیم که می توانیم از آن در پروژه های خود به راحتی استفاده نمائیم، این کد ماهیتا برای زبان انگلیسی نوشته شده و جهت سهولت کار با حروف فارسی نیز سازگار شده است.

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


از لیست داینامیک پیشنهاد کلمات می توانیم به فرض در یک دیکشنری آنلاین برای نمایش و پیشنهاد کلمات به صورت یک لیست بازشونده استفاده کنیم، یا زمانی که کاربر در فیلد جستجو به دنبال عبارتی است و بخشی از آن را تایپ می کند با نمایش لیست کلماتی که با عبارت تایپ شده او شروع می شوند تجربه بهتری از کار با برنامه را فراهم کنیم و ایده های جالب و کاربردی دیگر که می توانیم با این شیوه انجام دهیم، این قابلیت با نام های Ajax Auto Complete و Ajax Auto Suggest نیز شناخته می شود.

دانلود نمونه فایل های

لیست داینامیک پیشنهاد کلمات


روشی که در این مطلب در حال بررسی آن هستیم مبتنی بر کدهای آماده نوشته شده توسط برنامه نویسان خارجی است که در دو فایل جاوا اسکریپتی خلاصه می شود، برای استفاده از این کدها ابتدا فایل فشرده زیر را دریافت و سپس با توجه به ادامه مطلب، مراحل را انجام می دهیم تا کدها در برنامه هایمان قابل استفاده باشند.
دانلود نمونه فایل های لیست داینامیک پیشنهاد کلمات
توضیح:
- بسته بالا حاوی چند فایل با نام های مختلف است که هر کدام کاربرد و هدف خاصی دارند و در مجموع اسکریپت را قابل استفاده می کنند، فایل db_tbl.php که برای ساخت نمونه جدول و ورود اطلاعات پیش فرض جهت تست برنامه بر روی لوکال هاست یا سرور است، این فایل باید در فرآیند نصب و راه اندازی اسکریپت یک بار فراخوانی شود، فایل index.html که به عنوان رابط کاربری و صفحه نخست برنامه است و دایرکتوری با نام js با دو فایل جاوا اسکریپتی ajax_list.js و ajax_xmlhttp.js که کدهای اصلی را در خود جای داده اند و جهت کارکرد صحیح برنامه مورد نیاز است، db_list.php نیز فایلی است که درخواست ای جکس به آن ارسال می شود و در پاسخ رشته ای از ردیف ها را خروجی می دهد که در نهایت به شکل لیست در پنجره مرورگر دیده خواهند شد.
- در صورتی که تنظیمات فعلی یونیکد دیتابیس دقیقا مبتنی بر زبان فارسی نباشد این کد نسبت به شناسایی حروف فارسی ممکن است درست عمل نکند، اگر این مشکل پیش آمد دقت کنیم که یونیکد جداول در MySQL باید utf8_persian_ci یا سازگار با حروف فارسی باشد، جهت اطمینان و جلوگیری از بروز اشکالات ناخواسته بهتر است ترجیحا بر روی لوکال هاست با یونیکدهای مختلف برنامه را تست کنیم.
Ajax Dynamic List
پیش نمایش
نکته: این پیش نمایش بدون اتصال به پایگاه داده و صرفا جهت تست شبیه سازی شده و ممکن است نسبت به کد اصلی تفاوت های جزئی داشته باشد.

نحوه استفاده از نمونه فایل های برنامه لیست داینامیک پیشنهاد کلمات


ابتدا از طریق برنامه phpMyAdmin در سیستم مدیریت پایگاه داده MySQL دیتابیسی با نام فرضی db_words و Collation پیش فرض utf8_persian_ci می سازیم (اگر بخواهیم نام دیتابیس را تغییر دهیم باید در تمام فایل های برنامه عناوین db_words را متناسب با نام جدید تنظیم کنیم)، سپس فایل db_tbl.php را جهت ساخت جدول tbl_words و دو ستون id و word از طریق فراخوانی در مرورگر اجرا می کنیم (قبل از فراخوانی فایل و اجرای کدها باید اطلاعات اتصال به پایگاه داده را در متغیر conn تعریف کنیم که به صورت پیش فرض این کار برای لوکال هاست انجام شده است)، آدرس فراخوانی فایل db_tbl.php بستگی به محل قرارگیری آن در فولدر www سرور مجازی دارد، به طور مثال:
localhost/ajax-dynamic-list/db_tbl.php
محتوای فایل db_tbl.php:
<?php
//اتصال به دیتابیس
$conn = new mysqli("localhost", "root", "", "db_words");
if(!$conn) {
    echo "PHP & MySQL Connection: Error! " . $conn->errno . ' - ' . $conn->error;
    exit;
} else {
    echo "PHP & MySQL Connection: Ok!<br>";
    
    //سازگاری با حروف فارسی
    $sql = "SET NAMES 'utf8'";
    $conn->query($sql);
    
    //ساخت جدول و ستون ها
    $sql = "CREATE TABLE tbl_words(
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    word VARCHAR(255))
    ENGINE=MyISAM DEFAULT CHARACTER SET=utf8 COLLATE=utf8_persian_ci"
;
    $conn->query($sql);
    if(!$conn) {
        echo "Creating Table tbl_words: Error! " . $conn->error;
    } else {
        echo "Creating Table tbl_words: OK!<br>";
        
        $string = "کلمه 1, کلمه 2, کلمه 3, کلمه 4, کلمه 5";
        
        $words = explode(',', $string);
        
        for($i = 0; $i < count($words); $i++){
            //ذخیره نمونه اطلاعات در جدول
            $sql = "INSERT INTO tbl_words(word) VALUES('" . trim($words[$i]) . "')";
            $conn->query($sql);
        }
        
        if(!$conn) {
            echo "Inserting Into Table tbl_words: Error! " . $conn->error;
        } else {
            echo "Inserting Into Table tbl_words: OK!";
        }
    }
}
//پایان اتصال
$conn->close();
?>
همان طور که از نمونه کدها مشخص است برای اتصال به دیتابیس از اکستنشن MySQLi به شیوه شی گرا استفاده کرده ایم که در صورت لزوم می توانیم از کدنویسی رویه ای یا اکستنشن PDO نیز استفاده کنیم.
با ایجاد دیتابیس و اجرای دستورات بالا در واقع مرحله نصب و آماده سازی پایگاه داده تکمیل می شود و می توانیم فایل ایندکس (index.html) را اجرا کنیم، برای اجرای این فایل کافی است آدرس دایرکتوری محل نصب را به صورت لوکال یا سرور آنلاین در مرورگر وارد کنیم تا فایل index.html به عنوان فایل پیش فرض فراخوانی شود.
localhost/ajax-dynamic-list/
محتویات فایل index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>وبگو | لیست داینامیک پیشنهاد کلمات مبتنی بر ای جکس</title>
<!-- Webgoo.ir -->
<style type="text/css">
body{
    background-color:#E2EBED;
    font-family:Tahoma, Geneva, sans-serif;
    font-size:12px;        
    direction:rtl;
    line-height:22px;
}
#mainContainer{
    width:660px;
    margin:0 auto;
    text-align:left;
    height:100%;
    background-color:#FFF;
    border-left:3px double #000;
    border-right:3px double #000;
}
#formContent{
    padding:5px;
}    
#ajax_listOfOptions{
    position:absolute;    
    width:175px;
    height:100px;
    overflow:hidden;
    border:1px solid #317082;
    background-color:#FFF;
    text-align:left;
    font-size:12px;
    z-index:100;
}
#ajax_listOfOptions div{
    margin:1px;        
    padding:1px;
    cursor:pointer;
    font-size:12px;
}
#ajax_listOfOptions .optionDiv{    
/* Div for each item in list */
    text-align:right;
}
#ajax_listOfOptions .optionDivSelected{
/* Selected item in the list */
    background-color:#317082;
    color:#FFF;
    text-align:right;
}
#ajax_listOfOptions_iframe{
    background-color:#F00;
    position:absolute;
    z-index:5;
}
form{
    display:inline;
}
</style>
<script type="text/javascript" src="js/ajax_xmlhttp.js"></script>
<script type="text/javascript" src="js/ajax_list.js"></script>
</head>
<body>
<noscript>جاوا اسکریپت در مرورگر شما غیر فعال است!</noscript>
<form id="formContent" action="#">
<label for="word">عبارت 'کلمه' را تایپ کنید: </label>
<input type="text" id="word" name="word" onkeyup="ajax_showOptions(this, 'getword', event)">
<input type="hidden" id="word_hidden" name="word_id">
</form>
<hr>
- برای اجرای این کد باید فایل ها را در سرور مجازی (لوکال هاست، دایرکتوری www) یا سرور آنلاین قرار داده و موارد زیر را انجام دهیم.
<br>
- ابتدا با استفاده از برنامه phpMyAdmin دیتابیسی با نام فرضی db_words و Collation ترجیحی utf8_persian_ci می سازیم.
<br>
- در گام بعدی فایل db_tbl.php را از طریق مرورگر فراخوانی کرده تا جدول tbl_words با کلمات پیش فرض در دیتابیس ایجاد شود.
<br>
- آدرس فراخوانی فایل db_tbl.php بستگی به محل قرارگیری آن در سرور مجازی دارد، به طور مثال localhost/ajax-dynamic-list/db_tbl.php.
</body>
</html>
برای اجرای صحیح برنامه دو فایل ajax_xmlhttp.js و ajax_list.js باید به درستی در صفحه ایمپورت شده باشند، این دو فایل با توجه به تنظیمات ما در دایرکتوری با نام js قرار دارند و لذا نحوه درج آنها در صفحه به شکل زیر خواهد بود.
<script type="text/javascript" src="js/ajax_xmlhttp.js"></script>
<script type="text/javascript" src="js/ajax_list.js"></script>
محتویات فایل ajax_xmlhttp.js:
function sack(file){
    this.xmlhttp = null;
    this.resetData = function(){
        this.method = "POST";
          this.queryStringSeparator = "?";
        this.argumentSeparator = "&";
        this.URLString = "";
        this.encodeURIString = true;
          this.execute = false;
          this.element = null;
        this.elementObj = null;
        this.requestFile = file;
        this.vars = new Object();
        this.responseStatus = new Array(2);
      };

    this.resetFunctions = function(){
          this.onLoading = function(){};
          this.onLoaded = function(){};
          this.onInteractive = function(){};
          this.onCompletion = function(){};
          this.onError = function(){};
        this.onFail = function(){};
    };

    this.reset = function(){
        this.resetFunctions();
        this.resetData();
    };

    this.createAJAX = function(){
        try{
            this.xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
        } catch(e1){
            try{
                this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            } catch(e2){
                this.xmlhttp = null;
            }
        }

        if(!this.xmlhttp){
            if(typeof XMLHttpRequest != "undefined"){
                this.xmlhttp = new XMLHttpRequest();
            } else{
                this.failed = true;
            }
        }
    };

    this.setVar = function(name, value){
        this.vars[name] = Array(value, false);
    };

    this.encVar = function(name, value, returnvars){
        if(true == returnvars){
            return Array(encodeURIComponent(name), encodeURIComponent(value));
        } else{
            this.vars[encodeURIComponent(name)] = Array(encodeURIComponent(value), true);
        }
    }

    this.processURLString = function(string, encode){
        encoded = encodeURIComponent(this.argumentSeparator);
        regexp = new RegExp(this.argumentSeparator + "|" + encoded);
        varArray = string.split(regexp);
        
        for (i = 0; i < varArray.length; i++){
            urlVars = varArray[i].split("=");
            
            if (true == encode){
                this.encVar(urlVars[0], urlVars[1]);
            } else{
                this.setVar(urlVars[0], urlVars[1]);
            }
        }
    }

    this.createURLString = function(urlstring){
        if(this.encodeURIString && this.URLString.length){
            this.processURLString(this.URLString, true);
        }

        if(urlstring){
            if(this.URLString.length){
                this.URLString += this.argumentSeparator + urlstring;
            } else{
                this.URLString = urlstring;
            }
        }

        //prevents caching of URLString
        this.setVar("rndval", new Date().getTime());

        urlstringtemp = new Array();
        for(key in this.vars){
            if (false == this.vars[key][1] && true == this.encodeURIString){
                encoded = this.encVar(key, this.vars[key][0], true);
                delete this.vars[key];
                this.vars[encoded[0]] = Array(encoded[1], true);
                key = encoded[0];
            }

            urlstringtemp[urlstringtemp.length] = key + "=" + this.vars[key][0];
        }
        
        if(urlstring){
            this.URLString += this.argumentSeparator + urlstringtemp.join(this.argumentSeparator);
        } else{
            this.URLString += urlstringtemp.join(this.argumentSeparator);
        }
    }

    this.runResponse = function(){
        eval(this.response);
    }

    this.runAJAX = function(urlstring){
        if(this.failed){
            this.onFail();
        } else{
            this.createURLString(urlstring);
            
            if(this.element){
                this.elementObj = document.getElementById(this.element);
            }
            
            if(this.xmlhttp){
                var self = this;
                
                if(this.method == "GET"){
                    totalurlstring = this.requestFile + this.queryStringSeparator + this.URLString;
                    this.xmlhttp.open(this.method, totalurlstring, true);
                } else{
                    this.xmlhttp.open(this.method, this.requestFile, true);
                    
                    try{
                        this.xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
                    } catch(e){ }
                }

                this.xmlhttp.onreadystatechange = function(){
                    switch(self.xmlhttp.readyState){
                        case 1:
                            self.onLoading();
                            break;
                        case 2:
                            self.onLoaded();
                            break;
                        case 3:
                            self.onInteractive();
                            break;
                        case 4:
                            self.response = self.xmlhttp.responseText;
                            self.responseXML = self.xmlhttp.responseXML;
                            self.responseStatus[0] = self.xmlhttp.status;
                            self.responseStatus[1] = self.xmlhttp.statusText;

                            if(self.execute){
                                self.runResponse();
                            }

                            if(self.elementObj){
                                elemNodeName = self.elementObj.nodeName;
                                elemNodeName.toLowerCase();
                                
                                if (elemNodeName == "input"
                                || elemNodeName == "select"
                                || elemNodeName == "option"
                                || elemNodeName == "textarea") {
                                    self.elementObj.value = self.response;
                                } else{
                                    self.elementObj.innerHTML = self.response;
                                }
                            }
                            
                            if(self.responseStatus[0] == "200") {
                                self.onCompletion();
                            } else{
                                self.onError();
                            }

                            self.URLString = "";
                            break;
                    }
                };

                this.xmlhttp.send(this.URLString);
            }
        }
    };

    this.reset();
    this.createAJAX();
}
این فایل در واقع جهت مدیریت مبتنی بر رویداد ارسال و دریافت اطلاعات در بستر ای جکس است و به نوعی موتور اصلی برنامه محسوب می شود، برای تعیین ساز و کار نحوه نمایش لیست نتایج دریافتی و ایجاد قابلیت های مربوطه نیز فایل ajax_list.js کاربرد دارد.
محتویات فایل ajax_list.js:
var ajaxBox_offsetX = 0;
var ajaxBox_offsetY = 0;
var ajax_list_externalFile = 'db_list.php';    //Path to external file
var minimumLettersBeforeLookup = 1;    //Number of letters entered before a lookup is performed.
var ajax_list_objects = new Array();
var ajax_list_cachedLists = new Array();
var ajax_list_activeInput = false;
var ajax_list_activeItem;
var ajax_list_optionDivFirstItem = false;
var ajax_list_currentLetters = new Array();
var ajax_optionDiv = false;
var ajax_optionDiv_iframe = false;
var ajax_list_MSIE = false;
if(navigator.userAgent.indexOf('MSIE') >= 0 && navigator.userAgent.indexOf('Opera') < 0) ajax_list_MSIE = true;
var currentListIndex = 0;

function ajax_getTopPos(inputObj){
    var returnValue = inputObj.offsetTop;
        
    while((inputObj = inputObj.offsetParent) != null){
        returnValue += inputObj.offsetTop;
    }
    
    return returnValue;
}
    
function ajax_list_cancelEvent(){
    return false;
}

function ajax_getLeftPos(inputObj){
    var returnValue = inputObj.offsetLeft;
    
    while((inputObj = inputObj.offsetParent) != null) returnValue += inputObj.offsetLeft;
    
    return returnValue;
}

function ajax_option_setValue(e,inputObj){
    if(!inputObj) inputObj = this;
    var tmpValue = inputObj.innerHTML;
    if(ajax_list_MSIE) tmpValue = inputObj.innerText; else tmpValue = inputObj.textContent;
    if(!tmpValue) tmpValue = inputObj.innerHTML;
    ajax_list_activeInput.value = tmpValue;
    if(document.getElementById(ajax_list_activeInput.name + '_hidden')) document.getElementById(ajax_list_activeInput.name + '_hidden').value = inputObj.id;
      //var f1 = setTimeout('ajax_list_activeInput.focus()', 1);
      //var f2 = setTimeout('ajax_list_activeInput.value = ajax_list_activeInput.value', 1);
    ajax_options_hide();
}

function ajax_options_hide(){
    if(ajax_optionDiv) ajax_optionDiv.style.display = 'none';
    if(ajax_optionDiv_iframe) ajax_optionDiv_iframe.style.display = 'none';
}

function ajax_options_rollOverActiveItem(item, fromKeyBoard){
    if(ajax_list_activeItem) ajax_list_activeItem.className = 'optionDiv';
    item.className = 'optionDivSelected';
    ajax_list_activeItem = item;

    if(fromKeyBoard){
        if(ajax_list_activeItem.offsetTop>ajax_optionDiv.offsetHeight){
            ajax_optionDiv.scrollTop = ajax_list_activeItem.offsetTop - ajax_optionDiv.offsetHeight + ajax_list_activeItem.offsetHeight + 2;
        }
            
        if(ajax_list_activeItem.offsetTop<ajax_optionDiv.scrollTop){
            ajax_optionDiv.scrollTop = 0;
        }
    }
}

function ajax_option_list_buildList(letters,paramToExternalFile){
    ajax_optionDiv.innerHTML = '';
    ajax_list_activeItem = false;
        
    if(ajax_list_cachedLists[paramToExternalFile][letters.toLowerCase()].length <= 1){
        ajax_options_hide();
        return;
    }

    ajax_list_optionDivFirstItem = false;
    var optionsAdded = false;
    for(var no = 0; no < ajax_list_cachedLists[paramToExternalFile][letters.toLowerCase()].length; no++){
        if(ajax_list_cachedLists[paramToExternalFile][letters.toLowerCase()][no].length == 0) continue;
        optionsAdded = true;
        var div = document.createElement('DIV');
        var items = ajax_list_cachedLists[paramToExternalFile][letters.toLowerCase()][no].split(/###/gi);
            
        if(ajax_list_cachedLists[paramToExternalFile][letters.toLowerCase()].length == 1 && ajax_list_activeInput.value == items[0]){
            ajax_options_hide();
            return;
        }

        div.innerHTML = items[items.length-1];
        div.id = items[0];
        div.className = 'optionDiv';
        div.onmouseover = function(){ajax_options_rollOverActiveItem(this, false)}
        div.onclick = ajax_option_setValue;
            
        if(!ajax_list_optionDivFirstItem) ajax_list_optionDivFirstItem = div;
        ajax_optionDiv.appendChild(div);
    }
        
    if(optionsAdded){
        ajax_optionDiv.style.display = 'block';
        if(ajax_optionDiv_iframe)ajax_optionDiv_iframe.style.display = '';
        ajax_options_rollOverActiveItem(ajax_list_optionDivFirstItem, true);
    }
}

function ajax_option_list_showContent(ajaxIndex, inputObj, paramToExternalFile, whichIndex){
    if(whichIndex!=currentListIndex) return;
    var letters = inputObj.value;
    var content = ajax_list_objects[ajaxIndex].response;
    var elements = content.split('|');
    ajax_list_cachedLists[paramToExternalFile][letters.toLowerCase()] = elements;
    ajax_option_list_buildList(letters,paramToExternalFile);
}

function ajax_option_resize(inputObj){
    ajax_optionDiv.style.top = (ajax_getTopPos(inputObj) + inputObj.offsetHeight + ajaxBox_offsetY) + 'px';
    ajax_optionDiv.style.left = (ajax_getLeftPos(inputObj) + ajaxBox_offsetX) + 'px';
        
    if(ajax_optionDiv_iframe){
        ajax_optionDiv_iframe.style.left = ajax_optionDiv.style.left;
        ajax_optionDiv_iframe.style.top = ajax_optionDiv.style.top;
    }
}

function ajax_showOptions(inputObj, paramToExternalFile, e){
    if(e.keyCode == 13 || e.keyCode == 9) return;
    if(ajax_list_currentLetters[inputObj.name] == inputObj.value) return;
    if(!ajax_list_cachedLists[paramToExternalFile]) ajax_list_cachedLists[paramToExternalFile] = new Array();
    ajax_list_currentLetters[inputObj.name] = inputObj.value;
        
    if(!ajax_optionDiv){
        ajax_optionDiv = document.createElement('DIV');
        ajax_optionDiv.id = 'ajax_listOfOptions';
        document.body.appendChild(ajax_optionDiv);

        if(ajax_list_MSIE){
            ajax_optionDiv_iframe = document.createElement('IFRAME');
            ajax_optionDiv_iframe.border = '0';
            ajax_optionDiv_iframe.style.width = ajax_optionDiv.clientWidth + 'px';
            ajax_optionDiv_iframe.style.height = ajax_optionDiv.clientHeight + 'px';
            ajax_optionDiv_iframe.id = 'ajax_listOfOptions_iframe';

            document.body.appendChild(ajax_optionDiv_iframe);
        }

        var allInputs = document.getElementsByTagName('INPUT');
        for(var no = 0; no < allInputs.length; no++){
            if(!allInputs[no].onkeyup)allInputs[no].onfocus = ajax_options_hide;
        }
            
        var allSelects = document.getElementsByTagName('SELECT');
        for(var no=0; no < allSelects.length; no++){
            allSelects[no].onfocus = ajax_options_hide;
        }

        var oldonkeydown = document.body.onkeydown;
        if(typeof oldonkeydown != 'function'){
            document.body.onkeydown = ajax_option_keyNavigation;
        } else{
            document.body.onkeydown = function(){
                oldonkeydown();
                ajax_option_keyNavigation();
            }
        }
            
        var oldonresize = document.body.onresize;
        if(typeof oldonresize != 'function'){
            document.body.onresize = function(){
                ajax_option_resize(inputObj);
            };
        } else{
            document.body.onresize = function(){
                oldonresize();
                ajax_option_resize(inputObj);
            }
        }
    }

    if(inputObj.value.length < minimumLettersBeforeLookup){
        ajax_options_hide();
        return;
    }

    ajax_optionDiv.style.top = (ajax_getTopPos(inputObj) + inputObj.offsetHeight + ajaxBox_offsetY) + 'px';
    ajax_optionDiv.style.left = (ajax_getLeftPos(inputObj) + ajaxBox_offsetX) + 'px';
    if(ajax_optionDiv_iframe){
        ajax_optionDiv_iframe.style.left = ajax_optionDiv.style.left;
        ajax_optionDiv_iframe.style.top = ajax_optionDiv.style.top;
    }

    ajax_list_activeInput = inputObj;
    ajax_optionDiv.onselectstart =  ajax_list_cancelEvent;
    currentListIndex++;
        
    if(ajax_list_cachedLists[paramToExternalFile][inputObj.value.toLowerCase()]){
        ajax_option_list_buildList(inputObj.value,paramToExternalFile,currentListIndex);
    } else{
        var tmpIndex = currentListIndex / 1;
        ajax_optionDiv.innerHTML = '';
        var ajaxIndex = ajax_list_objects.length;
        ajax_list_objects[ajaxIndex] = new sack();
        var url = ajax_list_externalFile + '?' + paramToExternalFile + '=1&letters=' + inputObj.value.replace(" ", "+");
        ajax_list_objects[ajaxIndex].requestFile = url;    //Specifying which file to get
        ajax_list_objects[ajaxIndex].onCompletion = function(){
            ajax_option_list_showContent(ajaxIndex,inputObj,paramToExternalFile,tmpIndex);
        }; //Specify function that will be executed after file has been found
        ajax_list_objects[ajaxIndex].runAJAX(); //Execute AJAX function
    }
}

function ajax_option_keyNavigation(e){
    if(document.all) e = event;
    if(!ajax_optionDiv) return;
    if(ajax_optionDiv.style.display == 'none') return;
    if(e.keyCode == 38){ //Up arrow
        if(!ajax_list_activeItem)return;
        if(ajax_list_activeItem && !ajax_list_activeItem.previousSibling)return;
        ajax_options_rollOverActiveItem(ajax_list_activeItem.previousSibling,true);
    }

    if(e.keyCode == 40){ //Down arrow
        if(!ajax_list_activeItem){
            ajax_options_rollOverActiveItem(ajax_list_optionDivFirstItem, true);
        } else{
            if(!ajax_list_activeItem.nextSibling) return;
            ajax_options_rollOverActiveItem(ajax_list_activeItem.nextSibling, true);
        }
    }

    if(e.keyCode == 13 || e.keyCode == 9){ //Enter key or tab key
        if(ajax_list_activeItem && ajax_list_activeItem.className == 'optionDivSelected') ajax_option_setValue(false, ajax_list_activeItem);
        if(e.keyCode == 13) return false; else return true;
    }
        
    if(e.keyCode == 27){ //Escape key
        ajax_options_hide();
    }
}

document.documentElement.onclick = autoHideList;

function autoHideList(e){
    if(document.all) e = event;
    if(e.target) source = e.target;
    else if(e.srcElement) source = e.srcElement;
    if(source.nodeType == 3) //defeat Safari bug
    source = source.parentNode;
    if(source.tagName.toLowerCase() != 'input' && source.tagName.toLowerCase() != 'textarea') ajax_options_hide();
}
در نهایت فایل db_list.php خروجی درخواست را به صفحه مرورگر کاربر ارسال می کند:
<?php
//اتصال به دیتابیس
$conn = new mysqli("localhost", "root", "", "db_words");
if(!$conn) {
    echo "PHP & MySQL Connection: Error! " . $conn->errno . ' - ' . $conn->error;
    exit;
} else {
    //سازگاری با حروف فارسی
    $sql = "SET NAMES 'utf8'";
    $conn->query($sql);
    
    $letters = trim(@$_GET['letters']);
    $like = $letters . '%';
    $query = "SELECT id, word FROM tbl_words WHERE word LIKE ?";
    
    $stmt = $conn->prepare($query);
    $stmt->bind_param('s', $like);
    $stmt->execute();

    $result = $stmt->get_result();
    $num_of_rows = $result->num_rows;
    $output = null;
    
    while($row = $result->fetch_assoc()){
        $output .= $row["id"] . "###" . preg_replace("/$letters/si", "<b>$letters</b>", $row["word"], 1) . "|";
    }
    
    $stmt->free_result();
    $stmt->close();
    
    echo $output;
}
//پایان اتصال
$conn->close();
?>
همان طور که مشخص است در این نمونه کد از دستور LIKE در MySQL استفاده شده است، خروجی نیز به صورت رشته متنی است و کاراکترهای ### و | جهت کلید تجزیه هر آیتم در نظر گرفته شده است.
دسته بندی: آموزش کاربردی » Ajax
related مطالب بیشتر:
اعتبارسنجی همزمان فرم با ای جکس (Ajax) و PHP
نمایش داینامیک و صفحه به صفحه مطالب با ای جکس (Ajax)
آموزش نحوه آپلود فایل با PHP و ای جکس (Ajax)
ارسال اطلاعات فرم با ای جکس (Ajax) و نمایش پیام در حال پردازش
ساخت قابلیت امتیازدهی با PHP و Ajax
دیدگاه
more ۲۰ دیدگاه برای این مطلب ارسال شده است.
more چینش دیدگاه ها به ترتیب از جدیدترین به قدیمی ترین است.
سعید
۱۰:۴۳ ۱۳۹۹/۰۷/۰۱
سلام
دستتون درد نکنه از پروژه شما استفاده کردم
فقط یه مشکل اگه در یک صفحه دو تا لیست کشویی داشته باشیم چطوری هر کدوم مستقل کار کنه ؟
در صورتی که بخواهیم همه درخواست ها با پارامترهای حاضر ارسال شوند کافی است هر تگ input را با ID یکتا فراخوانی کنیم:
<input type="text" id="word1" name="word" onkeyup="ajax_showOptions(this, 'getword', event)">
<input type="text" id="word2" name="word" onkeyup="ajax_showOptions(this, 'getword', event)">
اما اگر بخواهیم هر فیلد input پارامتر جداگانه ای برای دریافت پاسخ خاص خود از فایل PHP ارسال کند باید چند تغییر در برنامه اعمال کنیم:
- یک آرگیومنت در هنگام فراخوانی تابع اضافه می کنیم:
ajax_showOptions(this, 'getword', 1, event)
- در فایل ajax_list.js در خط 130 تابع را به شکل نمونه زیر تغییر می دهیم:
function ajax_showOptions(inputObj, paramToExternalFile, type, e){
-در نهایت در خط 207 کدها را به شکل زیر تغییر می هیم تا پارامتر type در URL درخواستی وجود داشته باشد:
		var url = ajax_list_externalFile + '?' + paramToExternalFile + '=1&letters=' + inputObj.value.replace(" ", "+") + '&type=' + type;
در صورتی که این کارها به نحو صحیح انجام شود URL درخواستی باید به شکل نمونه زیر باشد:
http://localhost/ajax-dynamic-list/db_list.php?getword=1&letters=word&type=1
با دریافت پارامتر type از طریق متد GET در فایل PHP می توانیم خروجی مجزایی برای فیلدهای مختلف داشته باشیم که قاعدتا بخش نهایی کار نیاز به برنامه نویسی PHP دارد.
بهاره
۱۵:۳۰ ۱۳۹۵/۰۳/۲۴
خیلی ممنون از آموزش مفیدتون
chiro
۰۶:۰۴ ۱۳۹۴/۰۹/۰۱
مرسی ممنون از شما
واقن مرسی
مطالب شما همیشه کامل و قابل فهمه
تشکر بابت زحماتتون
مصطفی
۱۱:۳۰ ۱۳۹۴/۰۴/۱۸
با سلام تشکر از وب ساست بسیار مفیدتون.
میخواستم بدونم آیا قابیلت بر رو textarea هم قابل استفاده است؟
به لحاظ تئوری محدودیتی از این نظر وجود ندارد و همان روش با انجام تغییراتی اینجا هم عملی است، منتها باید تجربه لازم در کار با JavaScript و CSS را داشته باشید.
mohsen
۱۹:۱۴ ۱۳۹۴/۰۲/۲۵
سلام استاد. خوب هستین؟؟؟
من کد شما رو تو سایتم اضافه کردم ولی به جای اینکه اینطوری نشون بده:
کلمه 1
کلمه 2
کلمه 3
کلمه 4
اینطوری نشون میده:
کلمه 1 کلمه 2 کلمه 3 کلمه 4
علتش از چی میتونه باشه؟؟؟
اگر با وجود ورود صحیح استایل CSS کد در صفحه، باز مشکل وجود داشته باشد، خروجی کل صفحه باید بررسی شود، ممکن است تگ های مورد نیاز در خروجی شما درست نباشند یا استایل کد با موارد دیگری در صفحه شما تداخل داشته باشد (به فرض اگر برای div ها حالت display:inline به صورت کلی تعریف شده باشد)، برای مشاهده دقیق و مقایسه خروجی صفحه Add-on فایرفاکس با نام View Source Chart را نصب و امتحان کنید.
علی
۲۰:۲۵ ۱۳۹۳/۱۰/۱۹
سلام
یک سوال داشتم؟
الان فکر کن در فیلد جستجو یک کلمه نوشتم و برام لیست کرده اطلاعات رو خونده از بانک حالا میخوام تعریف کنم وقتی رو یکی از رکوردها کلیک شد به یک لینک بره و اون لینکم از بانک بخونه
مثلا رو یک رکورد کلیک کرد بره به
www.site.com/search/id
بجای id بیاد ستون ای دی رو از بانک بخونه
لطفا کمک کنید
با تشکر
انجام این کار خیلی سخت نیست! کافی است کمی با PHP کار کرده باشید، در این صورت در فایل ajax-list.php در هنگام چاپ خروجی، می توانید عبارت مورد نظر را در تگ a href چاپ کنید، به فرض:
 while($row = mysql_fetch_array($res)){
echo $row["id"]."###".preg_replace("/$letters/si", "<a href=\"www.site.com/search/$id\"><b>$letters</b></a>", $row["word"], 1)."|";
}
نکته: کد تست نشده!
zahra yavari
۱۰:۱۳ ۱۳۹۳/۰۳/۰۳
سلام
با تشکر از شما
میشه بیشتر راهنمایی کنید؟؟ که از چه دستوراتی استفاده کنم؟
باید با نحوه دریافت و مدیریت مقادیر از طریق متد POST در PHP و همچنین اجرای پرس و جوهای دیتابیس مانند استفاده از SELECT و LIKE آشنا باشید (در کل باید مقدمات کار را قبلا فرا بگیرید).
zahra yavari
۱۴:۳۰ ۱۳۹۳/۰۳/۰۲
سلام
من این کارها را انجام دادم اما مشکلی که داره اینه که بعد که از لیست انتخاب میشه چیزی برام چاپ نمیشه
یعنی میخوام اطلاعات اون صفحه رکوردی که انتخاب شد برام چاپ بشه؟؟
منظورتون از کلمه ی 1 و 2 و... چیه؟؟
و اینکه من خودم دستی دیتابیس را ساختم.. ایا نیازه اون فایل ها ی sql را دوباره وارد کرد؟؟
اینها صرفا نمونه کلماتی فرضی هستند جهت تست اسکریپت، هدف این کد این است که کلماتی را از دیتابیس به عنوان پیشنهاد به کاربر نمایش دهد تا کار او را در انتخاب یک مورد راحت تر کند، سایر موارد مانند چاپ و... بستگی به نحوه استفاده شما از پارامتر ارسالی کاربر دارد و اینکه چگونه با PHP و MySQL کدنویسی و کار کنید (این آموزش صرفا در رابطه با نحوه طراحی لیست پیشنهادی است و برنامه نویسی PHP و پرس و جوهای MySQL را باید در جای خودش فرا گرفته و با این کد ترکیب کنید).
reza
۲۲:۵۵ ۱۳۹۳/۰۲/۲۳
با سلام
شما در جواب بالا گفته اید که:
((به طور مثال وقتی در فیلد جستجوی سایتی عبارت "test" را وارد و بر روی دکمه کلیک کنید....))
ولی منظور ما جمله زیر است:
((به طور مثال وقتی در فیلد جستجوی سایتی عبارت "test" را وارد و بر روی کلمه test کلیک کنید....))
ما به طور کامل بر زبان php و متد get و post آشنایی داریم و مشکل ما از php نیست.
مشکل با کد جاوا اسکریپت است یعنی کدی را می خواهیم که:
{{{با کلیک روی کلمه پیشنهادی بعد از چند ثانیه
فرم به طور خودکار ارسال شود یعنی همان auto submit}}}
فقط نیاز به یک کد جاوا داریم که بعد از کلیک روی کلمه ، فرم به طور اتوماتیک ارسال شود .
(اگر باز هم منظور ما را متوجه نشده اید به سایت ویکی پدیا بروید)
هدف از کدی که می خواهیم صرفا راحت کردن کار کاربر می باشد یعنی می خواهیم کاربر بعد از انتخاب کلمه ،دیگر روی دکمه کلیک نکند یعنی همان انتخاب کلمه کار دکمه را انجام دهد.
با تشکر
برای حالت کلیک می توانید از نمونه زیر استفاده کنید، اما برای کنترل آن با صفحه کلید نیاز به نوشتن توابع پیچیده تری است:
<script type="text/javascript">
function submitForm(form, input, value){
document.getElementById(input).value = value;
document.getElementById(form).submit();
return true;
}
</script>
<form name="myform" id="myform" action="index.php" method="get">
<input type="text" name="search" id="search">
<input type="submit" value="ارسال">
</form>
<a href="javascript:void(0);" onclick="submitForm('myform', 'search', 'test')">test</a>
۱۶:۴۵ ۱۳۹۳/۰۲/۲۳
با سلام
فکر کنم منظور من را درست متوجه نشده باشید.
منظورم این بود که به جای اینکه روی دکمه سرچ کلیک کنیم تا ما را به صفحه ای ببرد ، با کلیک بر روی کلمه پیشنهادی ما را به صفحه ای ببرد.
شاید مثال گوگل مثال خوبی نبود.
مثال درست تر آن مثل سایت ویکی پدیا .
وقتی کلمه را جستجو می کنید یک سری لیست کلمه پیشنهادی برای شما باز می شود و با کلیک کردن روی آن کلمه یا زدن دکمه enter به آن صفحه هدایت میشوید.
توجه کنید که اینجا کد php مطرح نیست.
(((هدف فقط این است که به جای زدن دکمه سرچ و ارسال پارامتر ، بدون زدن دکمه سرچ و با کلیک کردن روی کلمه پیشنهادی پارامتر ارسال شود.)))
امیدوارم منظورم را درست متوجه شده باشید.
با تشکر
منظورتان را متوجه شده ایم و پاسخ قبلی هم در همین رابطه بود، باید لینکی بسازید که در آن پارامترها به صورت متد GET تنظیم شده باشند، به طور مثال وقتی در فیلد جستجوی سایتی عبارت "test" را وارد و بر روی دکمه کلیک کنید، آدرس در مرورگر به شکل نمونه زیر خواهد بود:
yoursite.com/?search=test
حال می توانید با تگ a و href نیز این لینک را ایجاد کنید تا با کلیک کاربر، مرورگر آدرس فوق را به سرور ارسال کنید:
<a href="yoursite.com/?search=test">test</a>
در واقع تفاوتی نمی کند که با فرم و دکمه این کار را انجام دهید یا با لینک ساده، مهم پارامترها است که باید از طریق متد GET ارسال و دریافت شود.
۱۳:۵۶ ۱۳۹۳/۰۲/۲۳
با سلام
چکار باید کرد که پس از جستجو کلمه، وقتی روی اون کلمه کلیک کنیم کاربر به صفحه دلخواه هدایت شود.
مثلا: در گوگل وقتی گوگل کلمه ای رو پیشنهاد می کنه و ما روی اون کلمه کلیک می کنیم (بدون اینکه روی دکمه سرچ کلیک کنیم) گوگل ما را به صفحه مورد نظر هدایت می کنه.
با تشکر
توضیح مطلب ساده نیست! باید برنامه نویسی سمت سرور (مانند PHP) بلد باشید، در این صورت می توانید لینک های جستجوی پیشنهادی را به صورت داینامیک ایجاد کرده و پارامترهای مورد نظر را در آن خروجی دهید، بدین ترتیب پارامترها از طریق متد GET قابل دریافت خواهند بود (این یک بحث تخصصی است و امکان توضیح ساده تر آن وجود ندارد!)
ابوالفضل
۰۰:۲۸ ۱۳۹۲/۱۱/۳۰
سلام
ممنون مشکل حل شد
ابوالفضل
۱۰:۳۵ ۱۳۹۲/۱۱/۲۹
سلام
من این کد را تست کردم همه چیز خوب است اما:
من خودم یک جدول دیگه در دیتابیس دارم که کلمات به صورت فارسی در اون قرار گرفته و یونیکد جدول هم utf8_general_ci هستش متاسفانه با متصل کردن به جدول خودم هیچ کلمه ای پیشنهاد داده نمی شود اما زمانی که به جدول ساخته شده توسط این آموزش متصلش می کنم کد خوب جواب میده جدولی که توسط کدهای شما ایجاد می شود حروف فارسی را کد کرده است اما در جدول ما حروف فارسی خوانا هستند لطف کنید اگر امکانش هست راهنمایی نمایید

نمیشه این کادر پیشنهاد کلمه که الان در زیر باکس نمایش داده می شود در بالای باکس نمایش داده شود؟

ممنون میشم راهنمایی بفرمایید
اگر کلمات به صورت فارسی در دیتابیس ذخیره شده اند، در هنگام اجرای دستورات MySQL و پس از اتصال، پرس و جوی زیر را نیز اجرا کنید:
SET NAMES 'utf8'
احتمالا مشکل حل می شود، در مورد تغییر نحوه نمایش باید با CSS آشنا باشید، متاسفانه امکان تمرکز و توسعه بیش از این بر روی آموزش فعلی نیست.
فاطمه
۱۸:۴۸ ۱۳۹۲/۱۱/۲۶
با سلام
ببخشید من تمام کدهایی را که شما گفته بودید به کار بردم ، پایگاه داده words را ایجاد کردم و دستورات mysql را هم در آن اجرا کردم .
اما لیست کشویی باز می شود اما هیچ عبارتی در آن نیست.
احتمالا یونیکد جداول شما تنظیم نیست، کد تست شده و موردی ندارد، لذا روش شما باید بررسی شود، شاید اشتباهی (هر چند کوچک) کرده باشید.
یاسمن
۱۸:۵۵ ۱۳۹۲/۰۹/۱۷
سلام واقعا ممنون که اینقدر سریع جواب میدید (:
راستش مشکل قبلیم هنوز برطرف نشده ولی یک مشکل جدی تر برام پیش اومده که واقعا راهی براش ندارم ممنون میشم اگه فقط تو این مورد کمکم کنید قول میدم دیگه سوال نکنم (: من یک فرم جست و جوی مقالات دارم که میخوام کاربر وقتی یک عبارتی رو در جعبه متن وارد میکنه مشابه های اون عبارت تو پایگاه داده رو بهش پیشنهاد بده یک لیست کشویی هم دارم که سه گزینه داره و به کاربر امکان جست و جو بر اساس عنوان مقاله ، نام نویسنده و سال انتشار رو میده من میخوام اگه کاربر جست و جو براساس عنوان مقاله رو انتخاب کرد از جدول مقالات عنوان های مشابه رو پیدا کنه و پیشنهاد بده و اگه براساس نام نویسنده رو انتخاب کرد از جدول نویسنده نامهای مشابه رو پیدا کنه و... ولی کدی که من دارم جستجو بر هر اساسی که باشه پیشنهادات رو براساس عنوان مقاله میده ): من خودم فکر می کنم اگه بتونم تو صفحه ajax-list.php به مقدار لیست کشویی یعنی [post[article_$ دسترسی داشته باشم میتونم با گذاشتن شرط مشکل رو حل کنم ولی با session امتحان کردم نشد راه دیگه ای هم برای دسترسی به مقدار لیست کشویی بلد نیستم! ببخشید که اینقدر طولانی شد. کدها هم براتون میذارم:
صفحه search : فقط قسمت فرمش رو گذاشتم که کدها طولانی نشه
<form action="search.php" method="POST" >
<p style="direction:rtl;text-align:center;"> <input type="text" name="textField" id="textField" maxlength="50" size="20" onkeyup="ajax_showOptions(this,'getword',event)" value= <?php echo $_key[2] ?>/></p>
<input type="hidden" id="word_hidden" name="word_id" />

<p style="direction:rtl;text-align:center;">جست و جو بر اساس :</p>
<p style="direction:rtl;text-align:center;"><select name="article">
<option value="name">نام نویسنده</option>
<option value="title" selected>عنوان مقاله</option>
<option value="year">سال انتشار</option>
</select></p>

<p style="direction:rtl;text-align:center;">نوع مقاله :</p>
<p style="direction:rtl;text-align:center;"><select name="articletype">
<option value="'confurance'">کنفرانس</option>
<option value="'jornal'" selected>ژورنال</option>
<option value="'confurance'||'jornal'">هر دو</option>
</select></p>

<p style="direction:rtl;text-align:center;"><input type="submit" name= "submit" value="جست وجو"/></p>
</form>
صفحه ajax-list
<?php
//session_start();
//$article=$_SESSION['article'];
$con = mysql_connect("localhost","root","");
mysql_select_db("scientific_article",$con);
if(isset($_GET['getword']) && isset($_GET['letters'])){
$letters = mysql_real_escape_string($_GET['letters']);
//$letters = preg_replace("/[^a-z0-9 ]/si","",$letters);//for english words!
//if($article=='title'){
$res = mysql_query("select * from `articles` where `title` like '".$letters."%'")
or die(mysql_error());
//echo "1###select id,word from ajax_words where word like '".$letters."%'|";
while($row = mysql_fetch_array($res)){
echo $row["articlecode"]."###".preg_replace("/$letters/si","<b>$letters</b>",$row["title"],1)."|";
}
//}
}
?>
کامنتهای این صفحه برای دسترسی به مقدار لیست کشوییه که جواب نداد ):
مشخص نیست به چه دلیل برای این مورد از نشست استفاده کرده اید؟! دریافت پارامترها از فرم باید از طریق متد POST (یا GET) انجام شود، اما نکته اصلی اینجاست که مورد مد نظر شما یک پروژه کوچک پیچیده است که به نظر حداقل باید برای طراحی تئوری آن یک تا دو ساعت وقت گذاشت! کدهای حاضر با توجه به نوع نیاز شما به صورت مستقیم کاربردی نخواهند داشت و باید از نوع بازنویسی شوند، به طور مثال بخش مورد استفاده در پرس وجو باید به صورت داینامیک و با توجه به انتخاب های کاربر تغییر کند.
more لطفا پیش از ارسال دیدگاه نکات زیر را مد نظر داشته باشید:
- به سوالات کلی، زمانبر، مبهم و مشکلاتی که تلاشی برای رفع آنها نکرده باشید پاسخ مختصر داده شده یا به بخش برنامه نویسی اختصاصی ارجاع داده می شوند.
- کدها و اسکریپت های طولانی را ترجیحا در یک صفحه وب آنلاین یا به صورت حساب موقت و آزمایشی قرار دهید تا امکان بررسی دقیق مشکل و خطایابی میسر باشد.
- تمام دیدگاه های ارسالی خوانده شده و برای هر کاربر مدت زمان لازم جهت پاسخگویی در نظر گرفته می شود، لطفا از طرح سوالات متعدد در بازه زمانی کوتاه خودداری کنید.



 refresh
10 × 10
1 × 6
20 × 20
=