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.
Related
I am working with a wordpress theme called X theme. My lead dev guy bailed and this function is not working. The purpose of it is to flip to the first image in that products gallery when a mousein/out event occurs. The query is looking for a proceeding post ID which is not there or doesn't meet the criteria for the query. So instead I would like it to simply get the image a better way because this doesn't work consistently.
function x_woocommerce_shop_thumbnail() {
GLOBAL $product;
$stack = x_get_stack();
$stack_thumb = 'entry-full-' . $stack;
$stack_shop_thumb = $stack_thumb;
$id = get_the_ID();
$rating = $product->get_rating_html();
woocommerce_show_product_sale_flash();
echo '<div class="entry-featured">';
echo '<a id="id'.$id.'" value="'.$id.'" href="'.get_the_permalink().'">';
echo get_the_post_thumbnail( $id , $stack_shop_thumb );
global $wpdb;
foreach($wpdb->get_results('SELECT ID FROM wp_posts WHERE post_parent = "'.$id.'" AND post_type = "attachment" ORDER BY ID DESC LIMIT 1') as $key => $row){
$file = '_wp_attached_file';
$childId = $row->ID;
global $wpdb;
$query = 'SELECT meta_value FROM wp_postmeta WHERE meta_key = "'.$file.'" AND post_id = "'.$childId.'"';
$otherImage = $wpdb->get_var($query);
if($otherImage != ''){
echo '<img id="otherImage" src="/wp-content/uploads/'.$otherImage.'"/>';
}
}
if ( ! empty( $rating ) ) {
echo '<div class="star-rating-container aggregate">' . $rating . '</div>';
}
echo '</a>';
echo "</div>";
}
The java & jQuery for the flip (is running in the footer of theme)
//Product Hover Image Switch
jQuery(document).ready(function() {
jQuery('[id^=id]').mouseover(function(){
if(jQuery(this).children('#otherImage').attr('src') != ''){
jQuery(this).fadeTo(200, 0, function(){
var source = jQuery(this).children('#otherImage').attr('src'),
original = jQuery(this).children('.wp-post-image').attr('srcset');
jQuery(this).children('.wp-post-image').attr('srcset', source);
jQuery(this).children('#otherImage').attr('src', original);
}).fadeTo(200, 1);
}
});
jQuery('[id^=id]').mouseout(function(){
if(jQuery(this).children('#otherImage').attr('src') != ''){
jQuery(this).fadeTo(200, 0, function(){
var source = jQuery(this).children('#otherImage').attr('src'),
original = jQuery(this).children('.wp-post-image').attr('srcset');
jQuery(this).children('.wp-post-image').attr('srcset', source);
jQuery(this).children('#otherImage').attr('src', original);
}).fadeTo(200, 1);
}
});
});
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');
I can't figure out how to make the title change upon scrolling inside the id="titlescroll" div, which surrounds the entire post, and then only outputs the text from the class="title output".
I have styled each post (in this case advanced custom field) within a div with id="titlescroll" and have placed the_title() inside a div with class="titleoutput".
With javascript found at http://jsfiddle.net/Nsubt/ I can make the title change, when I scroll past the class="titleoutput" div, but then I have the problem that it only changes when I scroll past the top of the post where the php code for the_title() sits. This causes problems when I scroll upwards.
I really appreciate any help I can get. Thanks!
PHP code
<?php
$query = new WP_Query( 'category_name=news');
// The Loop
if ( $query->have_posts() ) {
echo '<div class="content-area">';
while ( $query->have_posts() ) {
$query->the_post();
$postid = get_the_ID();
echo '<section class="space" id=';
echo $postid;
echo '>';
echo '</section>';
echo '<div id="titlescroll">';
echo '<div class="titleoutput">';
the_title();
echo '</div>';
$fields = get_fields();
if (get_field('one_column_images')){
echo '<div class="entry-content">';
the_field('one_column_images');
echo '<div class="onetext">';
the_field('one_column_text');
echo '</div>';
echo '</div>';
echo '</div>';
}
Javascript
jQuery(document).ready(function($) {
$(window).on("scroll resize", function(){
var pos=$('#entry-title').offset();
$('#titlescroll').each(function(){
if(pos.top >= $(this).offset().top && pos.top<= $(this).next().offset().top)
{
var $this = $(this);
$('#entry-title').html($this.child('.titleoutput').html()); //or any other way you want to get the date
return; //break the loop
}
});
});
});
Problem solved. I tried a million things and one of them worked. Hurrah!
Javascript
jQuery(document).ready(function($) {
$(window).on("scroll resize", function(){
var pos=$('#entry-title').offset();
$('.titleoutput').each(function(){
var box = $('#titlescroll').offset();
if(pos.top >= $(this).offset().top && box.top <= $(this).next().offset().top)
{
$('#entry-title').html($(this).html());
return; //break the loop
}
});
});
});
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();
} );