I am working on a project where there is a list of 5 'Modules'(Module1, Module2... so on). Its displayed in a html table. Each module has some chapters in it and so when modules are displayed in the table, I need to make a tooltip so that when user hovers over the module name a small tooltip shows all the chapter titles associated with it. Pretty much successful in implementing this but stuck at a point where console is displaying message as
'Empty string passed to getElementById().' and no chapters are being shown in tooltip and tooltip appears with "Please Wait..".
Here is my code for the same,
this is my jQuery and AJAX,
<link href='jquery-ui.css' rel='stylesheet' type='text/css'>
<script src='jquery-1.12.0.min.js' type='text/javascript'></script>
<script src='jquery-ui.js' type='text/javascript'></script>
<script>
$(document).ready(function() {
// initialize tooltip
$(".panel-body td").tooltip({
track: true,
open: function(event, ui) {
var id = this.id;
var split_id = id.split('_');
var module_id = split_id[1];
$.ajax({
url: 'fetch_details.php',
type: 'post',
data: {
module_id: module_id
},
success: function(response) {
// Setting content option
$("#" + id).tooltip('option', 'content', response);
}
});
}
});
$(".panel-body td").mouseout(function() {
// re-initializing tooltip
$(this).attr('title', 'Please wait...');
$(this).tooltip();
$('.ui-tooltip').hide();
});
});
</script>
And fetch_details.php
<?php
$dbhost = 'localhost';
$dbuser = 'root';
$dbpass = '';
$conn = mysql_connect($dbhost, $dbuser, $dbpass);
if(! $conn ) {
die('Could not connect: ' . mysql_error());
}
echo '';
mysql_select_db('dbname');
$moduleid = $_POST['module_id'];
$sql= mysql_query("SELECT title FROM table WHERE module_id='$moduleid'");
$html = '<div>';
$i = 1 ;
if( $sql === FALSE ) {
trigger_error('Query failed returning error: '. mysql_error(), E_USER_ERROR);
} else {
while($row = mysql_fetch_array($result)){
$title = $row['title'];
$html .= "<span class='head'>"<?php echo $title ; ?> " :</span><span>"" mins</span><br/>";
$i++;
}
}
$html .= '</div>';
echo $html;
?>
Till now I am unable to find out what's going wrong with this . Any help or advice will be highly appreciated.
The whole structure of the tool tip has to be something like this:
1) for example if you want to tooltip over a td , the td tag must have a title(the $('td#yourid').tooltip() shows the title of the td tag with id of #yourid). even if you don't want the title for your tooltip, you have to use it inside the your tag and later you can change it by an ajax return value. so:
<table>
<tr>
<td id = "tooltip-1" href = "#" title = "Nice tooltip" style="height:100px;width:100px;border:1px solid black;"><td>
</tr>
</table>
2) the tooltip structure must be like this if you want to tooltip over the td tag itself
<script>
$(function() {
$("#tooltip-1").tooltip({
open: function( event, ui ) {
var x = $(this); //this is for getting the tooltip-1 object to later use in ajax call
$.ajax({
type: 'post',
url: 'fetch_details.php',
data: {
'yourdata-name': 'yourdata'
},
success: function(html){
x.tooltip({
content: html
});
}
});
}
});
});
</script>
so you have to put the object that you want to tooltip on, in a variable like x and then use that x in ajax to point to the object so the tooltip will show the result of the ajax returning value
3) tooltip is new in jquery-ui and is somehow incompatible with bootstrap. so if you are using bootstrap try to use the bootstrap version of tooltip
4) there are alot of coding error within your code for example the syntax of $html .= "<span class='head'>"<?php echo $title ; ?> " :</span><span>"" mins</span><br/>"; is completely wrong. e.g. you can't use <?php ?> inside another <?php ?>.
My advice would be to first run my code and echo a simple string from fetch-details.php to ajax success function to see that this structure works and then you can manipulate your code based on this structure
since you gave little information about your code and the error given (by line) this was all i could do to help. i hope this information helps you with your program
Related
I have a <select> with only one option, i want to get the rest of the options from a database using PHP and then populate said <select> with the PHP result using AJAX.
Unfortunately my code is not working, im not surprised as im new to both AJAX and jQuery but i dont get any errors to guide myself through the issue.
The PHP works as expected because its used in another part of the site and i have no issues with it so my error must be in the AJAX (no big surprise here).
Below my HTML:
<select class="custom-select my-1 mr-sm-2" id="producto" name="producto" required>
<option disabled selected value>Elegir...</option>
</select>
Below my AJAX code:
<script type="text/javascript">
$(document).ready(function() {
$("#producto").click(function() {
$.ajax({
url: 'fetch_lista_productos_compra.php',
type: 'get',
success: function(data) {
$("#producto").append(data);
}
});
});
});
</script>
Below my PHP code:
<?php
require $_SERVER['DOCUMENT_ROOT'].'/testground/php/db_key.php';
$conn = mysqli_connect($servername, $username, $password, $dbname);
$sql_query = mysqli_query($conn, "SELECT * FROM productos WHERE disponibilidad = 'disponible'");
while ($row = mysqli_fetch_assoc($sql_query)) {
$titulo = $row['titulo'];
echo <<<EOT
<option value="$titulo">$titulo</option>\n
EOT;
}
?>
As always any kind of help is greatly appreacited and thanks for your time.
IMPORTANT EDIT
<select> has a duplicated id, perhaps i should i have stated this from the start as i know think thats whats causing my issue.
The fact is that in this <form> the selects are created dynamically on user request. They click on Add product and a new select with the products avaiable is created, i know the id/name of said input must have [ ] (id="producto[]") for it to be converted into an array but i dont know how to make the AJAX deal with this dynamically created reapeated selects issue. I apologise for this belated aclaration i realise now it is of the utmost importance.
You have to edit your response from this:
<?php
require $_SERVER['DOCUMENT_ROOT'].'/testground/php/db_key.php';
$conn = mysqli_connect($servername, $username, $password, $dbname);
$sql_query = mysqli_query($conn, "SELECT * FROM productos WHERE disponibilidad = 'disponible'");
while ($row = mysqli_fetch_assoc($sql_query)) {
$titulo = $row['titulo'];
echo <<<EOT
<option value="$titulo">$titulo</option>\n
EOT;
}
?>
To this:
<?php
require $_SERVER['DOCUMENT_ROOT'].'/testground/php/db_key.php';
$conn = mysqli_connect($servername, $username, $password, $dbname);
$sql_query = mysqli_query($conn, "SELECT * FROM productos WHERE disponibilidad = 'disponible'");
$response = '';
while ($row = mysqli_fetch_assoc($sql_query)) {
$titulo = $row['titulo'];
$response .= '<option value="' .$titulo . '">' . $titulo . '</option>'; //Concatenate your response
}
echo $response;
?>
But i suggest to use JSON to get a response and parse it on client side.
You can do this by pushing all values in to response array and use json_encode(). At the end you get straight response from the server with just a values, and append thous values whatever you need on client side.
Update
Also you append data to your existing select options. You can just add thous by editing this:
<script type="text/javascript">
$(document).ready(function() {
$("select#producto").focus(function() { //Change to on Focus event
$.ajax({
url: 'fetch_lista_productos_compra.php',
success: function(data) {
$("select#producto").html(data); //Change all html inside the select tag
}
});
});
});
</script>
Test result:
$('select#options').focus(function(){
alert("Hello this is a select trigger");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="options">
<option value="test">Test</option>
</select>
Please don't construct your html on the server, try to just send the raw data and then construct the html client-side, it's better that way and it leaves room for changing the view later without much coupling.
That said, instead of doing:
while ($row = mysqli_fetch_assoc($sql_query)) {
$titulo = $row['titulo'];
echo <<<EOT
<option value="$titulo">$titulo</option>\n
EOT;
}
just do
$rows = [];
while ($row = mysqli_fetch_assoc($sql_query)) {
$rows[] = $row;
}
//this is your best bet when sending data from PHP to JS,
//it sends the rows as JSON-like string,
//which you'll parse to an array in the client
echo json_encode($rows);
then in the client
$.ajax({
url: 'fetch_lista_productos_compra.php',
type: 'get',
success: (data /*json-like string*/) => {
const dataAsArray = JSON.parse(data);
$.each(dataAsArray, (index, row) => {
//now HERE you construct your html structure, which is so much easier using jQuery
let option = $('<option>');
option.val(row.titulo).text(row.titulo);
$("#producto").append(option);
});
}
});
Regarding your edit about several selects
I don't have access to your server of course so I'm using a mock service that returns JSON. IDs are dynamically generated and all data loading occurs asynchronously after you click on the button.
Try using your url and modify the success function according to your html.
$(document).ready(function() {
$('#add').click(() => {
//how many so far...?
let selectCount = $('select.producto').length;
const select = $('<select class="producto">');
select.attr('id', `producto${selectCount + 1}`);
//then we fetch from the server and populate select
$.ajax({
url: 'https://jsonplaceholder.typicode.com/posts',
type: 'get',
success: function(data) {
data.forEach((d) => {
const option = $('<option>');
option.val(d.id).text(d.title);
select.append(option);
});
}
});
document.body.appendChild(select[0]);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id='add'>Add product</button><br>
<!--<select class="custom-select my-1 mr-sm-2" id="producto" name="producto" required>
<option disabled selected value>Elegir...</option>
</select>-->
HIH
As it turns out the code in the question was actually working properly, the problem was not the code itself but the fact that, as i stated (sadly on a later edit and not right from the start) in the question, there where more than one <select> using the same id, therefore everytime the AJAX was executed the result was appended to the first <select> only, and it was appended over and over again everytime i clicked it, my solution was unifiying both the AJAX that populated the <select> and the jQuery that created the said dynamic <select>'s all in one script thus solving all of my issues at once.
Below my jQuery/AJAX code:
<script type="text/javascript">
$(document).ready(function() {
var max_fields = 10;
var wrapper = $(".input_fields_wrap");
var add_button = $(".add_field_button");
var x = 0;
$(add_button).click(function(e) {
e.preventDefault();
$.ajax({
url: '/testground/php/fetch_lista_productos_compra.php',
type: 'get',
success: function(data) {
if(x < max_fields) {
x++;
var html = '';
html += '<div class="form-group row" id="inputFormRow" style="margin-bottom: 0px;">';
html += '<label class="col-3 col-form-label font-weight-bold">Producto</label>';
html += '<div class="col-7">';
html += '<select class="custom-select my-1 mr-sm-2" id="producto" name="producto[]" required>';
html += '<option disabled selected value>Elegir...</option>';
html += data;
html += '</select>';
html += '</div>';
html += '<div class="col-1 my-auto" style="padding: 0px 0px 0px 0px;">';
html += '<button id="removeRow" type="button" class="btn btn-danger">X</button>';
html += '</div>';
html += '</div>';
$(wrapper).append(html);
}
}
});
});
$(document).on('click', '#removeRow', function () {
$(this).closest('#inputFormRow').remove(); x--;
});
});
</script>
I want to thank everyone that took the time to help me out with this Swati, Serghei Leonenco and Scaramouche, this community is truly amazing.
<script type="text/javascript">
$(document).ready(function() {
$("#producto").change(function() {
$.ajax({
url: 'fetch_lista_productos_compra.php',
type: 'get',
success: function(data) {
console.log(data)
// $("#producto").append(data);
}
});
});
});
</script>`enter code here`
try run this and check in your console that weather you are receiving the data from your php or not.
I have a navigation bar that is created from a MySQL table. I want to click on the link and only change the contents of two divs on the page. However, I cannot figure out the proper way to write the jQuery code.
I've attempted to include a single class for all the links and use
$(".class").click(function(){
//the code to change the div
}
But it doesn't seem to be working.
PHP code
<?php
require(__DIR__.'/dbconf.php');
require(__DIR__.'/db_functions.php');
$db_con = mysqli_connect($host, $username, $pass, $dbname);
$column = "playerName";
$table = "Players";
$condition = "";
$key = "";
$query = selectData($db_con, $column, $table, $condition, $key);
while($row=mysqli_fetch_assoc($query)){
$res[] = $row[$column];
echo "<a href = # class = 'player' name ='".$row[$column]."'>".$row[$column]."</a>";
}
mysqli_close($db_con);
?>
JQuery code
$(".player").click(function(){
var player = $(this).val()
var dataString = 'playerName'+ player;
$.ajax({
type: "POST",
url: "coin_amount.php",
data: dataString,
cache: false,
success: function(postresult){
$(".coins").html(postresult);}
});
return false;
});
It seems like this should work. That when any link with the class "players" is clicked, it should change the value of the player variable and call the coin_amount.php file. But it doesn't. What am I not understanding? I do know the ajax function is correct because I call that function on page load and it works. So it has to be something in the click function.
If player is created after the DOM has loaded, you will have to attach the click listener to the document, like so:
$(document).on('click', '.player', () => {
// execution code here
}
ADD It in the <script></script> tag in the head of page after have loaded the jquery library
Jquery code:
$(document).ready(function() {
$("#cercaButton").click(function () {
$(".divClass").load("./action/loadDdtGiornalieri.php");
});
});
In your case add the id at the link tag generated from the php code that print the menu.
I suggest you to add different ID at every link of the menu in order of load different contenent
From php you have to generate a string as
<a id="cercaButton">Cerca</a>
This is a complete example of load, including also the parameter post at the php web page
If you have to post data at the page loaded from jquery simplest code is
$(document).ready(function() {
$("#cercaButton").click(function () {
$(".divClass").load("./action/loadDdtGiornalieri.php", {
dateIn: $("#dateIn").val(),
tipoInterrogazione: $("#tipoInterrogazione").val()
});
});
});
I'm loading data from mysql to php with ajax. I want to create edit function for my website. This edit will be on modal.
Select input with options (subcategories) is loading by ajax after radio input categories is loaded with previous ajax.
I've tried several jquery events to change select option, but no one worked.
This is script code in my modal file.
<script>
$(document).ajaxComplete(function() {
$("#editexp'.$poz.'").on("shown.bs.modal", function(){
$("input[name=payment'.$poz.'][value='.$method.']").prop("checked", true);
$("input[name=kategoria'.$poz.'][value='.$catid.']").prop("checked", true);
var category = '.$catid.';
var poz = '.$poz.';
$.ajax({
url:"expense_subcategory_change.php",
method:"POST",
data:{category:category,
poz:poz
},
success:function(data){
$("#subcategory'.$poz.'").html(data);
}
});
$("input[type=radio][name=kategoria'.$poz.']").change(function(){
var category = $(this).val();
var poz = '.$poz.';
$.ajax({
url:"expense_subcategory_change.php",
method:"POST",
data:{category:category,
poz:poz
},
success:function(data){
$("#subcategory'.$poz.'").html(data);
}
});
});
});
});
$("#subcategory'.$poz.'").ajaxComplete(function() {
$("#subcategory'.$poz.' ").find("option").each( function() {
var $this = $(this);
if ($this.val() == '.$subcatid.') {
$this.prop("selected","selected");
return false;
}
});
});
</script>
I've also tried this:
$("#subcategory'.$poz.'").ajaxComplete(function() {
$("#subcategory'.$poz.' option[value='.$subcatid.']").prop("selected","selected");
});
also these two functions without ajaxComplete for #subcategory or with second ajaxComplete for document
Input with options is loading but first option is always selected.
This is main part of my expense_subcategory_change code:
$result = mysqli_query($connection,"$sql_query");
$output .= '<select class="mb-3 w-50-100 " name="subcategory'.$poz.'">';
while($row = mysqli_fetch_array($result))
{
$output .= '<option value="'.$row['id'].'" >'.$row['sub'].'</option>';
}
$output .= '</select>';
echo $output;
The issue is in your selector. You are using 'name' in the select element but using '#' (id) to search the dom for the element. Change your PHP code to:
$output .= '<select class="mb-3 w-50-100 " id="subcategory'.$poz.'">';
And I tested with the second method you provided as it seemed cleaner
$("#subcategory'.$poz.' option[value='.$subcatid.']").prop("selected","selected");
See the solution (simplified code) working here https://jsfiddle.net/79kugn60/
If you are using any event. Try Bind that event in your function. So that everytime event gets binded. After firing.
I have a button in my page:
if($posts = $q->fetchAll()) {
foreach ($posts as $post) {
$username = $post[0];
$post_id = $post[2];
$status = $post[1];
echo $username . " " . $status . "<br/>";
echo "<button value = '$post_id' id = 'like' class='like' type='submit'>Like</button>";
}
}
Let's assume I have ten result from the query, I will definitely have 10 LIKE button with the same ID.
Now my jQuery is coming this way:
$("#like").click(function() {
var menuId = $(this).val();
var request = $.ajax({
url: "likes.php",
type: "POST",
data: { id : menuId },
dataType: "html"
});
request.done(function( msg ) {
$(".likecount").html( msg );
});
});
Every click on a single button applies to all 10 buttons. How do I differentiate them and have the database affected accordingly?
First off, you're adding like elements via ajax, but you're binding the event handler to whichever like element is already part of the dom at any given moment:
$(document).ready(function()
{
//when dom is loaded, #like is selected, and event is bound
$('#like').click(function(){});
});
inside the click handler, you perform an ajax call that may add another like element to the page, but you never bind an event handler to that new element.
You have 2 options: add an event handler for each element that is added to the page dynamically (not so good, bad for performance). OR delegate the event. As an added bonus, you don't need the ID's of the like buttons anymore. You can use the like class to delegate!
$(document).ready(function()
{
$('body').on('click', '.like', function()
{
//handle click on like button here
});
});
This adds an event listener to the body tag, that will call the callback function whenever a click is registered on an element that has the like class.
I'll edit this response, to give you a, purely hypothetical way to ensure unique like id's
Using a closure, you can easily get unique ID's, by exploiting the fact that closure vars can outlive the closure function. But as you can see, just from the verbosity and added complexity of the code below, this approach is not to be recommended. Simply use the class, and leave the ID out. delegation all the way!
$('body').on('click', '.like', (function(count)
{//closure, pass like buttons currently on page
var idNum = 0;
count.each(function()
{
$(this).attr('id', $(this).attr('id') + idNum);
++idNum;//increment
});
return function()
{//this is the actual callback
request.done(function( msg )
{
var chunk = $(msg);//parse HTML response
chunk.find('.like').each(function()
{
$(this).attr('id', ($(this).attr('id') || 'like') + idNum);
++idNum;
});
});
};
}($('.like'))));
Or, if for some reason you don't want to delegate the event:
$('.like').on(function handler()
{//callback should be named, you'll see why
request.done(function( msg )
{
$('.like').off('click', handler);//remove handler
//add msg to DOM
$('.like').on('click', handler);//add handler, now including new DOM elements
});
});
You could (and IMO should) optimize this further, by storing the $.each callback in a closure reference, too:
$('body').on('click', '.like', (function(count)
{//closure, pass like buttons currently on page
var idNum = 0, eachCallback = function()
{
$(this).attr('id', ($(this).attr('id') || 'like') + idNum);
++idNum;//increment
};
count.each(eachCallback);
return function()
{//this is the actual callback
request.done(function( msg )
{
var chunk = $(msg);//parse HTML response
chunk.find('.like').each(eachCallback);
});
};
}($('.like'))));
This way, you avoid creating a callback function object on each click event... but read up on closures to fully understand why this is a better approach, performance wise.
Why not change your PHP to:
if($posts = $q->fetchAll()){
foreach ($posts as $post){
$username = $post[0];
$post_id = $post[2];
$status = $post[1];
echo $username . " " . $status . "<br/>";
echo "<button value = '$post_id' id = 'like_$post_id' class='like' type='submit'>Like</button>";
}
As each item relates to a post with a (I hope) unique ID, why not just append that value to the id property?
ID values MUST BE UNIQUE
Then you'll need to change your jQuery selector, how about:
$("button.like").click(function()
Don't use ID as selectors in your jquery, use class selector if your buttons are going to use the same class.
For example:
if($posts = $q->fetchAll()){
foreach ($posts as $post){
$username = $post[0];
$post_id = $post[2];
$status = $post[1];
echo $username . " " . $status . "<br/>";
// Removing Id like, because Id should be unique in DOM.
echo "<button value = '. $post_id. ' class='like' type='submit'>Like</button>";
}
}
Your jQuery will look like:
// class selector is a dot (.), if you use an id selector (hashtag #) and you
// you have more than 1 element with that Id, jQuery will only select the first one.
$('body').on('click', '.like', function(){
var menuId = $(this).val();
var request = $.ajax({
url: "likes.php",
type: "POST",
data: { id : menuId },
dataType: "html"
});
request.done(function( msg ) {
$(".likecount").html( msg );
});
});
I am have a table that shows the user suggestions that they have recieved on clicking read more some ajax is fired and in the database the suggestion is marked as read. Currently if the suggestion is new I show a closed envelope, if it is read I show an open envelope, however I can get it to reload the table when the user clicks the read more link so that the new class can be added. Currently it half works, they click read more and the full suggestions fades in but I need the envelope to change also.
<table>
<?php
$colours = array("#f9f9f9", "#f3f3f3"); $count = 0;
if(isset($newSuggestions)) {
foreach($newSuggestions as $row) {
if($row['commentRead'] == 0) {
$newRow = "new";
} else {
$newRow = "old";
}
?>
<tr id="a<?=$row['thoughtId'];?>" bgcolor="<?php echo $colours[$count++ % count($colours)];?>">
<?php
echo "<td class='".$newRow."'>".substr($row['thought'], 0,50)."...</td>";
echo "<td class='read'><a href='".base_url()."thought/readSuggestion/".$row['thoughtId']."' class='readMore'>Read More</a>";
echo "</tr>";
}
} else {
echo "You have no new suggestions";
}
?>
</table>
</div><!--/popular-->
</div><!--/widget-->
<div id="readMore">
</div>
<script type="text/javascript">
$(document).ready(function() {
//alert("hello");
$('#tabvanilla').tabs({ fx: { opacity: 'toggle', height:'toggle' } });
$('a.readMore').click(function(){
$('#readMore').fadeIn(500);
var url = $(this).attr('href');
$.ajax({
url : url,
type : "POST",
success : function(html) {
$('#readMore').html(html)
},
complete : function(html) {
$('table').html()
}
});
return false;
});
});
</script>
In the JavaScript where you open/fill in the full suggestions, you can modify the envelope image as well, using something like:
$('#envelope').attr('src', 'src/to/envelope.png');
I see no img tags, so you need to add one and fill in the id, so it is found by the JavaScript.
BTW: Having HTML and PHP on the same lines/parts, makes the total very unreadable. Only use <?php ... ?> for large PHP code blocks, otherwise use echo (or something similar).