1

This is driving me nuts. I've tried solving this two days already browsing through many webpages.

I'd like to use the jquery-ui autocomplete functionality just exactly as the sample in http://jqueryui.com/resources/demos/autocomplete/remote-jsonp.html, but instead of calling search.php I need to call an ASP file (Microsoft IIS environment). So, I created a local copy of above mentioned HTML file and adjusted only the URL.

$(function() {
  function log(message) {
    $("<div>").text(message).prependTo("#log");
    $("#log").scrollTop(0);
  }

  $("#birds").autocomplete({
    source: function(request, response) {
      $.ajax({
        url: "http://jqueryui.com/resources/demos/autocomplete/search.php",
        dataType: "jsonp",
        data: {
          term: request.term
        },
        success: function(data) {
          response(data);
        }
      });
    },
    minLength: 2,
    select: function(event, ui) {
      log("Selected: " + ui.item.value + " aka " + ui.item.id);
    }
  });
});
.ui-autocomplete-loading {
  background: white url("http://jqueryui.com/resources/demos/autocomplete/images/ui-anim_basic_16x16.gif") right center no-repeat;
}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery UI Autocomplete - Remote JSONP datasource</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="http://jqueryui.com/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<body>

  <div class="ui-widget">
    <label for="birds">Birds: </label>
    <input id="birds">
  </div>

  <div class="ui-widget" style="margin-top:2em; font-family:Arial">
    Result:
    <div id="log" style="height: 200px; width: 300px; overflow: auto;" class="ui-widget-content"></div>
  </div>


</body>
  • Now, when I set URL to search.php of jquery.com (cross-domain, from my web server to the file which is also used by the original HTML) it works a bit slow, but fine
  • When I try it with my local ASP file which is reading data from SQL it doesn't work although when I call the file directly in the browser it returns valid JSON data... I even changed the ASP file to do nothing than only a Response.Write with hard coded JSON data
  • I also tried it with Response.ContentType = "application/json", but this didn't help either
  • Then I loaded an own search.php file which again only does a echo of some hardcoded JSON data to https://softd4u.ch/search.php and tried to call this, but again without success

I found several samples in the Internet where the ASP file would be directly entered as source parameter (often older posts). I guess this might be working, but I think it makes sense to call the file via AJAX.

Trying to debug the jquery-1.12.4.js I at least found out that there is a 'parseerror' returned at one point, but I have no idea why and what I should do differently. At function ajaxHandleResponses( s, jqXHR, responses ) the variable responses was undefined in the case when it worked, but had content iin the case when it didn't work.

I'm sure the files are actually called (checked logs etc.) but they never trigger the success function of the AJAX call.

Does anyone have an idea what I'm missing here?

Source of classic asp file - version 1 (DB connection etc. handled in inc file):

<!-- #INCLUDE FILE="includes/general.inc" -->

<% 
Dim errortextInternal, rs, search, sql
Dim coma

search = Request.QueryString("term")
sql = "SELECT TOP 20 itmId, itmNo, itmDescr1, itmDescr2, itmInact, CASE WHEN itsuSupId1 IS NULL THEN '' ELSE itsuSupId1 END AS SupId1, " & _
        "CASE WHEN itsuSupId2 IS NULL THEN '' ELSE itsuSupId2 END AS SupId2, " & _
        "CASE WHEN itsuSupId3 IS NULL THEN '' ELSE itsuSupId3 END AS SupId3 " & _
        "FROM Items LEFT JOIN ItemsSuppl ON itmId = itsuItmId WHERE "
sql = sql & " (itmNo LIKE '%" & search & "%' OR itmDescr1 LIKE '%" & search & "%' OR itmDescr2 LIKE '%" & search & "%' OR EXISTS " & _
            "(SELECT * FROM ItemsSuppl AS sub WHERE sub.itsuItmId = itmId AND (itsuSupId1 LIKE '%" & search & "%' OR itsuSupId2 LIKE '%" & search & "%' OR itsuSupId3 LIKE '%" & search & "%'))) ORDER BY itmNo, itmDescr1 "

'Response.ContentType = "application/json"
Response.Write("[")
coma = ""

Success = SelectDbRecords(errortextInternal, rs, sql)

If Success Then

    Do While Not rs.EOF
        Response.Write(coma & "{""id"":""" & rs("itmId") & """,""label"":""" & Server.HTMLEncode(rs("itmNo") & " - " & Trim(Trim(rs("itmDescr1")) & " " & Trim(rs("itmDescr2")))) & """,""value"":""" & Server.HTMLEncode(rs("itmNo") & " - " & Trim(Trim(rs("itmDescr1")) & " " & Trim(rs("itmDescr2")))) & """}") 
        If coma = "" Then
            coma = ","
        End If
        rs.MoveNext
    Loop
    rs.ActiveConnection.Close

Else
    Response.Write("Fehler!")
End If 

Response.Write("]")

%>

Source of classic asp file - version 2 (hardcoded response for test purpose; no need to retrieve querystring):

<%@LANGUAGE="VBSCRIPT"%>
<%
Response.Write("[{""id"":""Nycticorax nycticorax"",""label"":""Black-crowned Night Heron"",""value"":""Black-crowned Night Heron""},{""id"":""Ardea purpurea"",""label"":""Purple Heron"",""value"":""Purple Heron""},{""id"":""Tetrao tetrix"",""label"":""Black Grouse"",""value"":""Black Grouse""},{""id"":""Caprimulgus europaeus"",""label"":""European Nightjar"",""value"":""European Nightjar""},{""id"":""Picus viridis"",""label"":""European Green Woodpecker"",""value"":""European Green Woodpecker""},{""id"":""Saxicola rubicola"",""label"":""European Stonechat"",""value"":""European Stonechat""},{""id"":""Luscinia svecica"",""label"":""Bluethroat"",""value"":""Bluethroat""},{""id"":""Ardea cinerea"",""label"":""Grey Heron"",""value"":""Grey Heron""},{""id"":""Corvus cornix"",""label"":""Hooded Crow"",""value"":""Hooded Crow""},{""id"":""Sylvia curruca"",""label"":""Lesser Whitethroat"",""value"":""Lesser Whitethroat""},{""id"":""Pluvialis apricaria"",""label"":""European Golden Plover"",""value"":""European Golden Plover""},{""id"":""Sylvia communis"",""label"":""Common Whitethroat"",""value"":""Common Whitethroat""}]")
%>
  • I suggest scrapping the jquery ui autosuggest for a lighter solution, which you can adjust yourself. I can post an answer containing a sample, if you like. – Malcolm Salvador Mar 17 '17 at 00:20
  • That example uses [JSONP](http://stackoverflow.com/a/3840118/692942), are you sure that is what you want to do? If so, here is how to send the callback - [Using CLASSIC ASP to return data to jsonp call](http://stackoverflow.com/a/33498470/692942). The likelihood is at the moment JQuery is not getting the correct response from your page so will never hit the `success` handler, have you tried including a `fail` handler or even a `done` as a catch-all? Ref [The jqXHR Object](http://api.jquery.com/jQuery.ajax/#jqXHR). – user692942 Mar 17 '17 at 10:54
  • The ASP or PHP element is simply a server side script. The jQuery UI Autocomplete will send a `term` via `GET` to the defined `url`. So it works fine with ASP as well as PHP. Please edit your post and include your ASP code, so that we can get an idea of what the script is doing with the text that is sent to it, and what data it is returning to your AJAX call. – Twisty Mar 17 '17 at 16:48
  • This is a better example of your use case: http://jqueryui.com/autocomplete/#remote – Twisty Mar 17 '17 at 16:50
  • Hello @Malky.Kid, this example with the birds provides exactly the functionality that I was looking for. So, I'm not sure whether a lighter solution would do the job. Nevertheless, I (and maybe others who will read this later) would appreciate if you could post your sample anyway. – Stefan Müller Mar 20 '17 at 20:05
  • Hell @Lankymart, thanks for your post. It's 'jsonp' because that was used in the sample. I wasn't sure about the data types. Tried it with 'json' as well, what didn't work either. The problem was more, that the jquery website didn't provide a sample of search.php which would have helped a lot. Now the link you provided helped as well. That's just great. I only added the callback querystring and brackets in my Response.Write and that's it. Thanks so much. – Stefan Müller Mar 20 '17 at 20:12
  • Hi @Twisty, thank you for your comment. I provided the ASP code meanwhile. As you can see, I already had retrieved the value for term from the query string. – Stefan Müller Mar 20 '17 at 20:14
  • @StefanMüller so an example of the response would be something like: `[{"id":"Nycticorax nycticorax","label":"Black-crowned Night Heron","value":"Black-crowned Night Heron""} ]`So you will want to sent your `url` value to the relative path of the ASP file. Set the `dataType` value to `json` and I would add `console.log(data);` into your success callback before sending the data to `response`. Test it, and report back with what you see in the console. – Twisty Mar 20 '17 at 21:56

2 Answers2

0

If your ASP is called, findbirds.aps, for example, you can use the following JavaScript code in index.html:

  $("#birds").autocomplete({
    source: "findbirds.asp",
    minLength: 2,
    select: function(event, ui) {
      log("Selected: " + ui.item.value + " aka " + ui.item.id);
    }
  });

When 2 or more characters are enters, a GET request will be sent to findbirds.asp on the same server, in the same location as index.html. You can emulate this buy navigating to findbirds.asp?term=white and you can see what the ASP script would send back. In your ASP code, This line:

search = Request.QueryString("term")

should now populate search with "white". Using the example bird data, this should result in:

[{
  "id":"Sylvia curruca",
  "label":"Lesser Whitethroat",
  "value":"Lesser Whitethroat"
},{
  "id":"Sylvia communis",
  "label":"Common Whitethroat",
  "value":"Common Whitethroat"
}]

You can see a similar example here: https://jsfiddle.net/Twisty/99427m8d/

This example does not have access to your ASP code, so it's not exactly the same, but it functions the same way your code should.

Twisty
  • 30,304
  • 2
  • 26
  • 45
  • thank you again for support and examples... one thing that is still not answered for me is, whether it makes any difference if I used ajax or called the asp file directly... your code above is calling it directly, the example in jsfiddle.net is using ajax – Stefan Müller Mar 30 '17 at 06:56
  • It makes little difference. The difference is if you call it direct, it use GET with term. If you use Ajax, you have more control over data sent and how. – Twisty Mar 30 '17 at 06:58
0

So, this finally worked for me.

Form with search field:

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>jQuery UI Autocomplete - Remote JSONP datasource</title>
    <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
    <link rel="stylesheet" href="/resources/demos/style.css">
    <style>
    .ui-autocomplete-loading {
        background: white url("https://jqueryui.com/resources/demos/autocomplete/images/ui-anim_basic_16x16.gif") right center no-repeat;
    }
    </style>
    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    <script>
    $( function() {
        function log( message ) {
            $( "<div>" ).text( message ).prependTo( "#log" );
            $( "#log" ).scrollTop( 0 );
        }
        $( "#article" ).autocomplete({
            source: function( request, response ) {
                $.ajax( {
                    url: "itemSearchAj2.asp",
                    dataType: "json",
                    data: 'term=' + escape(request.term),
                    success: function( data ) {
                        console.log("Data: ", data)
                        response(data);
                    }
                } );
            },
            minLength: 2,
            select: function( event, ui ) {
                log( "Selected: " + ui.item.value + " aka " + ui.item.id );
            }
        } );
    } );
    </script>
</head>
<body>

<div class="ui-widget">
    <label for="article">Article: </label>
    <input id="article">
</div>

<div class="ui-widget" style="margin-top:2em; font-family:Arial">
    Result:
    <div id="log" style="height: 200px; width: 300px; overflow: auto;" class="ui-widget-content"></div>
</div>

</body>
</html>

itemSearchAj2.asp - The classic ASP response when using datatype: 'json'

 <%@LANGUAGE="VBSCRIPT"%>
<%response.Expires=-1%>

<!-- #INCLUDE FILE="includes/global.inc" -->

<% 
Dim errortextInternal, rs, con, search, sql
Dim coma, retVal, label

Set con = Server.CreateObject("ADODB.Connection")
Set rs = Server.CreateObject("ADODB.Recordset")

con.Open odbcname

search = Request.QueryString("term")
sql = "SELECT TOP 20 itmId, itmNo, itmDescr1, itmDescr2, itmInact, CASE WHEN itsuSupId1 IS NULL THEN '' ELSE itsuSupId1 END AS SupId1, " & _
        "CASE WHEN itsuSupId2 IS NULL THEN '' ELSE itsuSupId2 END AS SupId2, " & _
        "CASE WHEN itsuSupId3 IS NULL THEN '' ELSE itsuSupId3 END AS SupId3 " & _
        "FROM Items LEFT JOIN ItemsSuppl ON itmId = itsuItmId WHERE "
sql = sql & " (itmNo LIKE '%" & search & "%' OR itmDescr1 LIKE '%" & search & "%' OR itmDescr2 LIKE '%" & search & "%' OR EXISTS " & _
            "(SELECT * FROM ItemsSuppl AS sub WHERE sub.itsuItmId = itmId AND (itsuSupId1 LIKE '%" & search & "%' OR itsuSupId2 LIKE '%" & search & "%' OR itsuSupId3 LIKE '%" & search & "%'))) ORDER BY itmNo, itmDescr1 "

Response.CharSet = "ISO-8859-1"
Response.Write("[")
coma = ""
retVal = ""

rs.Open sql, con, 3, 3

Do While Not rs.EOF
    label = rs("itmNo") & " - " & Trim(Trim(rs("itmDescr1")) & " " & Trim(rs("itmDescr2")))
    retVal = retVal & coma & "{""id"":""" & rs("itmId") & """,""label"":""" & label & """,""value"":""" & label & """}"
    If coma = "" Then
        coma = ","
    End If
    rs.MoveNext
Loop

Response.Write(retVal)
Response.Write("]")

%>

itemSearchAj2.asp - The same classic ASP response when using datatype: 'jsonp'

<%@LANGUAGE="VBSCRIPT"%>
<%response.Expires=-1%>

<!-- #INCLUDE FILE="includes/global.inc" -->

<% 
Dim errortextInternal, rs, con, search, sql
Dim coma, retVal, label

Set con = Server.CreateObject("ADODB.Connection")
Set rs = Server.CreateObject("ADODB.Recordset")

con.Open odbcname

search = Request.QueryString("term")
sql = "SELECT TOP 20 itmId, itmNo, itmDescr1, itmDescr2, itmInact, CASE WHEN itsuSupId1 IS NULL THEN '' ELSE itsuSupId1 END AS SupId1, " & _
        "CASE WHEN itsuSupId2 IS NULL THEN '' ELSE itsuSupId2 END AS SupId2, " & _
        "CASE WHEN itsuSupId3 IS NULL THEN '' ELSE itsuSupId3 END AS SupId3 " & _
        "FROM Items LEFT JOIN ItemsSuppl ON itmId = itsuItmId WHERE "
sql = sql & " (itmNo LIKE '%" & search & "%' OR itmDescr1 LIKE '%" & search & "%' OR itmDescr2 LIKE '%" & search & "%' OR EXISTS " & _
            "(SELECT * FROM ItemsSuppl AS sub WHERE sub.itsuItmId = itmId AND (itsuSupId1 LIKE '%" & search & "%' OR itsuSupId2 LIKE '%" & search & "%' OR itsuSupId3 LIKE '%" & search & "%'))) ORDER BY itmNo, itmDescr1 "

Response.CharSet = "ISO-8859-1"
Response.ContentType = "application/javascript"
Response.Write(Request.QueryString("callback") & "([")
coma = ""
retVal = ""

rs.Open sql, con, 3, 3

Do While Not rs.EOF
    label = rs("itmNo") & " - " & Trim(Trim(rs("itmDescr1")) & " " & Trim(rs("itmDescr2")))
    retVal = retVal & coma & "{""id"":""" & rs("itmId") & """,""label"":""" & label & """,""value"":""" & label & """}"
    If coma = "" Then
        coma = ","
    End If
    rs.MoveNext
Loop

Response.Write(retVal)
Response.Write("])")

%>

Some of the problems I originally had might also have been, because I didn't specify <%response.Expires=-1%> in the ASP file at the beginning. So, I might have received cached responses because I always used similar search terms.

At the end I was mainly struggeling with character translation problems, since I'm using German expressions including Umlaute etc. It didn't work for me when I tried using a Server.HTMLEncode together with Response.Write in the ASP file. What finally helped in there was the line Response.CharSet = "ISO-8859-1".

The second problem with characters was, when I typed Umlaute in the search field. Obviously data: { term: request.term } seems to automatically encodeURI the term, which then is not properly decoded again by the ASP file. The character 'ä' for instance is encoded as %C3%A4. When I instead use data: 'term=' + escape(request.term) the encoding is correct ('ä' becomes %E4). I know, escape() is deprecated, but again, encodeURI doesn't work for me.