I have a header.php, that appears in every single page on my blog, with a navbar that looks like this:
<nav>
<ul>
<li>Logistics</li>
<li>Contact</li>
</ul>
</nav>
But when I click the anchor tag linking to #contact, which is located in page with id 5, as you can see by the php code, nothing happens. I tried using a slash (/#contact) but I keep getting the same behavior. Isn't this the correct way of linking to a specific id on another page?
EDIT: I also have some smooth scrolling code (below) which I think may be related to my issue.
<script>
$( document ).ready( function () {
// Add smooth scrolling to all links
$( "a" ).on( 'click', function ( event ) {
// Make sure this.hash has a value before overriding default behavior
if ( this.hash !== "" ) {
// Prevent default anchor click behavior
event.preventDefault();
// Store hash
var hash = this.hash;
// Using jQuery's animate() method to add smooth page scroll
// The optional number (800) specifies the number of milliseconds it takes to scroll to the specified area
$( 'html, body' ).animate( {
scrollTop: $( hash ).offset().top
}, 800, function () {
// Add hash (#) to URL when done scrolling (default click behavior)
window.location.hash = hash;
} );
} // End if
} );
} );
</script>
Thanks!
You have a javascript error.
<script>
$( document ).ready( function () {
// Add smooth scrolling to all links
$( "a" ).on( 'click', function ( event ) {
// Make sure this.hash has a value before overriding default behavior
if ( this.hash !== "" ) {
// Prevent default anchor click behavior
event.preventDefault();
// Store hash
var hash = this.hash;
// Using jQuery's animate() method to add smooth page scroll
// The optional number (800) specifies the number of milliseconds it takes to scroll to the specified area
$( 'html, body' ).animate( {
scrollTop: $( hash ).offset().top
}, 800, function () {
// Add hash (#) to URL when done scrolling (default click behavior)
window.location.hash = hash;
} );
} // End if
} );
} );
</script>
Here is the problem. On the home page you have a div with id #contato. On the other pages it is not there.
$( 'html, body' ).animate( {
scrollTop: $( hash ).offset().top
}, 800, function () {
// Add hash (#) to URL when done scrolling (default click behavior)
window.location.hash = hash;
} );
Your hash var's value is "#contato", but when js tries to get it's offset you recieve an error saying that it's impossible to read property top of 'undefined'. So, you can try to remove that part of the script from the other pages and only keep it on home. This should work like a charm. If you have any question, please ask.
LE: I'd recommend this method for smooth scroll (I didn't tested it for your case, but it always worked for me)
$(function() {
$('a[href*="#"]:not([href="#"])').click(function() {
if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
if (target.length) {
$('html, body').animate({
scrollTop: target.offset().top
}, 1000);
return false;
}
}
});
});
use
<?php echo get_page_link(5)."#contact"; ?>
instead of get permalink function
Related
On the checkout page in Woocommerce there is an "I accept terms and conditions" checkbox. The "terms and conditions" is a link, but Woocommerce captures the click event on the link, and instead opens a small popup(?) with the Terms and conditions page.
I would like to disable the script, and have it be just a normal link.
I identified the js code which captures this event. Unfortunately it's a part of checkout.min.js which controls other parts of the checkout experience too, so I would like to keep the rest of the script intact.
i = {
init: function() {
e(document.body).on("click", "a.woocommerce-terms-and-conditions-link", this.toggle_terms)
},
toggle_terms: function() {
if (e(".woocommerce-terms-and-conditions").length)
return e(".woocommerce-terms-and-conditions").slideToggle(), !1
}
};
i.init()
Bonus question, can I change the link to point to an arbitrary url (a pdf in this case)?
cale_b is right.
But because the link already has target="_blank" there is no need for add a new click handler. To archieve that your custom javascript code is load / run after WooCommerce's script you can use wp_add_inline_script.
I use this snippet and it works:
function disable_wc_terms_toggle() {
wp_add_inline_script( 'wc-checkout', "jQuery( document ).ready( function() { jQuery( document.body ).off( 'click', 'a.woocommerce-terms-and-conditions-link' ); } );" );
}
add_action( 'wp_enqueue_scripts', 'disable_wc_terms_toggle', 1000 );
Add this to your theme's functions.php and your done.
You can also do this by removing the woocommerce 'action'. Add this code to your functions.php file:
function stknat01_woocommerce_checkout_t_c_link() {
remove_action( 'woocommerce_checkout_terms_and_conditions', 'wc_terms_and_conditions_page_content', 30 );
}
add_action( 'wp', 'stknat01_woocommerce_checkout_t_c_link' )
WooCommerce uses jQuery, so you can use jQuery's off API to remove the event binding, and then assign your own event listener.
Important: The key to making this work is that your script MUST load / run after WooCommerce's script, otherwise the event won't be there to turn "off". If Woo's script runs after yours, it'll bind the event and yours won't remove it. I've demonstrated one method below, but you might need to use others (such as using a setTimeout):
// no-conflict-safe document ready shorthand
jQuery(function($) {
// wait until everything completely loaded all assets
$(window).on('load', (function() {
// remove the click event, and add your own to redirect
$( document.body )
.off( 'click', 'a.woocommerce-terms-and-conditions-link' )
.on( 'click', location.href='your_full_url_here');
});
});
Next, I anticipate you asking how to open the PDF in a new tab - for answers to that, see this question.
I followed this instructions for the removing inline toggle display of "Terms and conditions". It does not work until following code it is removed from checkout.min.js.
.slideToggle(),!1}},i={init:function(){e(document.body).on("click","a.woocommerce-terms-and-conditions-link",this.toggle_terms)},toggle_terms:function(){if(e(".woocommerce-terms-and-conditions").length)return e(".woocommerce-terms-and-conditions").slideToggle(),!1}};
After removing this line from checkout.min.js my checkout.js is also changed, here it is:
//remove toggle
/*
var wc_terms_toggle = {
init: function() {
$( document.body ).on( 'click', 'a.woocommerce-terms-and-conditions-link', this.toggle_terms );
},
toggle_terms: function() {
if ( $( '.woocommerce-terms-and-conditions' ).length ) {
$( '.woocommerce-terms-and-conditions' ).slideToggle();
return false;
}
}
};
*/
// no-conflict-safe document ready shorthand
jQuery(function($) {
// wait until everything completely loaded all assets
$(window).on('load', (function() {
// remove the click event, and add your own to redirect
$( document.body )
.off( 'click', 'a.woocommerce-terms-and-conditions-link' );
.on( 'click', location.href='https://yoursite.whatever');
});
});
wc_checkout_form.init();
wc_checkout_coupons.init();
wc_checkout_login_form.init();
//wc_terms_toggle.init();
});
Thank you for the script.
In a plugin, we're using a button & text input to trigger the wpLink modal. All works well, until we hit a template that removes the main content editor and relies only on metaboxes for the page content.
The error we're getting is this.textarea is undefined. The code we're using is:
$( 'body' ).on( 'click', '.pluginxyz-add-link', function( event ) {
wpActiveEditor = true;
wpLink.open();
return false;
});
So I assume there is some dependency to the main editor. I can't find explicit info/documentation around this.. anyone have a suggestion about making this work without the main editor?
Actually, I just figured this out. In our code, the ONLY sibling text input is always where the value will go.
$( 'body' ).on( 'click', '.pluginxyz-add-link', function( event ) {
clickedEle = $( this );
textBoxID = $( clickedEle ).siblings( 'input[type=text]' ).attr( 'id' );
wpActiveEditor = true;
wpLink.open( textBoxID);
return false;
});
I'm hoping to find some help retrieving the Google Calendar attachment fileId through FullCalendar v2.9.0.
The Google calendar is dedicated to this project and is public as is the Drive folder containing image files which are the attachments - one image per event. I am new to the details of Javascript, but I've searched and researched quite a bit. I have not been able to find an example or tutorial that is close enough to what I'm trying to do that I can understand.
My project involves a month view FullCalendar where a user clicks an event, the event background highlights and a sidebar div populates with title, dateTime, description, location, and attachment image file. The user would browse through multiple events with the sidebar updating accordingly.
Here's what I've done so far:
The Google calendar elements are populating and updating correctly except for the image attachment.
I can hard code the HTML in gcal.html with a URL appended with the attachment fileId and get the image in the sidebar. The image, of course, is static though.
Using Google API Explorer calendar.events.get and entering calendarId, eventId, and simple API key, all of which are retrievable from FullCalendar, API Explorer returns the attachment fileId,
(Note that the fileUrl below works in a browser pulling up a viewer, but does not work in my HTML. This one does though: "https://drive.google.com/uc?export=view&id=0B5Nk_tOCzCISaWdqYy1DYnF6SzA")
From API Explorer
Execute without OAuth
calendar.events.get executed 16 minutes ago time to execute: 282 ms
Request
GET https://www.googleapis.com/calendar/v3/calendars/c6kag4dlhqs7m160s3t3lfggak%40group.calendar.google.com/events/u9a5fuoqkfmkm2c20vpn75krf4?fields=attachments(fileId%2CfileUrl)&key={YOUR_API_KEY}
Response
200
- Show headers -
{
"attachments": [
{
"fileUrl": "https://drive.google.com/file/d/0B5Nk_tOCzCISaWdqYy1DYnF6SzA/view?usp=drive_web",
"fileId": "0B5Nk_tOCzCISaWdqYy1DYnF6SzA"
}
]
}
I've tried what seems like endless combinations of statements, basically guessing, at the right syntax in a gcal.html eventClick function. I've also been trying to add code to events.push in gcal.js. This is the only place where I can find other event elements referenced.
My current setup with "alert(event.fileid);" under eventClick ingcal.html and "attachments: entry.fileid" under events.push in gcal.js returns an alert "undefined". In gcal.js a few lines down I notice "successArgs = [ events ].concat(Array.prototype.slice.call(arguments, 1)); // forward other jq args". I'm wondering if FullCalendar returns all fields for an event?
gcal.html (head)
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<link href='../fullcalendar.css' rel='stylesheet' />
<link href='../fullcalendar.print.css' rel='stylesheet' media='print' />
<script src='../lib/moment.min.js'></script>
<script src='../lib/jquery.min.js'></script>
<script src='../fullcalendar.min.js'></script>
<script src='../gcal.js'></script>
<script>
$(document).ready(function() {
$('#calendar').fullCalendar({
eventLimit: 4,
googleCalendarApiKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
events: {
googleCalendarId: 'c6kag4dlhqs7m160s3t3lfggak#group.calendar.google.com'
},
//$('#calendar'.fullCalendar( 'clientEvents' [, filter ] )
// Need to highlight next upcoming event on page load
// var filter = (events, event.start > getdate(new))
eventClick: function(event, events ) {
alert(event.fileid);
//eventRender: function(event, element, view) {
// Need to reset highlight on prevoiusly clicked event
// element.css('background-color', '#5777c8');
//}
//$('#calendar').fullCalendar( 'updateEvents' );
$( "#sidebar2" ).html(event.title);
$( "#sidebar3" ).html(event.start.format('dddd MMM. Do'));
$( "#sidebar4" ).html(event.start.format('h:mm a'));
$( "#sidebar5" ).html(event.description);
$( "#sidebar6" ).html(
'<a style= color:#a2cadc; href=http://' +
event.location + ' target="_blank">' +
"More Band Info" + '</a>'
);
$(this).css('background-color', '#5777c8');
return false;
console.log
},
loading: function(bool) {
$('#loading').toggle(bool);
}
});
});
</script>
gcal.js (line 122 to end)
return $.extend({}, sourceOptions, {
googleCalendarId: null, // prevents source-normalizing from happening again
url: url,
data: data,
startParam: false, // `false` omits this parameter. we already included it above
endParam: false, // same
timezoneParam: false, // same
success: function(data) {
var events = [];
var successArgs;
var successRes;
if (data.error) {
reportError('Google Calendar API: ' + data.error.message, data.error.errors);
}
else if (data.items) {
$.each(data.items, function(i, entry) {
var url = entry.htmlLink || null;
// make the URLs for each event show times in the correct timezone
if (timezoneArg && url !== null) {
url = injectQsComponent(url, 'ctz=' + timezoneArg);
}
events.push({
id: entry.id,
title: entry.summary,
start: entry.start.dateTime || entry.start.date,
// try timed. will fall back to all-day
end: entry.end.dateTime || entry.end.date, // same
url: url,
location: entry.location,
description: entry.description,
attachments: entry.fileid // tryiing to find the attachment reference
});
});
// call the success handler(s) and allow it to return a new events array
successArgs = [ events ].concat(Array.prototype.slice.call(arguments, 1));
// forward other jq args
successRes = applyAll(success, this, successArgs);
if ($.isArray(successRes)) {
return successRes;
}
}
return events;
}
});
}
// Injects a string like "arg=value" into the querystring of a URL
function injectQsComponent(url, component) {
// inject it after the querystring but before the fragment
return url.replace(/(\?.*?)?(#|$)/, function(whole, qs, hash) {
return (qs ? qs + '&' : '?') + component + hash;
});
}
});
Any help to get this working would be greatly appreciated.
I wanted to use the new observe feature but it does not seem to be working. At least not for me.
First things first here is the result of mrt --version
Meteorite version 0.4.6
Meteor version 0.5.9 (git checkout)
The goal is to create a bunch of draggable elements whose position gets reflected among clients.
Tis is my query:
var items = Items.find({});
var handle = items.observe( {
changed: function (newDocument, oldDocument) {
if ( newDocument._id !== dragged ) {
$( "#" + id ).style( "left", newDocument.left );
$( "#" + id ).style( "top", newDocument.top );
}
}
} );
I know the positions are changed because when I reload the page the images get synchronized. I tried with both observe and observeChanged with the same result. If I set a break point inside the callback it is never called.
could it be because I still have insecure and autopublish on?
thank you for your help
it looks like it helps to remove insecure and autopublish but more importantly, to wait until the subscription is ready.
I ended up using the Meteor.subscribe("name", function() {}); syntax and it works now.
here is the full code:
Meteor.subscribe("allItems", function() {
var items = Items.find( {} );
Session.set( "items", items.fetch() );
handle = items.observe( {
changed: function ( newDocument, oldDocument ) {
if ( newDocument._id !== dragged ) {
$( "#" + newDocument._id ).css( "left", newDocument.left );
$( "#" + newDocument._id ).css( "top", newDocument.top );
}
}
} );
});
hope that helps
How can i Assert that the CSS for a page has successfully loaded and applied its styles in Watin 2.1?
After doing some research and writing up my answer, I stumbled upon this link that explains everything you need to know about CSS, when it is loaded and how you can check for it.
The link provided explains it so well, in fact, that I'm adding some quotes from it for future reference.
If you're curious, my answer was going to be #2 and a variation of #4.
When is a stylesheet really loaded?
...
With that out of the way, let's see what we have here.
// my callback function
// which relies on CSS being loaded function
CSSDone() {
alert('zOMG, CSS is done');
};
// load me some stylesheet
var url = "http://tools.w3clubs.com/pagr/1.sleep-1.css",
head = document.getElementsByTagName('head')[0],
link = document.createElement('link');
link.type = "text/css";
link.rel = "stylesheet";
link.href = url;
// MAGIC
// call CSSDone() when CSS arrives
head.appendChild(link);
Options for the magic part, sorted from nice-and-easy to ridiculous
listen to link.onload
listen to link.addEventListener('load')
listen to link.onreadystatechange
setTimeout and check for changes in document.styleSheets
setTimeout and check for changes in the styling of a specific element you create but style with the new CSS
5th option is too crazy and assumes you have control over the content of the CSS, so forget it. Plus it checks for current styles in a timeout meaning it will flush the reflow queue and can be potentially slow. The slower the CSS to arrive, the more reflows. So, really, forget it.
So how about implementing the magic?
// MAGIC
// #1
link.onload = function () {
CSSDone('onload listener');
};
// #2
if (link.addEventListener) {
link.addEventListener('load', function() {
CSSDone("DOM's load event");
}, false);
};
// #3
link.onreadystatechange = function() {
var state = link.readyState;
if (state === 'loaded' || state === 'complete') {
link.onreadystatechange = null;
CSSDone("onreadystatechange");
}
};
// #4
var cssnum = document.styleSheets.length;
var ti = setInterval(function() {
if (document.styleSheets.length > cssnum) {
// needs more work when you load a bunch of CSS files quickly
// e.g. loop from cssnum to the new length, looking
// for the document.styleSheets[n].href === url
// ...
// FF changes the length prematurely :(
CSSDone('listening to styleSheets.length change');
clearInterval(ti);
}
}, 10);
// MAGIC ends
There has been an update to the article lined to by #ShadowScripter. The new method purportedly works in all browsers, including FF.
var style = document.createElement('style');
style.textContent = '#import "' + url + '"';
var fi = setInterval(function() {
try {
style.sheet.cssRules; // <--- MAGIC: only populated when file is loaded
CSSDone('listening to #import-ed cssRules');
clearInterval(fi);
} catch (e){}
}, 10);
document.getElementsByTagName('head')[0].appendChild(style);
After page load you can verify the style on some of your elements something like this:
var style = browser.Div(Find.ByClass("class")).Style;
Assert.That(Style.Display, Is.StringContaining("none"));
Assert.That(Style.FontSize, Is.EqualTo("10px"));
And etc...
Since browser compatibility can vary, and new future browser standards subject to change, I would recommend a combination of the onload listener and adding CSS to the style sheet so you can listen for when the HTML elements z-index changes if you are using a single style sheet. Otherwise, use the function below with a new meta tag for each style.
Add the following to the CSS file that you are loading:
#*(insert a unique id for he current link tag)* {
z-index: 0
}
Add the following to your script:
function whencsslinkloads(csslink, whenload ){
var intervalID = setInterval(
function(){
if (getComputedStyle(csslink).zIndex !== '0') return;
clearInterval(intervalID);
csslink.onload = null;
whenload();
},
125 // check for if it has loaded 8 times a second
);
csslink.onload = function(){
clearInterval(intervalID);
csslink.onload = null;
whenload();
}
}
Example
index.html:
<!doctype html>
<html>
<head>
<link rel=stylesheet id="EpicStyleID" href="the_style.css" />
<script async href="script.js"></script>
</head>
<body>
CSS Loaded: <span id=result>no</span>
</body>
</html>
script.js:
function whencsslinkloads(csslink, whenload ){
var intervalID = setInterval(
function(){
if (getComputedStyle(csslink).zIndex !== '0') return;
clearInterval(intervalID);
csslink.onload = null;
whenload();
},
125 // check for if it has loaded 8 times a second
);
csslink.onload = function(){
clearInterval(intervalID);
csslink.onload = null;
whenload();
}
}
/*************************************/
whencsslinkloads(
document.getElementById('EpicStyleID'),
function(){
document.getElementById('result').innerHTML = '<font color=green></font>'
}
)
the_style.css
#EpicStyleID {
z-index: 0
}
PLEASE do not make your script load synchronously (without the async attribute) just so you can capture the link's onload event. There are better ways, like the method above.