1

我在下面有一段代码,它显示了 2 个下拉菜单,一个用于建筑物,另一个用于房间。当用户从下拉菜单中选择建筑物时,它将使用 ajax 导航到 room.php,在该脚本中它编译查询并输出房间列表,然后显示在房间下拉菜单中页:

         $sql = "SELECT DISTINCT Building FROM Room"; 

 $sqlstmt=$mysqli->prepare($sql);

 $sqlstmt->execute(); 

 $sqlstmt->bind_result($dbBuilding);

 $buildings = array(); // easier if you don't use generic names for data 

 $buildingHTML = "";  
 $buildingHTML .= '<select name="buildings" id="buildingsDrop" onchange="getRooms();">'.PHP_EOL; 
 $buildingHTML .= '<option value="">Please Select</option>'.PHP_EOL;  

 while($sqlstmt->fetch()) 
 { 
     $building = $dbBuilding; 
     $buildingHTML .= "<option value='".$building."'>" . $building . "</option>".PHP_EOL;  
  } 

  $buildingHTML .= '</select>'; 

  $roomHTML = "";  
  $roomHTML .= '<select name="rooms" id="roomsDrop">'.PHP_EOL; 
  $roomHTML .= '<option value="">Please Select</option>'.PHP_EOL;  
  $roomHTML .= '</select>'; 


        ?>

<script type="text/javascript">

        function getRooms() { 
    var building = jQuery("#buildingsDrop").val(); 
    jQuery('#roomsDrop').empty(); 
    jQuery('#roomsDrop').html('<option value="">Please Select</option>'); 
    jQuery.ajax({ 
          type: "post", 
          url:  "room.php", 
          data: { building:building }, 
          success: function(response){ 
              jQuery('#roomsDrop').append(response); 
          } 
        }); 


 }

 </script> 

现在上面的代码适用于除 Internet Explorer 之外的所有浏览器。感谢关于 SO 的一些很好的建议,我被告知要验证脚本,因为 Internet Explorer 在验证代码时非常严格。

无论如何,在我的验证中,我意识到我有这个错误:

文档类型在此处不允许元素“选项”:

指向下面的这一行:

jQuery('#roomsDrop').html('<option value="">Please Select</option>'); 

它声明它需要进入<select>我在上面的代码中技术上尝试做的标签。我的问题是如何修复代码以通过验证但能够执行它的功能,即在从建筑物下拉菜单中选择建筑物后显示房间下拉菜单中的房间列表?

以下是应用程序,请在 Internet Explorer 以及 chrome、firefox、opera 或 safai 中打开应用程序。首先在其中一个非 Internet Explorer 浏览器中向应用程序发送文本,以查看该应用程序的工作原理,然后在 Internet Explorer 中对其进行测试,您可以自己查看问题以及我想要实现的目标。

应用程序(请在 Internet Explorer 和其他主要浏览器中打开)

更新:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>

<title>Room </title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="roomStyle.css">
</head>



<body>

<?php

     // connect to the database
 include('connect.php');

 /* check connection */
 if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
die();
}


$building = isset($_POST['building']) ? $_POST['building'] : ''; 

$sql = "SELECT Room FROM Room WHERE Building = ?"; 

 $sqlstmt=$mysqli->prepare($sql);

 $sqlstmt->bind_param("s",$building);

 $sqlstmt->execute(); 

 $sqlstmt->bind_result($dbRoom);


$roomHTML  = "";  

 while($sqlstmt->fetch()) { 
    $roomHTML .= "<option value='".$dbRoom."'>" . $dbRoom . "</option>".PHP_EOL;  
} 


echo $roomHTML; 

 $sqlstmt->execute(); 


?>
</body>
</html>
4

1 回答 1

2

问题是room.php返回这个:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>

<title>Room </title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="roomStyle.css">
</head>



<body>

<option value='CW2/08'>CW2/08</option>
<option value='CW4/09'>CW4/09</option>
<option value='CW4/10'>CW4/10</option>
<option value='CW5/10'>CW5/10</option>
</body>
</html>

当它应该只返回这个(基于你如何使用响应):

<option value='CW2/08'>CW2/08</option>
<option value='CW4/09'>CW4/09</option>
<option value='CW4/10'>CW4/10</option>
<option value='CW5/10'>CW5/10</option>

虽然我不愿意这么说,但 Internet Explorer 是正确的(在这种情况下)。<option>元素不应该是元素的直接子<body>元素。

这在 Chrome 中工作的原因(例如)是 Chrome 仅将其附加到select#roomDrop

<title>Room </title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="roomStyle.css">
<option value="CW2/08">CW2/08</option>
<option value="CW4/09">CW4/09</option>
<option value="CW4/10">CW4/10</option>
<option value="CW5/10">CW5/10</option>

并且 Chrome 不会在视觉上呈现元素中的<title><meta>或元素。<link><select>

至少有几种方法可以纠正这个问题。

  1. 更改room.php为仅输出<option>元素。
  2. 将您的函数更改getRooms()为仅附加返回的<option>元素。

至于要遵循上述两个修复中的哪一个,这取决于您还room.php用于什么。还有其他解决方案(我敢肯定),但最终这些将归结为修复 PHP 或修复 AJAX 调用。

没有看到 PHP 源代码room.php,我无法帮助第一个。第二个可以这样做:

function getRooms() {
    'use strict';
    var building = jQuery("#buildingsDrop").val(),
        //use jQuery (or plain JavaScript) to build the option as a DOM element
        defaultOption = $('<option />').text('Please Select').val('');
    //append the DOM element, not an HTML string
    jQuery('#roomsDrop').empty().append(defaultOption);
    jQuery.ajax({
        "type": "post",
        "url": "room.php",
        "data": {
            "building": building
        },
        "success": function (response) {
            //filter out the option elements
            var opts = $(response).filter('option');
            //and append only those
            jQuery('#roomsDrop').append(opts);
        },
        "error": function (jqXHR, textStatus, errorThrown) {
            //always good to have an error handler.
            console.log(textStatus);
            console.log(errorThrown);
        }
    });
}

您可能会注意到我使用 jQuery 将初始选项构建为 DOM 元素,而不是构建 HTML 字符串。我这样做是因为:

  1. 这通常被认为是一种更好的做法。
  2. 它消除了通过字符串连接构建元素的需要。
  3. 它使我不必编写格式良好的 HTML(在长字符串上可能很难)。
  4. 做起来并不需要太多的努力。

更新:

由于您已包含 的 PHP 源代码room.php,因此您可以将其修改为仅输出如下<option>元素:

<?php
    // connect to the database
    include('connect.php');
    /* check connection */
    if (mysqli_connect_errno()) {
        printf("Connect failed: %s\n", mysqli_connect_error());
        die();
    }
    $building = isset($_POST['building']) ? $_POST['building'] : '';

    $sql = "SELECT Room FROM Room WHERE Building = ?";
    $sqlstmt=$mysqli->prepare($sql);
    $sqlstmt->bind_param("s",$building);
    $sqlstmt->execute();
    $sqlstmt->bind_result($dbRoom);

    $roomHTML  = "";

    while($sqlstmt->fetch()) {
        $roomHTML .= "<option value='".$dbRoom."'>" . $dbRoom . "</option>".PHP_EOL;
    }
    echo $roomHTML;
    $sqlstmt->execute();
?>

也就是说,简单地消除与元素无关的所有<option>内容。

于 2012-12-25T04:37:13.800 回答