これは、さまざまなレベルでOpenCartにカテゴリメニューを表示するために使用したコードです。動作しますが、クリックするたびにどんどんXHR finished loading: POST
およびXHR finished loading: GET
sは、時々クリックしてページを停止します。
<script type="text/javascript">
_url = '';
$(document).ready(function(){
$('#mnav a').on('click', function() {
var cat = $(this).attr('id');
_url = '&category_id=' + cat;
$.post('index.php?route=test/category/child' + _url,
function(data) {
if(data.length>10){
$('#mnav #sub').remove();
$(data).insertAfter($('#mnav #' + cat));
}
});
});
});
$.ajaxPrefilter(function( options, original_Options, jqXHR ) {
options.async = true;
});
</script>
HTMLコード:
<div id="mnav" class="list-group">
<?php foreach ($categories as $category) { ?>
<a id="<?php echo $category['category_id']; ?>" class="list-group-item active"><?php echo $category['name']; ?></a>
<?php } ?>
</div>
コントローラーコード:
<?php
class ControllerTestCategory extends Controller {
public function index() {
if (isset($this->request->get['path'])) {
$parts = explode('_', (string)$this->request->get['path']);
} else {
$parts = array();
}
$data['category_id'] = 0;
if (isset($parts[0])) {
$data['category_id'] = $parts[0];
} else {
$data['category_id'] = 0;
}
if (isset($parts[1])) {
$data['child_id'] = $parts[1];
} else {
$data['child_id'] = 0;
}
$this->load->model('catalog/cat');
$data['categories'] = array();
$categories = $this->model_catalog_cat->getCategories(0);
foreach ($categories as $category) {
$children_data = array();
$filter_data = array(
'filter_category_id' => $category['category_id'],
'filter_sub_category' => true
);
$data['categories'][] = array(
'category_id' => $category['category_id'],
'name' => $category['name'],
'children' => $category['children'],
'products' => $category['products'],
'href' => $this->url->link('product/category', 'path=' . $category['category_id'])
);
}
$this->response->setOutput($this->load->view('test/category', $data));
}
public function child() {
if (isset($this->request->get['category_id'])) {
$this->load->model('catalog/cat');
$data['categories'] = array();
$categories = $this->model_catalog_cat->getCategories($this->request->get['category_id']);
$data['x'] = '<div id="sub">';
foreach ($categories as $category) {
$data['x'] .= '<li>' . $category['name'] . '</li>';
}
$data['x'] .= '</div>';
} else {
$data['x'] = 'NA';
}
$this->response->setOutput($this->load->view('test/category', $data));
}
}
SQLコード:
public function getCategories($parent_id = 0) {
$sql = "SELECT c.category_id, c.parent_id, cd.name,
(SELECT COUNT(DISTINCT ch.category_id) from category ch where ch.parent_id = c.category_id and cd.language_id = '" . (int)$this->config->get('config_language_id') . "') as children";
$sql .= " , (SELECT COUNT(DISTINCT p.product_id)
FROM product p
LEFT JOIN product_description pd ON (p.product_id = pd.product_id)
LEFT JOIN product_to_category p2c ON (p2c.product_id = p.product_id)
LEFT JOIN category_path cp ON (cp.category_id = p2c.category_id)
WHERE
pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND
p.status = '1' AND
p.date_available <= NOW()) AS items";
$sql .= " FROM category c LEFT JOIN category_description cd ON (c.category_id = cd.category_id) WHERE c.parent_id = '" . (int)$parent_id . "' AND cd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND c.status = '1' ORDER BY c.sort_order, LCASE(cd.name)";
$query = $this->db->query($sql);
return $query->rows;
}
必要なすべてのJavaScript、jQuery、JSONコードを提供していただければ幸いです。
投稿リクエストの結果をJavaScript配列に保存して、再利用することができます。以下を参照してください:
var cachedObj = [];
$(document).ready(function(){
$('#mnav a').on('click', function() {
var cat = $(this).attr('id');
_url = '&category_id=' + cat;
getData(cat, _url); //<-- Get data from ajax or cache
});
});
//This function replaces the $.post call (just for example)
function dummyPost(id, url){
//url should be used to make the post call
var data = "<span class='sub'>Test " + id + "</span>";
return data;
}
function getData(id, url){
//Try to get data from cache
var data;
if(cachedObj[url]) {
data = cachedObj[url];
console.log("Data retrived from cache");
}
else {
data = dummyPost(id, url);
cachedObj[url] = data;
console.log("Data retrived from post");
}
$('#mnav .sub').remove();
//$(data).insertAfter($('#mnav #' + id));
$('#mnav #' + id).append($(data));
}
.sub{
color: red;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="mnav" class="list-group">
<a id="1" class="list-group-item active">One</a>
<a id="2" class="list-group-item active">Two</a>
<a id="3" class="list-group-item active">Three</a>
</div>
投稿リクエストを行うために変更する必要があるdummyPost
関数を作成しました。
私の例のログを見ると、リンクをクリックしたときに「投稿」を含むサブメニューが取得され、次回はキャッシュされた配列cachedObj
からデータが取得されることがわかります。
お役に立てば幸いです。さようなら。
pdate:コードに適用すると、次のようになります。
<script type="text/javascript">
var cachedObj = []; //<-- Add an array to cache submenus
//Add a function to retrieves data from cache or REST
function getData(url){
//Try to get data from cache
if(cachedObj[url]) {
console.log("Data retrived from cache");
}
else {
$.ajax({
type: 'GET',
url: 'index.php?route=test%2Fcategory%2Fchild' + url,
success: function(data) {
cachedObj[url] = data;
console.log("Data retrived from post");
}),
async:false
});
}
return cachedObj[url];
}
$(document).ready(function(){
$('#mnav a').on('click', function() {
var cat = $(this).attr('id');
var url = '&category_id=' + cat;
var data = getData(url); //<-- Call the new function to get data
if(data.length>10){
$('#mnav #sub').remove();
$(data).insertAfter($('#mnav #' + cat));
}
});
});
</script>
テストできないので、エラーが含まれている可能性があります。
問題は、アンカータグのデフォルトアクションを妨げていない可能性があります。 event.preventDefault
を追加してみてください。このようにして、ブラウザはPOST
リクエストではなくGET
リクエストを発行します。
さらに、ajaxを介して新しい#mnav a
要素を追加する場合は、イベントを要素ではなくドキュメントにバインドすることをお勧めします。
$(document).ready( function() {
$(document).on('click', '#mnav a', function( event ) {
event.preventDefault();
// some code
});
});
私は私のajax駆動プロジェクトでこの問題に直面しました。私の解決策があなたのお役に立てば幸いです。これにより、それ以上の呼び出しが作成されない場合があります。
// DOM ready
$(function() {
$(document).off('click', '#mnav a').on('click', '#mnav a', function(e){
e.preventDefault();
// your stuff here
});
});
コードを書く前に、クライアントとサーバーがどのように通信するかについて戦略を立てる必要があるようです。
あなたの問題についての私の理解は、「メニューはクリックするたびにajaxリクエストを生成し、それを望まない」です。
しかし、これがコードの作成方法です。jQueryによって設定されたメニューのonclickハンドラーには、$.post()
呼び出しが含まれています。
これを行うもう1つの方法は、メニューを作成するために必要なすべてのデータをクライアントに事前に送信することです。次に、メニューをクリックするたびに、ajaxリクエストを送信するのではなく、すでにメモリにあるデータから描画します。
これを行う方法はいくつか考えられます。 選択する戦略は、システムの快適性や制御、およびページ速度の優先度によって異なります。
<script><?php echo 'var menuData = '.json_encode($my_data).'; ?></script>
のようなデータをすぐに利用できるようにします。これが最速のオプションです。手順は次のとおりです。
javascriptでドロップダウンを作成します。
function myFunction(){
var port_button = document.getElementById("port").value;
if(port_button == 0){
var newhref;
var newhrefid;
var name = ["jquery ajax", "dropdown menu", "db"];
var links = ["api.jquery.com/jquery.ajax/", "www.w3schools.com/howto/howto_js_dropdown.asp", "www.w3schools.com/php/php_ajax_database.asp"];
var div=document.getElementById("myDropdown");
for(var i = 0; i<3; i++){
newhref= document.createElement("a");
newhref.href="http://"+links[i];
newhref.innerHTML= name[i];
newhrefid = "idhr_"+i;
newhref.setAttribute('id', newhrefid );
div.appendChild(newhref);
}
document.getElementById("myDropdown").classList.toggle("show");
document.getElementById("port").value = "2";
}
else if(port_button == 1){
document.getElementById("myDropdown").classList.toggle("show");
document.getElementById("port").value = "2";
}
else{
document.getElementById("myDropdown").classList.toggle("hide");
document.getElementById("port").value = "1";
}
}
function filterFunction() {
var input, filter, ul, li, a, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
div = document.getElementById("myDropdown");
a = div.getElementsByTagName("a");
for (i = 0; i < a.length; i++) {
if (a[i].innerHTML.toUpperCase().indexOf(filter) > -1) {
a[i].style.display = "";
} else {
a[i].style.display = "none";
}
}
}
.dropbtn {
background-color: #4CAF50;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
.dropbtn:hover, .dropbtn:focus {
background-color: #3e8e41;
}
#myInput {
border-box: box-sizing;
background-image: url('searchicon.png');
background-position: 14px 12px;
background-repeat: no-repeat;
font-size: 16px;
padding: 14px 20px 12px 45px;
border: none;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f6f6f6;
min-width: 230px;
overflow: auto;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown a:hover {background-color: #ddd}
.show {display:block;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="dropdown">
<button onclick="myFunction()" class="dropbtn">Dropdown</button>
<div id="myDropdown" class="dropdown-content">
<input type="text" placeholder="Search.." id="myInput" onkeyup="filterFunction()">
</div>
</div>
<input type="hidden" id = "port" value = "0">
「入力」、「p」、「a」などの要素のドロップダウンを作成できます。
特定のIDを選択する場合は、このHTMLをコードに追加します。
<form>
<select id = "name_of_user" name="users" onchange="showUser(this.value)">
<option value="">Select a person:</option>
<option value="1">Peter Griffin</option>
<option value="2">Lois Griffin</option>
<option value="3">Joseph Swanson</option>
<option value="4">Glenn Quagmire</option>
</select>
</form>
データベースデータを選択してこのコードを結合するには:
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT id, name FROM user";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
// output data of each row
$option = "";
while($row = $result->fetch_assoc()) {
$option .= '<option value = "'.$row["id"].'">'.ech$row["name"].'</option>';
}
}
$conn->close();
?>
<form>
<select id = "name_of_user" name="users" onchange="showUser(this.value)">
<?php echo $option; ?>
</select>
</form>
ここで、AJAX=を作成してドロップメニューコードに結合する必要があります。
function myFunction(){
var port_button = document.getElementById("port").value;
if(port_button == 0){
var newhref;
var newhrefid;
var div=document.getElementById("myDropdown");
var val_1 = document.getElementById("name_of_user");//If you want to do a where select.
$.ajax({
url: 'test.php',
type: 'POST',
datatype: 'Json',
data: {'q': val_1},
success: function (response) {
var newhref;
var newhrefid;
var div=document.getElementById("myDropdown");
for(var i = 0; i<response.nunber_of_rows; i++){
newhref= document.createElement("a");
newhref.href= response.tabel[i];
newhref.innerHTML= response.tabel[i];
newhrefid = "idhr_"+i;
newhref.setAttribute('id', newhrefid );
div.appendChild(newhref);
}
}
});
document.getElementById("myDropdown").classList.toggle("show");
else if(port_button == 1){
document.getElementById("myDropdown").classList.toggle("show");
document.getElementById("port").value = "2";
}
else{
document.getElementById("myDropdown").classList.toggle("hide");
document.getElementById("port").value = "1";
}
}
データベースに接続するには、phpが必要です。
<?php
$q = intval($_POST['q']);
$error_state = "";
$con = mysqli_connect('localhost','peter','abc123','my_db');
if (!$con) {
die('Could not connect: ' . mysqli_error($con));
}
mysqli_select_db($con,"ajax_demo");
$sql="SELECT links FROM user WHERE id = '".$q."'";
$result = mysqli_query($con,$sql);
$i = 0;
while($row = mysqli_fetch_array($result)) {
$tabel[$i] = array($row['link']);
$i++;
}
$nunber_of_rows=$i;
mysqli_close($con);
echo json_encode (array(
'tabel'=>$tabel,
'nunber_of_rows'=>$nunber_of_rows
));
?>
私の例のソースは、スニペットの例のリンクにあります。
間違いなく、私の助けを求めてください。
JavaScriptのコード側に問題があるのではないかと思います。私はあなたのPHPとDB関連のコードが結果を適切にスローしていると想定しています。より良い解決策は here からajaxメニューローダープラグインをダウンロードすることです。
PHPコードをファイルにスローするためのコードを設定して、フロントがまったく邪魔にならないようにすることができます。HTML構造に従う必要がある場合があり、スタイルを適用するために新しいクラス名でCSSを更新できます。あなたの問題をもっと早く解決できるといいのですが。