I'm sure I'm not doing this in the correct manner, but I just experimenting to find out the best way to get this done.
Basically, I am using Wordpress, I have created my own theme, based on Thematic.
I have a loop, that is displaying posts from a category.
At the top of the page, I have a menu, which i am trying to use as a filter. So when a user clicks on one of the menu items, it takes the ID of that item, which is the category ID, and then I am trying to use JQuery to replace the contents of a div with the new categories posts.
When i tried using AJAX to load the content, i was getting undefined function errors. So I tried putting the loop into a PHP function inside functions.php.
Here is the function:
function get_vehicle_filter() {
$f = 0;
query_posts( array('cat' => '47', 'orderby' => 'ID', 'order' => 'ASC'));
while ( have_posts() ) : the_post();
$postid = get_the_ID();
$site_url = get_site_url();
$src = wp_get_attachment_image_src( get_post_thumbnail_id($post->ID), array( 200,200 ), false, '' );
echo "<a href='$site_url/vehicles-sale-info/?post_id=$postid'>";
echo "<div class='job_image_holder'>";
echo "<img src='$src[0]' class='attachment-post-thumbnail wp-post-image' />";
echo "<div class='job_image_title'>";
the_title( "<p class='white center'>", "</p>" );
echo "</div>";
echo "</div>";
echo "</a>";
$f++;
endwhile;
wp_reset_query();
}
I'm using this to display the loop on the page, which works fine:
<script>
jQuery(document).ready(function(jQuery) {
jQuery("#filtered_vehicles").html("<?php get_vehicle_filter() ?>");
});
</script>
But when i try to get the ID of the clicked menu item into the php function, I am falling down. This is the latest version:
jQuery('.vehicle_filter_item').click(function() {
// capture id from clicked button
var filterCat = jQuery(this).attr('id');
jQuery('#filtered_vehicles').fadeOut('fast', function() {
jQuery("#filtered_vehicles").html('<?php $filterCat = ' + filterCat + '; get_vehicle_filter($filterCat) ?>').fadeIn('fast');
});
});
I know thats not right, and it obviously doesnt work!!
But I've been breaking it down to see what is and isnt working, and if i try to call the function in its simplest form, as I have above when the page is loading, like below, it doesnt work?
jQuery('.vehicle_filter_item').click(function() {
// capture id from clicked button
var filterCat = jQuery(this).attr('id');
jQuery('#filtered_vehicles').fadeOut('fast', function() {
jQuery("#filtered_vehicles").html('<?php get_vehicle_filter() ?>').fadeIn('fast');
});
});
As this works when the page loads, why doesnt it work when replacing with JQuery, the exact same code?
Can anyone point me in the right direction please.
Thanking you!
PHP executes on the server. So when you serve the page, the content inside the jQuery html() is already written. Your function get_vehicle_filter() has been called and the return is what appears inside your jQuery("#filtered_vehicles").html().
What you need to do is inside the click event, make an AJAX call to a file that returns the get_vehicle_filter(). Something like that:
jQuery('.vehicle_filter_item').click(function() {
// capture id from clicked button
var filterCat = jQuery(this).attr('id');
$.ajax({
method: "POST",
url: "file_that_calls_get_vehicle_filter.php",
data: { filter: filterCat }
})
.done(function( result ) {
jQuery('#filtered_vehicles').fadeOut('fast', function() {
jQuery("#filtered_vehicles").html(result).fadeIn('fast');
});
});
});
Hope it sends you on the right path.
Right, this is how I got this working.
Ajax call:
jQuery('.vehicle_filter_item').click(function() {
// capture id from clicked button
var filterCat = jQuery(this).attr('id');
jQuery.ajax({
method: "POST",
url: "ajax-functions.php",
data: "filterCat="+ filterCat,
})
.done(function( result ) {
jQuery('#filtered_vehicles').fadeOut('fast', function() {
jQuery("#filtered_vehicles").html(result).fadeIn('fast');
});
});
});
Function: (which is called on page load)
function get_vehicle_filter() {
$f = 0;
query_posts( array('cat' => '47', 'orderby' => 'ID', 'order' => 'ASC'));
while ( have_posts() ) : the_post();
$postid = get_the_ID();
$site_url = get_site_url();
$src = wp_get_attachment_image_src( get_post_thumbnail_id($post->ID), array( 200,200 ), false, '' );
echo "<a href='$site_url/vehicles-sale-info/?post_id=$postid'>";
echo "<div class='job_image_holder'>";
echo "<img src='$src[0]' class='attachment-post-thumbnail wp-post-image' />";
echo "<div class='job_image_title'>";
the_title( "<p class='white center'>", "</p>" );
echo "</div>";
echo "</div>";
echo "</a>";
$f++;
endwhile;
wp_reset_query();
}
Function called through AJAX ajax-functions.php
define('WP_USE_THEMES', false);
require_once('../../../wp-blog-header.php');
if($_POST['filterCat'] == "") {
$filterCat = '47';
} else {
$filterCat = $_POST['filterCat'];
}
$f = 0;
query_posts( array('cat' => $filterCat, 'orderby' => 'ID', 'order' => 'ASC'));
while ( have_posts() ) : the_post();
$postid = get_the_ID();
$site_url = get_site_url();
$src = wp_get_attachment_image_src( get_post_thumbnail_id($post->ID), array( 200,200 ), false, '' );
echo "<a href='$site_url/vehicles-sale-info/?post_id=$postid'>";
echo "<div class='job_image_holder'>";
echo "<img src='$src[0]' class='attachment-post-thumbnail wp-post-image' />";
echo "<div class='job_image_title'>";
the_title( "<p class='white center'>", "</p>" );
echo "</div>";
echo "</div>";
echo "</a>";
$f++;
endwhile;
wp_reset_query();
So, basically, the reason I could not get this working was because on the AJAX call, which was a separate file, i was missing these 2 lines at the top:
define('WP_USE_THEMES', false);
require_once('../../../wp-blog-header.php');
Related
I'm trying to make a simplistic website that only shows the post image after you hover on a title. The problem is I can't get my JS to work.
With some previous tips I got here on how to go about doing this I first list all the post images with their URL as an ID (makes it easier to compare) in a PHP shortcode snippet:
// The Query
$the_query = new WP_Query( array( 'post_type' => 'post','posts_per_page' => -1 ) );
// The Loop
if ( $the_query->have_posts() ) {
echo '<ul>';
while ( $the_query->have_posts() ) {
$the_query->the_post();
//Useless
// echo '<li>' . get_the_title() . '</li>';
// echo '<li>' . get_permalink() . '</li>';
echo '<li>';
echo '<a href="' . get_permalink() . '">';
echo '<figure class="popUp" id="' . get_permalink() . '">';
the_post_thumbnail();
echo '</figure>';
echo '</a>';
echo '</li>';
}
echo '</ul>';
/* Restore original Post Data */
wp_reset_postdata();
} else {
// no posts found
}
In CSS I set the display properties of PopUp to none.
Up to this point everything is as expected. But now the JS comes in. I want to get the URL of a hovered post and if it is the same as the URL(in CSS the ID) of the post I want it to display. When hovering stops I also want the image to disapear.
document.getElementById("carousel").addEventListener('mouseover', function(event) {
var hoveredEl = event.target; // The actual element which was hovered.
if (hoveredEl.tagName !== 'A') { return; } // Ignore non links
const addCSS = s =>(d=>{d.head.appendChild(d.createElement("style")).innerHTML=s})(document);
// Usage:
addCSS("#" + hoveredEl + " { display: inline-block; }";)
});
document.getElementById("carousel").addEventListener('mouseout', function(event) {
var hoveredEl = event.target; // The actual element which was hovered.
if (hoveredEl.tagName !== 'A') { return; } // Ignore non links
const addCSS = s =>(d=>{d.head.appendChild(d.createElement("style")).innerHTML=s})(document);
// Usage:
addCSS("#" + hoveredEl + " { display: none; }";)
});
I put it on the page as a shortcode JS snippet in the same DIV as the PHP code but in a different to the links being hovered (could that be the iss). Is there any obvious red flags in the JS code?
Edit: Closed figure tag and used the event listener on a specific DIV. Still no luck...
Try something like this (note the new hover-target class):
// The Query
$the_query = new WP_Query( array( 'post_type' => 'post','posts_per_page' => -1 ) );
// The Loop
if ( $the_query->have_posts() ) {
echo '<ul>';
while ( $the_query->have_posts() ) {
$the_query->the_post();
echo '<li>';
echo '<a class='hover-target' href="' . get_permalink() . '">';
echo '<figure class="popUp" id="' . get_permalink() . '">';
the_post_thumbnail();
echo '</figure>';
echo '</a>';
echo '</li>';
}
echo '</ul>';
/* Restore original Post Data */
wp_reset_postdata();
} else {
// no posts found
}
jQuery('.hover-target').hover(function(e) {
$(this).siblings('figure').show()
}, function(e){
$(this).siblings('figure').hide()
})
This assumes the thumbnails are hidden by default, with a rule such as this:
.popUp {
display: none;
}
This works because you are using jQuery's hover() to pass two separate functions, one for mouseenter and one for mouseleave. On mouseenter, display the image. On mouseleave, hide the image.
I'm currently doing a PHP page that displays bans and also gives an option to unban users.
I can't seem to get the button to work and run the query to unban. Any help would be much appricated.
It currently does nothing and I'm also unsure as to how to display the Pnotice errors as I get
Uncaught TypeError: Cannot read property 'required' of undefined
Here is the function listed in lightcms.php for banlist.php;
function banListAll() {
global $db;
$getBanListAllQuery = "SELECT * FROM users_bans";
$getBanListAll = $db->query($getBanListAllQuery);
while ($showBanListAll = $getBanListAll->fetch_assoc()) {
echo "<tr id=\"banID" . $showBanListAll['id'] . "\">";
echo "<td>";
echo $showBanListAll['id'];
echo "</td>";
echo "<td>";
echo $showBanListAll['added_date'];
echo "</td>";
echo "<td>";
echo $showBanListAll['value'];
echo "</td>";
echo "<td>";
echo $showBanListAll['reason'];
echo "</td>";
echo "<td>";
echo $showBanListAll['expire'];
echo "</td>";
echo "<td>";
echo "<button data-id=\"" . $showBanListAll['id'] . "\" type=\"button\" class=\"btn btn-xs btn-danger btn-unban\">Unban</button>";
echo "</td>";
echo "</tr>";
}
}
Here is the javascript on banlist.php
<script type="text/javascript">
$(".btn-unban").click(function(){
var articleId = "#banID"+ $(this).attr("data-id");
var myData = "unban="+ $(this).attr("data-id"); //post variables
var formData = new FormData(this);
$.ajax({
type: "POST",
url: "./engine/post/unban.php",
dataType:"json",
data: myData,
success: processJson
});
function processJson(data) {
// here we will handle errors and validation messages
if (!data.success) {
if (data.errors.required) {
new PNotify({
title: 'Uh oh!',
text: data.errors.required,
type: 'error'
});
}
} else {
new PNotify({
title: 'Success!',
text: data.message,
type: 'success'
});
$(articleId).fadeOut("slow");
}
}
});
</script>
And here is the unban.php file
<?php
require_once $_SERVER['DOCUMENT_ROOT']."/admin_required.php";
$id = $_POST['id'];
$insert = "DELETE users_bans WHERE id = '$id'";// Do Your Insert Query
if($db->query($insert)) {
echo '{"success":true,"message":"User was unbanned!"}';
} else {
echo '{"error":true,"message":"Sorry this has not worked, try another time!"}';
}
//Need to work on displaying the error^
?>
Your JS looks for "errors.required" but your PHP sends "error" with no required.
Here's some code edits that (IMO) clean up the code. (any changes to sql are based on the assumption that you're using mysqli. that assumption based on the use of ->fetch_assoc()) Please consider atlest the change to unban.php as what you currently have is open to sql injection
Your new banListAll function:
function banListAll() {
global $db;
// don't use SELECT * if you can help it. Specify the columns
$getBanListAllQuery = "SELECT id, added_date, value, reason, expire FROM users_bans";
$getBanListAll = $db->query($getBanListAllQuery);
while ($showBanListAll = $getBanListAll->fetch_assoc()) {
$showBanListAll[] = "<button type='button' class='btn btn-xs btn-danger btn-unban'>Unban</button>";
// array_slice to get ignore the ['id']
echo "<tr data-banid='" . $showBanListAll['id'] . "'><td>" . implode("</td><td>", array_slice($showBanListAll,1)) . "</td></tr>";
}
}
New JS on banlist.php
<script type="text/javascript">
function processJson(data) {
// here we will handle errors and validation messages
if (data.error === false) {
row.fadeOut("slow");
}
// assuming we always get a "message"
new PNotify({
title : 'Uh oh!',
text : data.message,
type : 'error'
});
}
$(".btn-unban").click(function() {
var $this = $(this); // creating jQuery objects can be costly. save some time
var row = $this.closest('tr');
var banID = row.data('banid');
var postData = { unban: banID };
var formData = new FormData(this);
$.ajax({
type : "POST",
url : "./engine/post/unban.php",
dataType : "json",
data : postData,
success : processJson
});
});
</script>
And here is the unban.php file
<?php
require_once $_SERVER['DOCUMENT_ROOT']."/admin_required.php";
$id = $_POST['id'];
// Don't just concat variables that came from users into your DB queries.
// use paramterized queries. If $db is a mysqli connection
$insert = "DELETE FROM users_bans WHERE id = ?";// Do Your Insert Query
$deleteStmt = $db->prepare($insert);
// if id is a number change "s" to "i" below
$deleteStmt->bind_param("i",$id);
if($deleteStmt->execute()) {
echo jsonResult(false,"User was unbanned!");
} else {
echo jsonResult(true,"Sorry this has not worked, try another time!");
}
// add this function to return results to your JS functions
// should make it harder to put "errors" instead of "error" ;)
function jsonResult($hasErrors, $msg) {
return json_encode(array("error"=>$hasErrors,"message"=>$msg));
}
and just in case you thought unban.php was getting unnecessarily long, here it is without comments
<?php
require_once $_SERVER['DOCUMENT_ROOT']."/admin_required.php";
$id = $_POST['id'];
$insert = "DELETE FROM users_bans WHERE id = ?";// Do Your Insert Query
if ($deleteStmt = $db->prepare($insert)) {
$deleteStmt->bind_param("i",$id);
if($deleteStmt->execute()) {
echo jsonResult(false,"User was unbanned!");
} else {
echo jsonResult(true,"Sorry this has not worked, try another time!");
}
}
else {
print_r($db->error);
}
// the function should go into your general functions file
?>
I have a data set of items coming from a SQL database. Those items are displayed in multiple divs like:
<?php
$url = 'DataBase';
$json_response = file_get_contents ( $url );
$json_arr = json_decode ( $json_response, true );
for($i = count ( $json_arr )-1; $i > 0; $i--) {
$json_obj = $json_arr [$i];
echo '<div id="MyDIV">';
echo $json_obj ['id'] ;
echo $json_obj ['title'];
echo $json_obj ['article'];
echo '<button id="read_more_btn">Read more</button>';
echo '</div>'
}
?>
My problem is that I cannot handle click events for EACH div, so I cannot identify which item has been clicked. I’ve been searching for a solution for quite a while, but haven’t found anything. So my question is – how can I identify the clicked item?
EDIT
I have no idea how I can dynamically assign an ID to a button
You could use a data attributes (HTML5 assumed) to attach the Id as meta data to your divs. Your PHP (note I am adding data-id attributes):
<?php
$url = 'DataBase';
$json_response = file_get_contents ( $url );
$json_arr = json_decode ( $json_response, true );
for($i = count ( $json_arr )-1; $i > 0; $i--) {
$json_obj = $json_arr [$i];
echo '<div data-id="' . $json_obj['id'] . '">';
echo $json_obj ['id'] ;
echo $json_obj ['title'];
echo $json_obj ['article'];
echo '<button id="read_more_btn">Read more</button>';
echo '</div>'
}
?>
JS - simple click handler attachment, using jQuery .data() [docs] to get data attribute:
$('div').click(function(e) {
var id = $(this).data("id");
alert(id);
});
JSFiddle Demo
How about when creating the html in the php, you echo the id inside the class.
echo '<div id="mydiv-' . $json_obj['id'] . '">';
So now in the html, it's going to look like
<div id="mydiv-1"> ... </div>
<div id="mydiv-2"> ... </div>
<div id="mydiv-3"> ... </div>
etc.
And then in Javascript, you could access them the same way you access any tag.
$('#mydiv-1').click(function(e){
console.log('a div was clicked');
console.log($(this))
});
So in order to assign listeners to each div, you could do a loop
for(var i = 1;$('#mydiv-container').children().length >= i,i++)
{
$('#mydiv-' + i).click(function(){
}
Make sure to add a container for all the divs.
Give each div a unique numeric class, so your jquery will be
$('div').click(function() {
var item_id = $(this).attr("class");
//do stuff here
});
or
$('div').click(function() {
var item_id = this.className;
//do stuff here
});
I have a form where I add Input fields ( groups ) dynamically.
It is quite a complex form, and a PART can be seen here : FIDDLE
The actual error i get on the consul is :
Error: uncaught exception: query function not defined for Select2 s2id_autogen1
When I have fields already in the form ( the first two for example ) the EDIT and REMOVE button will work just fine .
My problem is that the REMOVE button ( styled input field ) is not working for the dynamically ADDED fields ( actually "appended" by JS and populated from PHP )
NOTE on code: I know the code is a mess :-(. It was inherited and will be cleaned soon.
it was copied and pasted from the HTML output.
The ADD , REMOVE and EDIT are actually styled like buttons ( too long and irrelevant to paste )
The actual source is PHP and it is spanning over multiple files ( so is the JS ) , and thus a bit too complicated to show here .
UPDATE : The code as per popular request :-)
public function show_field_repeater( $field, $meta ) {
global $post;
// Get Plugin Path
$plugin_path = $this->SelfPath;
$this->show_field_begin( $field, $meta );
$class = '';
if ($field['sortable'])
$class = " repeater-sortable";
echo "<div class='at-repeat".$class."' id='{$field['id']}'>";
$c = 0;
$meta = get_post_meta($post->ID,$field['id'],true);
if (count($meta) > 0 && is_array($meta) ){
foreach ($meta as $me){
//for labling toggles
$mmm = isset($me[$field['fields'][0]['id']])? $me[$field['fields'][0]['id']]: "";
echo '<div class="at-repater-block at-repater-block-'.$c.$field['id'].'"><h3>'.$mmm.'
<span class="at-re-remove">
<input id="remove-'.$c.$field['id'].'" class="buttom button-primary" type="submitkb" value="Remove '.$field['name'].'" accesskey="x" name="removek">
</span>';
echo '<script>
jQuery(document).ready(function() {
jQuery("#remove-'.$c.$field['id'].'").on(\'click\', function() {
var answer = confirm("Are you sure you want to delete this field ??")
if(!answer){
event.preventDefault();
}
jQuery(".at-repater-block-'.$c.$field['id'].'").remove();
});
});
</script>';
echo '<span class="at-re-toggle">
<input id="edit-'.$field['id'].'" class="buttom button-primary" type="" value="Edit '.$field['name'].'" accesskey="p" name="editk"></h3>
</span>
<span style="display: none;">
<table class="repeate-box wp-list-table widefat fixed posts" >';
if ($field['inline']){
echo '<tr class="post-1 type-post status-publish format-standard hentry category-uncategorized alternate iedit author-self" VALIGN="top">';
}
foreach ($field['fields'] as $f){
//reset var $id for repeater
$id = '';
$id = $field['id'].'['.$c.']['.$f['id'].']';
$m = isset($me[$f['id']]) ? $me[$f['id']]: '';
$m = ( $m !== '' ) ? $m : $f['std'];
if ('image' != $f['type'] && $f['type'] != 'repeater')
$m = is_array( $m) ? array_map( 'esc_attr', $m ) : esc_attr( $m);
//set new id for field in array format
$f['id'] = $id;
if (!$field['inline']){
echo '<tr>';
}
call_user_func ( array( &$this, 'show_field_' . $f['type'] ), $f, $m);
if (!$field['inline']){
echo '</tr>';
}
}
if ($field['inline']){
echo '</tr>';
}
echo '</table></span>
<span class="at-re-toggle"><img src="';
if ($this->_Local_images){
echo $plugin_path.'/images/edit.png';
}else{
echo 'http://i.imgur.com/ka0E2.png';
}
echo '" alt="Edit" title="Edit"/></span>
<img src="';
if ($this->_Local_images){
echo $plugin_path.'/images/remove.png';
}else{
echo 'http://i.imgur.com/g8Duj.png';
}
echo '" alt="'.__('Remove','mmb').'" title="'.__('Remove','mmb').'"></div>';
$c = $c + 1;
}
}
echo '<img src="';
if ($this->_Local_images){
echo $plugin_path.'/images/add.png';
}else{
echo 'http://i.imgur.com/w5Tuc.png';
}
echo '" alt="'.__('Add','mmb').'" title="'.__('Add','mmb').'" ><br/><input id="add-'.$field['id'].'" class="buttom button-primary" type="submitk" value="Add '.$field['name'].'" accesskey="q" name="addk"></div>';
//create all fields once more for js function and catch with object buffer
ob_start();
echo '<div class="at-repater-block">';
echo '<table class="wp-list-table repeater-table">';
if ($field['inline']){
echo '<tr class="post-1 type-post status-publish format-standard hentry category-uncategorized alternate iedit author-self" VALIGN="top">';
}
foreach ($field['fields'] as $f){
//reset var $id for repeater
$id = '';
$id = $field['id'].'[CurrentCounter]['.$f['id'].']';
$f['id'] = $id;
if (!$field['inline']){
echo '<tr>';
}
if ($f['type'] != 'wysiwyg')
call_user_func ( array( &$this, 'show_field_' . $f['type'] ), $f, '');
else
call_user_func ( array( &$this, 'show_field_' . $f['type'] ), $f, '',true);
if (!$field['inline']){
echo '</tr>';
}
}
$js_code2 ='<span class=\"at-re-remove\"><input id="remove-'.$c.$field['id'].'" class="buttom button-primary remove-'.$c.$field['id'].'" type="submi7" value="Removevv " accesskey="7" name="remove7"></span>';
if ($field['inline']){
echo '</tr>';
}
$js_code2 = str_replace("\n","",$js_code2);
$js_code2 = str_replace("\r","",$js_code2);
$js_code2 = str_replace("'","\"",$js_code2);
echo $js_code2;
echo '</table><img src="';
if ($this->_Local_images){
echo $plugin_path.'/images/remove.png';
}else{
echo 'http://i.imgur.com/g8Duj.png';
}
echo '" alt="'.__('Remove','mmb').'" title="'.__('Remove','mmb').'" ></div>';
$counter = 'countadd_'.$field['id'];
$js_code = ob_get_clean ();
$js_code = str_replace("\n","",$js_code);
$js_code = str_replace("\r","",$js_code);
$js_code = str_replace("'","\"",$js_code);
$js_code = str_replace("CurrentCounter","' + ".$counter." + '",$js_code);
echo '<script>
jQuery(document).ready(function() {
var '.$counter.' = '.$c.';
jQuery("#add-'.$field['id'].'").on(\'click\', function() {
'.$counter.' = '.$counter.' + 1;
jQuery(this).before(\''.$js_code.'\');
// jQuery("#'.$field['id'].'").append(\''.$js_code2.'\');
// alert(\''.$js_code2.'\');
update_repeater_fields();
});
});
</script>';
echo '<script>
jQuery(document).ready(function() {
jQuery(".remove-'.$c.$field['id'].'").on(\'click\', function() {
var answer = confirm("Are you sure you want to delete this field ??")
if(!answer){
event.preventDefault();
}
jQuery(".remove-'.$c.$field['id'].'").remove();
});
});
</script>';
echo '<br/><style>
.at-inline{line-height: 1 !important;}
.at-inline .at-field{border: 0px !important;}
.at-inline .at-label{margin: 0 0 1px !important;}
.at-inline .at-text{width: 70px;}
.at-inline .at-textarea{width: 100px; height: 75px;}
.at-repater-block{background-color: #FFFFFF;border: 1px solid;margin: 2px;}
</style>';
$this->show_field_end($field, $meta);
}
OK so as you've already been told, the live is deprecated.
Here's the fiddle of the solution: http://jsfiddle.net/y8JFb/2/
Basically give each new div that you dynamically create a unique ID based on your counter, then give data attribute to your remove counter which contains that ID.
Then you have your click handler:
$( document ).on( "click", ".at-re-remove", function( e ) {
$("#"+$(e.target).data("remove")).remove();
$(e.target).remove();
} );
I have a JavaScript in the view but it's not executing again after loading different content with AJAX, so I want to place it in the <head> of the view to be isolated from AJAX without having to put it in a file because it's using PHP arrays from the controller. How do I do it? Is there a way to write JavaScript code the CakePHP way and set it as inline false the same way as JavaScript files?
It seems like even JavaScript codes places in head will not execute with AJAX so how should I do it? Should I place JavaScript related divs outside the content div or what?
This is my view:
<script>
var geocoder, lat, lng;
function initialize() {
var location = <?php echo "\"" . $location . "\""?>;
location = location.replace(/\+/g, ' ');
document.getElementById("address").innerHTML = location + " Weather";
var latlng = new google.maps.LatLng(<?php echo $loc['lat'];?>, <?php echo $loc['lng'];?>);
var mapOptions = {
zoom: 12,
center: latlng,
navigationControl: false,
mapTypeControl: false,
scaleControl: false,
draggable: false,
scrollwheel: false,
disableDoubleClickZoom: true,
zoomControl: false,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
<?php $i = 0 ?>
<?php foreach ($posts as $post): ?>
var markerLatlng = new google.maps.LatLng(<?php echo h($post['Post']['latitude']); ?>, <?php echo h($post['Post']['longitude']); ?>);
var marker = new google.maps.Marker({
position: markerLatlng,
map: map,
title: '<?php echo h($post['Post']['temperature']); ?>',
icon: 'http://chart.apis.google.com/chart?chst=d_map_spin&chld=0.6|0|FF0000|12|_|<?php echo h($post['Post']['temperature']); ?>',
url: '<?php echo $this->Html->url(array('controller' => 'posts', 'action' => 'view', $post['Post']['id'])); ?>'
});
google.maps.event.addListener(marker, 'click', function() {
window.location.href = this.url;
});
<?php endforeach; ?>
}
function loadScript() {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://maps.googleapis.com/maps/api/js?key=AIzaSyBoEBzeiYi-bCaTIlcK7lrNKUyvUfLQqGM&sensor=false&callback=initialize®ion=LB";
document.body.appendChild(script);
}
$(document).ready(function(){
$(".post .toggle").toggle(function(){
$(".post .toggle").css('background-image','url(../../img/down.png)');
$(this).css('background-image','url(../../img/up.png)');
$(".post .description").hide();
$(this).parent().find(".description").show("slow");
$(".post").height(100);
$(this).parent().height(200);},
function() {$(".post .toggle").css('background-image','url(../../img/down.png)');$(".post").height(100);$(".post .description").hide();$(this).css('background-image','url(../../img/down.png)');
});
});
window.onload = loadScript;
</script>
<div id="weather">
<center><div id="address"> </div>
<p><div id="coords"><?php echo $loc['lat'] . ", " . $loc['lng'];?></div></p></center>
<div id="weather-menu">
<?php echo $this->Html->link('Today', 'today/' . $location);?>
<?php echo $this->Html->link('Yesterday', 'yesterday/' . $location);?>
<?php echo $this->Html->link('Custom', 'custom/' . $location);?>
<?php echo $this->Html->link('All', 'all/' . $location);?>
</div>
<div id="post-container">
<?php /*
if ($posts) {
echo "<div id=\"post\"><div id=\"temperature\">";
echo $posts[0]['Post']['temperature'] . "°C</div>";
if ($posts[0]['Humidity']['humidity'])
echo "<div id=\"humidity\">" . $posts[0]['Humidity']['humidity'] . "%</div>";
echo "<div id=\"created\">" . $this->Time->niceShort($posts[0]['Post']['created']) . " </div>";
echo "<div id=\"username\">" . $posts[0]['User']['username'] . "</div>";
echo "<div id=\"condition\">";
if (strtotime($posts[0]['Post']['created']) > date_sunrise(strtotime($posts[0] ['Post']['created']), SUNFUNCS_RET_TIMESTAMP, $posts[0]['Post']['latitude'], $posts[0] ['Post']['longitude'],90, 2) && strtotime($posts[0]['Post']['created']) < date_sunset(strtotime($posts[0]['Post']['created']), SUNFUNCS_RET_TIMESTAMP, $posts[0]['Post']['latitude'], $posts[0]['Post']['longitude'],90, 2))
echo $this->Html->image('/img/weather-icons/' . $posts[0]['Post']['condition'] . 'A.png');
else
echo $this->Html->image('/img/weather-icons/' . $posts[0]['Post']['condition'] . 'B.png');
echo "</div></div>";
}*/
?>
<?php
//$posts = $this->requestAction('/weather/fetch');
foreach (array_slice($posts, 0) as $post) {
echo "<div class=\"post\"><div class=\"temperature\">";
echo $this->Html->link($post['Post']['temperature'] . "°C", array('controller' => 'posts', 'action' => 'view', $post['Post']['id'])) . "</div>";
if ($post['Humidity']['humidity'])
echo "<div class=\"humidity\">" . $post['Humidity']['humidity'] . "%</div>";
echo "<div class=\"created\">" . $this->Time->niceShort($post['Post']['created']) . "</div>";
echo "<div class=\"username\">" . $this->Html->link($post['User']['username'], array('controller' => 'users', 'action' => 'view', $post['Post']['user_id'])) . "</div>";
echo "<div class=\"condition\">";
if (strtotime($post['Post']['created']) > date_sunrise(strtotime($post['Post']
['created']), SUNFUNCS_RET_TIMESTAMP, $post['Post']['latitude'], $post['Post']['longitude'],90, 2) && strtotime($post['Post']['created']) < date_sunset(strtotime($post['Post']['created']), SUNFUNCS_RET_TIMESTAMP, $post['Post']['latitude'], $post['Post']['longitude'],90, 2))
echo $this->Html->image('/img/weather-icons/' . $post['Post']['condition'] . 'A.png');
else
echo $this->Html->image('/img/weather-icons/' . $post['Post']['condition'] . 'B.png');
echo "</div>";
echo "<div class=\"description\">" . $post['Description']['description'] . "</div>";
echo "<div class=\"toggle\"></div>";
echo "</div>";
}
?>
</div>
<div id="side-container">
<div id="map_canvas"></div>
<br/>
<div id ="current"><?php if (isset($w_temp)) echo "Current Temperature: " . $w_temp . "°C" . $this->Html->image('/img/wg.png');?></div>
</div>
<?php
$this->Paginator->options(array(
'update' => '#content',
'before' => $this->Js->get('#busy-indicator')->effect('fadeIn', array('buffer' => false)),
'complete' => $this->Js->get('#busy-indicator')->effect('fadeOut', array('buffer' => false))
));
echo $this->Paginator->prev('« Previous ', null, null, array('class' => 'disabled'));
echo $this->Paginator->next('Next »', null, null, array('class' => 'disabled'));
echo $this->Js->writeBuffer();
?>
<div id="busy-indicator"></div>
</div>
and this is my controller index action:
public function index($date, $location = null) {
$this->set('location', $location);
$address = urlencode($location);
$loc = $this->getLocation($address);
$this->set('loc', $loc);
$this->loadModel('Post');
if ($date == 'all') {
$this->paginate = array('conditions' => array(
'latitude BETWEEN ? AND ?' => array(
$loc['lat'] - 0.05, $loc['lat'] + 0.05),
'longitude BETWEEN ? AND ?' => array(
$loc['lng'] - 0.05, $loc['lng'] + 0.05)
),
'order' => array('Post.created' => 'desc'),
'limit' => '5');
$this->set('posts', $this->paginate('Post'));
}
else if ($date == 'today') {
$this->set('posts', $this->Post->find('all', array(
'conditions' => array(
'latitude BETWEEN ? AND ?' => array(
$loc['lat'] - 0.05, $loc['lat'] + 0.05),
'longitude BETWEEN ? AND ?' => array(
$loc['lng'] - 0.05, $loc['lng'] + 0.05),
'Post.created >' => date('Y-m-d H:i:s', strtotime("-1 day"))
),
'order' => array('Post.created' => 'desc'))));
}
else if ($date == 'yesterday') {
$this->set('posts', $this->Post->find('all', array(
'conditions' => array(
'latitude BETWEEN ? AND ?' => array(
$loc['lat'] - 0.05, $loc['lat'] + 0.05),
'longitude BETWEEN ? AND ?' => array(
$loc['lng'] - 0.05, $loc['lng'] + 0.05),
'Post.created >' => date('Y-m-d H:i:s', strtotime("-2 day")),
'Post.created <' => date('Y-m-d H:i:s', strtotime("-1 day"))
),
'order' => array('Post.created' => 'desc'))));
}
$this->wunder($location);
}
Thank you guys. I just needed to add this to my javascript code:
var pathname = window.location.pathname;
window.onload = loadScript;
$(document).ready(function() {
$.ajax({
url: pathname,
success: function(){
loadScript();
}
})
});
You wrote:
I have a JavaScript in the view but it's not executing again after
loading different content with AJAX
I only briefly looked at what you are doing but I didn't immediately see where you are making an AJAX request. Clarifying that point would be helpful, as others have noted. However, be aware that After loading new content with AJAX if your script had event handlers on any replaced content then you will need to destroy and recreate the event handlers in Javascript (even if you replaced it with identical DOM elements).
To this point:
Is there a way to write JavaScript code the CakePHP way and set it as
inline false the same way as JavaScript files?
So you do this essentially the same way as you reference external source files in cakePHP, you can replace:
<script>
...
</script>
with the following:
$this->Html->ScriptBlock('your javascript here', array('inline'=>false));
Then in the section make sure you have (for cakePHP 2.1 or newer):
echo $this->fetch('script');
or (for cakePHP 2.0x or earlier)
$scripts_for_layout();
Since you're using "AJAX" to inject a script into a page i suppose, the way you are doing it is by using jQuery maybe or anything pulling your content into the DOM via element.innerHTML = content, am I wrong ?
BUT scripts passed in element.innerHTML will not execute, and this is what jQuery use to fragment your HTML response !
The best way to do it IMHO is to use "AJAX" only to get the data from your CakePHP app to the javascript front end (with a JSON response), then you will use this data within your javascript code to display your charts. It would be much more efficient, and you would not have the issues shoesole is talking about loosing DOM elements references.
Or you can do this the lazy way, with this hack :
<img style="display:none" src="data:image/png,script" onerror="
console.log('Hey I am javascript code running as long as javascript isnt disabled!');
"/>
<script>
// this is new invention like JSON it seem cute function but it is not
function connect_php() {
jQuery(document).ready(function($){
setTimeout(function() {
$("#final_result").css('display', 'block');
}, 4000); //here 1000 means 1 second
});
}
jQuery(document).ready(function($){
(function a(x) {
// The following condition
// is the base case.
if ( ! x) {
return;
}
a(--x);
event.preventDefault();
$( "#aform" ).submit();
connect_php();
})(10);
});
</script>
if you have php for loop doing something must wait this will fired after php finish or your loop finish send message from php to JavaScript defined in JS from start