article

لیست داینامیک پیشنهاد کلمات، مبتنی بر ای جکس، 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 استفاده شده است، خروجی نیز به صورت رشته متنی است و کاراکترهای ### و | جهت کلید تجزیه هر آیتم در نظر گرفته شده است.
sectionدسته بندی: آموزش کاربردی » Ajax
related مطالب بیشتر:
» اعتبار سنجی همزمان فرم با آژاکس (Ajax) و PHP
» نمایش نتایج پایگاه داده MySQL با PHP و ای جکس (Ajax)
» آموزش نحوه آپلود فایل با PHP و ای جکس (Ajax)
» نمایش زنده آمار و اطلاعات با ای جکس (Ajax)
» ارسال اطلاعات فرم با ای جکس (Ajax) و نمایش پیام در حال پردازش
commentنظرات (۲۰ یادداشت برای این مطلب ارسال شده است)
more یادداشت های جدید بر اساس تاریخ ارسال در انتهای یادداشت های موجود نمایش داده می شوند.
نویسنده: mohsen
۱۹:۱۴ ۱۳۹۴/۰۲/۲۵
سلام استاد. خوب هستین؟؟؟
من کد شما رو تو سایتم اضافه کردم ولی به جای اینکه اینطوری نشون بده:
کلمه 1
کلمه 2
کلمه 3
کلمه 4
اینطوری نشون میده:
کلمه 1 کلمه 2 کلمه 3 کلمه 4
علتش از چی میتونه باشه؟؟؟
پاسخ: 
اگر با وجود ورود صحیح استایل CSS کد در صفحه، باز مشکل وجود داشته باشد، خروجی کل صفحه باید بررسی شود، ممکن است تگ های مورد نیاز در خروجی شما درست نباشند یا استایل کد با موارد دیگری در صفحه شما تداخل داشته باشد (به فرض اگر برای div ها حالت display:inline به صورت کلی تعریف شده باشد)، برای مشاهده دقیق و مقایسه خروجی صفحه Add-on فایرفاکس با نام View Source Chart را نصب و امتحان کنید.
نویسنده: مصطفی
۱۱:۳۰ ۱۳۹۴/۰۴/۱۸
با سلام تشکر از وب ساست بسیار مفیدتون.
میخواستم بدونم آیا قابیلت بر رو textarea هم قابل استفاده است؟
پاسخ: 
به لحاظ تئوری محدودیتی از این نظر وجود ندارد و همان روش با انجام تغییراتی اینجا هم عملی است، منتها باید تجربه لازم در کار با JavaScript و CSS را داشته باشید.
نویسنده: chiro
۰۶:۰۴ ۱۳۹۴/۰۹/۰۱
مرسی ممنون از شما
واقن مرسی
مطالب شما همیشه کامل و قابل فهمه
تشکر بابت زحماتتون
نویسنده: بهاره
۱۵:۳۰ ۱۳۹۵/۰۳/۲۴
خیلی ممنون از آموزش مفیدتون
نویسنده: سعید
۱۰:۴۳ ۱۳۹۹/۰۷/۰۱
سلام
دستتون درد نکنه از پروژه شما استفاده کردم
فقط یه مشکل اگه در یک صفحه دو تا لیست کشویی داشته باشیم چطوری هر کدوم مستقل کار کنه ؟
پاسخ: 
در صورتی که بخواهیم همه درخواست ها با پارامترهای حاضر ارسال شوند کافی است هر تگ 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 دارد.
more لطفا پیش از ارسال یادداشت نکات زیر را مد نظر داشته باشید:
- موارد غیرمرتبط با مباحث آموزش ها را در فرم منوی "تماس با ما" مطرح و پاسخ را از طریق ایمیل دریافت کنید.
- به سوالات کلی، مبهم و مشکلاتی که تلاشی برای رفع آن نکرده باشید پاسخ مختصر داده خواهد شد.
- کدها و اسکریپت های طولانی را ترجیحا در یک صفحه وب آنلاین قرار دهید تا امکان تست و بررسی وجود داشته باشد.
- از درج عناوین تبلیغاتی در فیلدها خودداری کنید، در صورتی که یادداشت تبلیغاتی تشخیص داده شود حذف خواهد شد.
- تمام یادداشت ها بررسی و زمانی جهت پاسخگویی در نظر گرفته می شود، لطفا از طرح سوالات متعدد خودداری کنید.





8 × 7
 refresh

آخرین دیدگاه ها
more برای دسترسی سریع به یادداشت مربوطه می توانید از لینک مطلب در کادر زیر استفاده کنید.
form عبدالمالت ریالی
در:
سلام علیک میشه از چند فونت در یک صفحه html استفاده کرد.؟
۱۳۹۹/۰۸/۰۱

form مبینا
در:
سلام من برنامه ای میخواستم که داخل ارایه 5 رنگ قرار گرفته باشه. و با استفاده از حلقه for این یک متنو به اون پنج...
۱۳۹۹/۰۸/۰۱

form mohadeseh
در:
ممنون از راهنماییتون مشکلم حل شد
۱۳۹۹/۰۷/۲۸

form محمد
در:
سلام. یک کد نوشته ام بدین صورت: وقتی صفحه باز شده یک پنجره پیام خالی با یک ok باز شده هر چه ok را...
۱۳۹۹/۰۷/۲۸

form فایز پور جهانبخشی
در:
سلام اگر بخواهیم برنامه ای که داخل متلب نوشتیم تا یک ثانیه اجرا شود و بعد از ثانیه اول در حالت خطا که...
۱۳۹۹/۰۷/۲۸

form mohadeseh
در:
الان کد من که توی تگ <head> گزاشتم میخواستم بدونم ایا امکانش هست که توی تگ link که ایکون رو باهاش اوردم بتونم...
۱۳۹۹/۰۷/۲۷

form mohadeseh
در:
سلام ببخشید لطفا راهنمایی کنید که چجوری title برای favicon در html بزارم؟ جوری که وقتی موس روی icon قرار بگیره متن...
۱۳۹۹/۰۷/۲۷

form ryomaechizen
در:
سلام. اگه حافظه وب پر بشه و مجبورا عکسا کپی باشن چطور باید مشکل بارگزاریشون حل بشه؟
۱۳۹۹/۰۷/۲۶

form رونا
در:
پرونده فرستاده شده نمی‌تواند به wp-content/uploads/2020/10 برود. سلام این ارور برای چی رخ می ده
۱۳۹۹/۰۷/۲۵

form reza
در:
سلام خوبید انشاالله؟ خواستم بدونم این نوار ابزار رو چطور باید اونایی رو دوست دارم بزارم سمت راست وبلاگم. هر چی کد و ......
۱۳۹۹/۰۷/۲۴

form سینا
در:
چگونه میتوانیم با استفاده از HTML فرمول شیمیایی مواد را بنویسیم؟ با عدد اتمی، جرمی و بار اتمی
۱۳۹۹/۰۷/۲۱

form فاطمه
در:
سلام ممنونم... خیلی ساده و روون توضیح دادین.. اونقدر که تشویق شدم محتوای یه فایل تکس رو با ایجکس درون یه div بیارم ولی...
۱۳۹۹/۰۷/۲۱

form امیرحسین
در:
خب متوجه شدم. که باید خط اول عدد فانکشن رو تغییر بدم. بسته به تعداد آرایه یا هر عدد دیگه تغییر بدم جوابمو...
۱۳۹۹/۰۷/۲۱

form امیرحسین
در:
عالی بود. خیلی ممنونم. ولی هر چند کلمه داخل آرایه داشته باشم به همون میزان خروجی گرفته میشه. من اگه 10 کلمه در آرایه داشته...
۱۳۹۹/۰۷/۲۱

form سعادتی
در:
سلام کاش روش برطرف کردن این بهم ریختگی رو هم توضیح میدادید. ممنون
۱۳۹۹/۰۷/۲۰
form امیرحسین
در:
موفق شدم اینو پیدا کنم. ولی میخوام کلمات تکراری داخلشون نباشه. مثال AAA فقط یک بار در اون خط وجود داشته باشه.
۱۳۹۹/۰۷/۲۰
form امیرحسین
در:
سلام. نه محدودیت زمانی وجود نداره.
۱۳۹۹/۰۷/۲۰
form امیرحسین
در:
سلام خسته نباشید. میخوام از این تابع برای بدست آوردن لیست های متفاوت استفاده کنم. مثلا یه آرایه داشته باشم. امیدوارم کمکم...
۱۳۹۹/۰۷/۲۰
form ابوالفضل
در:
سلام وقتتون بخیر من میخوام یه افزونه برای مرورگر کروم طراحی کنم و میخوام یه متنی رو هر سری از سایت دریافت کنه و...
۱۳۹۹/۰۷/۲۰
form mahdi
در:
سلام چطور می تونم از ip خارجی استفاده کنم؟ برای دریافت لانچر میخام. مرسی
۱۳۹۹/۰۷/۱۹
form احسان عباسی
در:
با سلام و تشکر از سایت خوبتون من یه کد تعریف کردم که در بورس ایران سهم مدنظرمو بیاره .. میخواستم ببینم امکانش هست دستوری...
۱۳۹۹/۰۷/۱۷
form شبنم
در:
سلام وقتتون بخیر، ببخشید از کلمه event یا e دقیقا چه زمانی توی فانکشن استفاده میکنیم؟
۱۳۹۹/۰۷/۱۷
form احمد
در:
با عرض سلام مجدد ساختار کلی دستورم به این صورت هست. بعد از حلقه وایل اون دیو کلاس 1 و 2 و 3 میخواهم...
۱۳۹۹/۰۷/۱۶
form احمد
در:
با عرض سلام ببخشید چطوری میتونم یه قسمت از تگ ها رو داخل حلقه وایل رد کنم دوباره تگ های بعدی داخل حلقه قرار بگیرن...
۱۳۹۹/۰۷/۱۶
form ابوالفضل
در:
سلام واقعا من خیلی گشتم تا بتونم این آموزش رو پیدا کنم چون واقعا نمی دونستم چی بنویسم تا یک رتبه بندی برای نتایج جستجو...
۱۳۹۹/۰۷/۱۵
form mahtab
در:
سلام وقتتون بخیر ببخشید میشه بفرمایید چجوری کلیپ رو بزاریم وبلاگ ؟؟ بی زحمت کامل بفرمایین ممنون و متشکر
۱۳۹۹/۰۷/۱۴
form Saeid Azari
در:
سلام ببخشید اگه امکانش هست سوال منو جواب بدید یکم گیج شدم...من یک کد html دارم که باید یک سایت درست کنم و ان را...
۱۳۹۹/۰۷/۱۳
form ابوالفضل
در:
سلام یک سوال دارم چجوری یک متنی که درون تگ td هست و بعد تگ br هست (تگ br درون تگ td است) رو...
۱۳۹۹/۰۷/۱۳
form parnian
در:
با سلام با توجه به این که این مطلب در سال 91 نوشته شده ایا تغیری هم کرده؟ مثلا استفاده و مهم بودن تگ های...
۱۳۹۹/۰۷/۱۳
form fahimeh
در:
سلام من دارم پروژه واسه دانشگاه مینویسم طراحی سایتو کردم برای کار با پایگاه داده دستور insert و delete کار میکنه ولی...
۱۳۹۹/۰۷/۱۲
form امین
در:
با عرض سلام ببخشید یه فرم دارم اخر فرمم یه دکمه دارم میخواستم بدونم چطوری باید بعد از کلیک کردن دکمه به صفحه دیگه انتقال...
۱۳۹۹/۰۷/۱۱
form محسن
در:
سلام من از فرم ساز گرویتی استفاده میکنم آیا امکان استفاده همچین چیزی رو میتونم داخلش داشته باشم آیا کدی داره که در قسمت...
۱۳۹۹/۰۷/۱۱
form مالکی
در:
چرا وبلاگم بالا نمی یاد
۱۳۹۹/۰۷/۰۹
form احمد
در:
با عرض سلام مجدد و خسته نباشید ببخشید نمونه کد رو اگر امکانش هست نگاه کنید که چطوری این متغییری رو که بدست اوردم در...
۱۳۹۹/۰۷/۰۹
form الناز
در:
سلام وقتتون بخیر. چطور میشه برنامه ای رو در php نوشت که کدملی رو تبدیل به شماره دانشجویی کنه اگه برام بنویسید ممنون میشم.
۱۳۹۹/۰۷/۰۹
form محمد
در:
سلام من میخواستم بدونم چه طوری میشه بدون اینکه از کاربر بپرسی که میخواهد از حساب خروج پیدا کند خود سایت بفهمد که کاربر از...
۱۳۹۹/۰۷/۰۹
form احمد
در:
با سلام ببخشید چطوری باید در جکوری از یک متغییر در صفحات دیگه استفاده کنم مثال دو عدد را باهم جمع کردم و ریختم داخل...
۱۳۹۹/۰۷/۰۹
form مهسا
در:
سلام و خسته نباشید مشکلی برای وبلاگ من پیش اومده موقع ورود بهم پیام میده وبلاگ داره بروز رسانی میشه و بعدا وارد وبلاگ شوید...
۱۳۹۹/۰۷/۰۸
form Moshtagh
در:
سلام و خسته نباشید بنده چند روزه که وقتی اطلاعات ورود به وبلاگم رو وارد تیترها و کلیک میکنم با چنین پاسخی مواجه میشم...
۱۳۹۹/۰۷/۰۸
form mahtab
در:
سلام خسته نباشین ببخشید چرا بلاگفا باز نمیکنه ؟؟؟ میرم مدیریت وبلاگ نه تو بروز شده ها وبی هستم نه هم که...
۱۳۹۹/۰۷/۰۷
form جواد
در:
سلام و عرض ادب. سایت من هک شده و یک کد ریدایرکت تو دیتابیس هاستم بارگزاری شده که آخر همه پست ها تو...
۱۳۹۹/۰۷/۰۷
  در انتظار بررسی: ۰
 پاسخگویی به سوالات ممکن است تا 24 ساعت زمان ببرد.