So the problem is as follows:
I want to dynamically echo a javascript thing with PHP. This echo needs to be (or work with) another javascript file where the echo'd value is used to call a function when the ID is clicked.
However when the page is loaded and the document.getElementById things are added (and they are correct) when the element is clicked, the console tells me that fplaying is undefined
PHP File
<?php
mysql_connect ("localhost", "root", "") or die ("We couldn't connect!");
mysql_select_db ("dr");
mysql_query ("SELECT * FROM songs");
$result = mysql_query ("SELECT * FROM songs");
while ($row=mysql_fetch_array($result)) {
$source = $row ['audiosource'];
echo "
document.getElementById('$source').onclick = fplaying
";
}
?>
JS File
$(function() {
console.log( "ready!" );
function fplaying () {
alert ("test");
}
});
I am not sure if this can be done with php and this is probably not the answer you are looking for.But long comments are not recommended so I just posted as an answer.
It is possible to do, I have done when I was new to Web Developments (With ASP.Net), but still this indicates an improper architecture. JavaScript, that you are using, is a client side script and thus should be accompanied with proper AJAX structure to do such thing. Server should only be responsible to send proper response based on request, not dictate how a page should behave on client side.
Some thing like -
var play = function(){
...//code to play
};
$.ajax({
url: ..//url to php page
type: ...
...,
success: function(data){
...//data responded by php page
play();
},
error: function(){
}
});
I used syntax for jQuery. There are other libraries too.
This is very simple. Try this.
echo " <script> ";
echo "document.getElementById('$source').onclick = fplaying ";
echo "</script>";
I don't think
document.getElementById('$source').onclick = fplaying
will find the function as fplaying is undefined.
Try:
var fplaying = function() {
alert ("test");
}
instead of
function fplaying () {
alert ("test");
}
As in the JS you are printing through PHP only sets the onclick event for an element with that ID which exists somewhere else on the page I think. So, much better way of doing this would be define a class in that clickable item
<button id='<?php echo $source; ?>' class='click-me'>Click Me</button>
Then in JS use this:
$('.click-me').on('click',function(){
alert($(this).attr('id'));
});
Let's suppose you have a collection, coming from a db query: $collection and consists of associative arrays, with a unique id
Now, you are obviously going to display these objects and ask for a user to do something with them, your fplay function. What you must do, is echo whichever parts of the items you need and somehow pass in the html the item id.
So, the php part which will construct your html would be something like:
echo "<ul>";
$id = $item['id'];
foreach ($collection as $item){
echo '<li><a onclick="return fplaying(' + $id + ')" href="#" class="btn"></li>';
}
echo "</ul>";
Then, your js function would use the id as a parameter and do whatever you need:
function fplaying (id) {
alert ("your id is " + id);
}
$source = $row ['audiosource'];
echo '<div id="'.$source['id'].'" class="sourceDiv">'.$source['name'].'</div>';
then go to your js file and add this --you don't have to do that in php
$(document).ready(function(){
$('.sourceDiv').click(function(){alert($(this).attr('id'))});
});
Obviously your declaration of fplaying() is delayed and in addition its locally defined, only.
$(function() {
console.log( "ready!" );
function fplaying () {
alert ("test");
}
});
In that code fplaying is dropped as soon as the outer function has finished. Try binding that fplaying to your window instead.
$(function() {
console.log( "ready!" );
window.fplaying = function() {
alert ("test");
};
});
To illustrate this additionally:
function a() {
function fplaying() {
alert("Hi");
}
fplaying();
}
a();
will display alert box.
function a() {
function fplaying() {
alert("Hi");
}
}
a();
fplaying();
won't show alert box for fplaying() is visible in scope of a(), only, and thus it's undefined as in your case.
function a() {
window.fplaying = function() {
alert("Hi");
};
}
a();
fplaying();
will show alert box for now fplaying() is declared as method of object window more or less serving as global scope, too.
For it's delayed using $(function() { ... }); make sure invoking code as rendered by PHP isn't running before document has loaded. But that doesn't seem to be an issue according to your spare information on context.
Okay, from what I understand of your problem:
Your php creates a html file that has an element with id="the value of $source" and you want it to play a sound on click.
If you want to create a piece of javascript like you did, you could try:
echo ""
while ($row=mysql_fetch_array($result)) {
$source = $row ['audiosource'];
echo "
document.getElementById('$source').onclick = fplaying()
";
}
echo "</script>"
That should make the browser recognize the script as javascript and execute it. Make sure this is printed to the html after the part of the page with the elements you're referring to is printed to the html. Otherwise the script might run before the relevant part of the page is loaded in the browser.
Related
I want to make instant search using php and java,but I keep getting this error:
Uncaught ReferenceError: searchq is not defined
at HTMLInputElement.onkeydown
So i want every time on key down to activate a function which will search for results in database and display results as a div.I checked all things to make sure all is good.Link .js file to my php page and to my element.Checked my code spelling mistakes,and i cannot find where my mistake is.Here is my code:
jQuery(document).ready(function ($) {
function searchq(){
var searchTxt = $("input[name='food-search']").val();
$.post("Food-Groups-BG.php", {food_data_bg: searchTxt}, function(output){
$("#food-output").html(output);
});
}
});
<?php
mysqli_connect("localhost","myUsername","myPassword","dbName") or die ("could not connect");
if(isset($_POST['Food-Groups-BG.php'])){
$searchq = $_POST['Food-Groups-BG.php'];
$searchq = preg_replace("#[^0-9a-z]#i","".$searchq);
$query = mysqli_query("SELECT * FROM food_data");
$count = mysqli_num_rows($query);
if($count == 0){
$output = 'Няма намерени резултати!';
}else{
while($row = mysqli_fetch_array($query)){
$fname = $row['title'];
$output .= '<div>'.$fname.'</div>';
}
}
}
echo($output);
?>
<!--**************************************************************
HTML
***************************************************************-->
<p>Търсене на храни: <input type="text" name="food-search" id="food-search-id" onkeydown="searchq();"></p>
Any help is appreciated ! <3
By declaring the function searchq inside another function (which is passed to ready()) you only make searchq available inside that function, and not globally. Instead of using the onkeydown attribute in your HTML markup I would bind the event using jQuery.
jQuery(document).ready(function ($) {
function searchq(event) {
var searchTxt = $("input[name='food-search']").val();
$.post("Food-Groups-BG.php", {food_data_bg: searchTxt}, function(output){
$("#food-output").html(output);
});
}
$("#food-search-id").on("keydown", searchq);
});
To learn more about event handling you can check out the jQuery documentation, for example keydown and on.
Ali Yousuf is right. searchq() is only visible in the local scope of the jQuery(document).ready(function ($) {....}) handler function and cannot be accessed from anywhere outside. So you have to remove the jquery ready handler like Ali Yousuf said or define your function like this window.searchq = function() {...} to make it globally accessible
I have built a follow/unfollow Twitter like system using PHP. With help of this forum I have been successful creating a dynamic button that allows you to “follow” or “unfollow” each user, using AJAX/JQUERY to run the PHP/MySQL code in the back and avoid refreshing the page when the action happens. The thing is that I am able to run this script on the background only once. Let’s say a user unfollows a member by mistake (my AJAX/JQUERY script won’t have any problem with that), but then wants to follow him again, this is where I am stuck. The page will have to be refresh to make this happen. I know this is happening due to the PHP dynamic data that I am using as you will see in my code.
In the PHP code am running an iteration that output all the members in the database. I am outputting here (for simplicity) just the member’s name and a follow/unfollow button to each one. The php variable $what_class is the result of a PHP function that looks into the database to determine if the user is following or not that member. $what_class will output the strings “follow” of “unfollow” so the class can be defined, and then be targeted by either of the two the Jquery scripts.
PHP CODE
<?php foreach($members as $member){ ?>
<p class="member_name"><?php echo $member->name; ?></p>
<button class="<?php echo $what_class; ?>" type="button" data-member_id="<?php echo $member->id; ?>" user_id="<?php echo $id;?>" ><?php echo $what_class; ?></button>
<?php } ?>
Below is the JQUERY scripts, as mentioned before, the button class will be defined by PHP through $what_class. This is the problem when trying to re-use the button after the first time, class won´t change in PHP’s $what_class unless the page is refreshed. I tried to use $(this).removeClass('unfollow').addClass('follow') to change the class using Jquery and have the button to be re-usable but it isn’t working.
JQUERY SCRIPTS TO FOLLOW OF UNFOLLOW
<script type="text/javascript">
$(document).ready(function() {
$("button.unfollow").on('click', function() {
var memberId = $(this).attr('data-member_id');
var userId = $(this).attr('user_id');
$.get("follow_actions.php", {unfollow_id:memberId, user_id:userId} , function(data) {
});
$(this).html('follow');
$(this).removeClass('unfollow').addClass('follow');
});
});
</script>
<script type="text/javascript">
$(document).ready(function() {
$("button.follow").on('click', function() {
var memberId = $(this).attr('data-member_id');
var userId = $(this).attr('user_id');
$.get("follow_actions.php", {follow_id:memberId, user_id:userId} , function(data) {
});
$(this).html('unfollow');
$(this).removeClass('follow').addClass('unfollow');
});
});
</script>
Does anyone knows how I accomplish having a reusable button without reloading the page? I thank you in advance.
Previous Answer:
What I do for that kind of scenario is to have two buttons. One will be shown to the user, and the other one will be hidden.
<button class="follow" data-member_id="<?php echo $member->id; ?>" user_id="<?php echo $id;?>" >Follow</button>
<button class="unfollow" style="display:none" data-member_id="<?php echo $member->id; ?>" user_id="<?php echo $id;?>" >Unfollow</button>
Just tweak your php code what to show and what not.
When a button is click, hide this button and show the other one.
$(document).ready(function(){
$(".follow").on("click", function(){
$(".follow").hide(200);
$(".unfollow").show(200);
/* PUT YOUR OTHER PROCESSES HERE */
});
$(".unfollow").on("click", function(){
$(".follow").show(200);
$(".unfollow").hide(200);
/* PUT YOUR OTHER PROCESSES HERE */
});
});
Check this JSfiddle.
Update:
We can use toggleClass() of jQuery.
<button class="follow" data-member_id="12" user_id="12">Follow</button>
And the script:
$(document).ready(function(){
$(".follow, .unfollow").on("click", function(){
var memberId = $(this).attr('data-member_id');
var userId = $(this).attr('user_id');
$(".follow, .unfollow").toggleClass("follow unfollow");
$(this).text(function(i, text){
return text === "Follow" ? "Following" : "Follow";
});
});
});
Check this JSfiddle.
use <button class="followUnfollow <?php echo $what_class; ?>"
You need to write as less code as possible. Have a common class such as followUnfollow and then check if follow class exists within this element using hasClass function from jQuery.
Have a look at the code below.
<script type="text/javascript">
$(document).ready(function() {
$("button.followUnfollow").on('click', function() {
var memberId = $(this).attr('data-member_id');
var userId = $(this).attr('user_id');
if($(this).hasClass('follow')) { // FOLLOW
$.get("follow_actions.php", {follow_id:memberId, user_id:userId} , function(data) {
});
$(this).html('unfollow');
$(this).removeClass('follow').addClass('unfollow');
} else { // UNFOLLOW
$.get("follow_actions.php", {unfollow_id:memberId, user_id:userId} , function(data) {
});
$(this).html('follow');
$(this).removeClass('unfollow').addClass('follow');
}
});
});
</script>
I have a group of Images in a webpage with each one has it's own ID, all of the ID's saved in a php array. I want to write a script where it take the ID from the php array and pass it to the client side and repeat a certain jquery function for each image. Here what I did:
<script>
<? php for ($i = 0; $i < $counterPostID; $i++) {
$str = "#post".$arrID[$i]; ?>
var myvar = <? php echo json_encode($str); ?> ;
var myvar2 = myvar + " " + "#textcaption";
//functions to be repeated for each image
jQuery(myvar).mouseover(function() {
jQuery(myvar2).slideDown("slow");
}).mouseout(function() {
jQuery(myvar2).slideUp("slow");
});
<? php } ?>
</script>
The code work fine but only for the last occurrence in the loop, I want the jQuery code to be repeated for all the images. How can I do that?
Assuming $counterPostID is an array with all the ID's, you can just implode it to a selector
var selector = '<?php echo "#post" . implode(", #post", $counterPostID); ?>';
// should output something like -> '#postid1, #postid2, #postid3' ... etc
$(selector).on('mouseenter mouseleave', function() {
$('.textcaption', this).slideToggle('slow'); // use a class, not the same ID
});
This isn't working because you're overwriting your vars with each loop. You could output the entire array to javascript and loop through it client-side, but you don't have to. I would recommend giving your posts a class, and giving your #textcaption elements a class, since ids must be unique, and targeting the classes:
jQuery('.post').mouseover(function () {
jQuery(this).find('.textcaption').slideDown("slow");
}).mouseout(function () {
jQuery(this).find('.textcaption').slideUp("slow");
});
You're using the SAME ID over and over:
#post1 #textcaption
#post2 #textcaption
^^^^^^^^^^^^--- here
etc..
IDs can occur only ONCE in a DOM document. Since an ID must be unique, document.getElementById() (which is what jquery is using internally, basically) will only ever return a single DOM element, never a list. That means the FIRST id found is what will be returned/processed.
Plus, your code will generate highly repetitive JS. Why not simply pass your IDs as an array to JS, then loop on that array? e.g.
<script>
var IDs = <?php echo json_encode($arrID); ?>;
$.each(IDs, function(idx, valu) {
... do your mouseover/mouseout stuff here ..
});
</script>
I am trying to make a pop up load as soon as the page loads. I've used this already on the site and it works. However now nothing pops up.
<script>
window.onload = function (<?php echo $name . "," . $club ;?>){
var txt = name + " has been deleted from this club";
$.prompt(txt,{
buttons:{Delete:true},
close: function(e,v,m,f){
if(v){
var uid = f.userid;
window.location = "manageclub.php?id=" + club;
}
else{}
}
});
}
</script>
First of all, I should say that this approach doesn't feel quite right; you're building a new page just so that you can show a JavaScript prompt which will then redirect to another page ... I'm sure that could be done in a better way.
That said, here's the answer. You can't pass arguments inside the function definition like that; define those variables inside the function body instead;
Secondly, you're not escaping club properly for use in a URL.
window.onload = function ()
{
var name = <?php echo json_encode($name) ?>,
club = <?php echo json_encode($club) ?>,
txt = name + " has been deleted from this club";
$.prompt(txt, {
buttons:{Delete:true},
close: function(e,v,m,f) {
if (v) {
var uid = f.userid;
window.location = "manageclub.php?id=" + encodeURIComponent(club);
}
}
});
}
I'm using encodeURIComponent() to escape club properly inside JavaScript at the redirect code, and json_encode() to escape the PHP variables to be used in JavaScript.
I have a script that requires quite a few seconds of processing, up to about minute. The script resizes an array of images, sharpens them and finally zips them up for the user to download.
Now I need some sort of progress messages.
I was thinking that with jQuery's .post() method the data from the callback function would progressively update, but that doesn't seem to work.
In my example I am just using a loop to simulate my script:
$(document).ready(function() {
$('a.loop').click(function() {
$.post('loop.php', {foo:"bar"},
function(data) {
$("div").html(data);
});
return false;
});
});
loop.php:
for ($i = 0; $i <= 100; $i++) {
echo $i . "<br />";
}
echo "done";
Update: Getting progress information is a lot easier since jQuery Ajax requests have a promise interface. Use this answer:
https://stackoverflow.com/a/32272660/18771
The original answer below is outdated (it is originally from 2010). It still works but is more complicated than it needs to be. I'll keep it in place for reference and and comparison.
You need some kind of progress info from the server. The ajax callbacks do no progressive work, they fire just once - after the request returned successfully.
So... in PHP you would need something like this:
/* progress.php */
$batch_done = some_way_to_find_out_that_number();
$batch_size = some_way_to_find_out_that_number_too();
header('Content-type: application/json');
// TODO: format number
echo '{"progress":'. ($batch_size==0 ? '0' : $batch_done*100.0/$batch_size).'}';
For this to work your image processing script must leave some evidence of its progress of course.
And in JavaScript something like this:
$(document).ready(function() {
$('a.loop').click(function() {
var queryData = {foo:"bar"};
// prepare a function that does cyclic progress checking
var progressCheck = function() {
$.getJSON(
"progress.php", queryData,
function(data) {
$("div.progress").css("width", data.progress+"%");
}
)
};
$.post(
'loop.php', queryData,
/* create the post request callback now */
function(intvalId){
return function(data) {
$("div").html(data);
clearInterval(intvalId);
}
}( setInterval(progressCheck, 1000) )
);
return false;
});
});
This part requires some explanation:
function(intvalId){
return function(data) {
$("div").html(data);
clearInterval(intvalId);
};
}( setInterval(progressCheck, 1000) )
function(intvalId) is an anonymous function that takes one argument - an interval ID. This ID is necessary to stop an interval that has been set up via setInterval(). Luckily, the call to setInterval() returns this very ID.
The anonymous outer function returns an inner function(data), this one will be the actual callback for $.post().
We call the outer function immediately, doing two things in the process: Triggering off the interval with setInterval() and passing in its return value (the ID) as an argument. This argument value will be available to the inner function at its call time (which may be some minutes in the future). The callback for post() now can actually stop the interval.
As an exercise for you ;)
Modify the ajax call such that it stops the interval on request error or timeout, too. Currently, if the callback is never run (and it runs on success only!), the interval will never stop.
Make sure the post() cannot be triggered twice inadvertently.
Thanks to Tomalak I finally put something together that works.
Since I am not actually writing my image files on the server when processing the batch I wrote a log file that I am consulting in the progress.php script.
I would like to know if this is the best way of doing this. I wanted to avoid writing to a file and tried with PHP's $_session but cannot seem to progressively read from it.
Is this possible with $_session?
HTML:
<a class="download" href="#">request download</a>
<p class="message"></p>
JS:
$('a.download').click(function() {
var queryData = {images : ["001.jpg", "002.jpg", "003.jpg"]};
var progressCheck = function() {
$.get("progress.php",
function(data) {
$("p.message").html(data);
}
);
};
$.post('proccess.php', queryData,
function(intvalId) {
return function(data) {
$("p.message").html(data);
clearInterval(intvalId);
}
} (setInterval(progressCheck, 1000))
);
return false;
});
process.php:
$arr = $_POST['images'];
$arr_cnt = count($arr);
$filename = "log.txt";
$i = 1;
foreach ($arr as $val) {
$content = "processing $val ($i/$arr_cnt)";
$handle = fopen($filename, 'w');
fwrite($handle, $content);
fclose($handle);
$i++;
sleep(3); // to mimic image processing
}
echo "<a href='#'>download zip</a>";
progress.php:
$filename = "log.txt";
$handle = fopen($filename, "r");
$contents = fread($handle, filesize($filename));
fclose($handle);
echo $contents;