Adding a variable into a page - wordpress - javascript

When I create pages within Wordpress, the call to action links on those pages always have the same URL. I want to be able to globalize this variable but am struggling to find a good way to do it.
If I were making simple PHP pages I could simply include e.g.
$URLpath = "http://example.com/my/page";
Then call this in the html:
Call to action
Obviously I can't do this within the Wordpress CMS as it renders as <?=$URLpath?>
I could add, say, Call to action and replace after the page loads using javascript replace over the whole block of html, but it doesn't feel efficient to do this.
Is there a better way? I'm pretty new to Wordpress.

You can add a shortcode in your functions.php file that prints your cta, or better create a plugin with some parameter that manages this link.
For example in functions.php you could add
function cta_func( $atts ){
$URLpath = "http://example.com/my/page";
return 'Call to action';
}
add_shortcode( 'cta', 'cta_func' );
inside your pages/post you can write simply this shortcode.
...
[cta]
...
Further infos about shortcodes are in the reference of codex
https://codex.wordpress.org/Shortcode_API

A good way to do this within WordPress is to use their wp_localize_script()
In your functions.php file you could use as:
// For sake of example I will put your data inside an array,
// but you can set a single value.
$dataForJS = array(
$URLPath => "http://example.com/my/page"
);
// wp_localize_script() takes 3 parameters:
// 1. Name of the registered script, this is the name you used in wp_register_script()
// here I am naming it "main" but it can be anything.
// 2. Name of the variable.
// This name is then available in your JS and will contain your data.
// 3. The data you want to pass, it can be a single value or array
wp_localize_script( 'main', 'd', $dataForJS );
In your JavaScript, you will be able to access this data by just calling the variable d.
What this does is that if the page requests the "main" script, WordPress will add a script tag with your data inside it and makes sure it is placed before your "main" script runs.

Related

how to handle javascript that only runs on certain pages when bundled together

When working on small client sites, I often end up working with a main.js file that includes a bunch of jQuery plugins and small toggle functionality. Some of these code snippets are only relevant on certain pages, but ends up bundled together in one main.min.js file.
My question is, how do people write the individual code snippets in order to only execute that code when the correct page is being rendered?
Here's an example: Let's say I have a page with a search input field. This input is hooked up with jQuery autocomplete in order to show search suggestions as the user types. the code in main.js could look something like this:
var data = [
{
value: 'some value',
data: 'some data'
},
{...}
]
$('#autocomplete').autocomplete({
lookup: data,
lookupLimit: 10,
minChars: 3,
});
This code is only useful on the template that has that input field, but as main.js contains a bunch of other smaller bits like this that are useful globally and on other pages, the whole file is loaded on every pageview. What strategy should I use to only execute that piece of code when the page needs it?
I though of a few ways my self:
Check if the DOM-element (in this case #autocomplete) exists.
Check if the URL is == '/page-with-autocomplete'.
Use a class on , and check for that class i n order to run the script.
Other ideas? Any standard way to do this sort of thing? Anything considered a "best practice"?
Stick your JS in an if block and check for the unique DOM element on the page you want the script to run.
Although you can't just do:
if ( $('#my-el') ) {}
You have to check if the element has a length, like:
if ( $('#my-el').length ) {}

Add options to a Wordpress plugin Custom Post Type via child theme functions.php

I'm using Uncode theme for a site. It has a core custom post type called 'portfolio'.
I need to add an option to this CPT so that it shares the tags with regular posts.
I have found the file in the theme core where the CPT is registered and added the following and it works:
'taxonomies' => array('portfolio_category', 'post_tag')
However, as editing core files is a big no no, I'm wondering if there is a way of doing this through my own functions file so it is future proof?
EDIT: It's apparent that I've misunderstood!
Looks like register_taxonomy_for_object_type is what you're after.
The WP Codex has this to say:
register_taxonomy_for_object_type()
Add a registered Taxonomy to a registered Post Type.
register_taxonomy_for_object_type( 'post_tag', 'portfolio' );
Original answer:
From the WP Codex:
register_post_type()
Create or modify a post type. register_post_type should only be invoked through the 'init' action. It will not work if called before 'init', and aspects of the newly created or modified post type will work incorrectly if called later.
(addtl. emphasis mine)
This being the case, you could create a function
function igloobob_portfolio_cpt_mod() {
register_post_type('portfolio', $args);
}
add_action('init', 'igloobob_portfolio_cpt_mod', 999);
where $args basically duplicate's the Uncode theme's arguments to register_post_type, save for your modification. The 999 priority arg is to ensure that it executes after the parent theme has already registered the post type.

How would I pass data to an external script loaded with $.getScript()?

So I'm trying to load a javascript remotely using jquery's $.getScript, but I'm puzzled on how I can pass data to the external script.
I've tried setting variables before the call but they aren't available in the script that gets loaded, and when I try to send/retrieve them using the query string, the remote script tries to read the querystring of the base file that it gets called from, not itself. Is there any other way to do this? Or is it possible to have a javascript file read its own querystring rather than the file it's called from (that's loaded in the browser)?
// editor ini
var editor_ini = { page: current_page, action: 'edit' };
var foo = 'bar';
// load the editor
$.getScript('assets/desktop/desklets/'+launcher.config.editor+'/execute.js', function(){});
In the execute.js file, the editor_ini and foo are both unavailable, I get the same result with:
// load the editor
$.getScript('assets/desktop/desklets/'+launcher.config.editor+'/execute.js', { page: current_page, action: 'edit', foo: 'bar' }, function(){});
because the remote script seems to be getting the query string from the original document rather than the one used when calling the file.
If it matters, I was trying to use the query object plugin for jquery for reading the query string.
global variable declared in inline javascript is accessible in external javascript page loaded using $.getScript().
I bet that your var foo='bar' is inside a function, so not visible in global scope. Try:
window.foo = 'bar'
Truly global variables will be accessible to your script. So, if they aren't, then it's probably because your variables that you think are global actually aren't. You can either move them to the top level scope or set them on the window object like Alexei suggested.
There are other ways to share data.
1) You can put an id on the <script> tag that loads the code and then have the code get the .src value from that tag and get the query string off the script's actual URL. I like this option, but I don't know if you can do it using jQuery.getScript() since I don't think it exposes that as an option.
2) You can have the loading script call a function that you provide and return an object with the desired data from that function.
3) Once the new script is loaded, you can call a setXXX() function in that script to set the state that it needs.
4) You can set information into a cookie that the other script can read.
5) You can encode data into a URL hash value that the other script can read.

Get the name of the HTML document that called a JS function

I'm a beginner with JS.
I am working with some JavaScript on a site, and I just want to use only 1 file of JS for determine the actions off the pages. Something like this:
function registerEvents(){
NameOfHTMLDocument = //?? Get the name of the document that called registerEvents function.
switch(NameOfHTMLDocument)
{
case:"homepage":
hmp_btn = document.getElementById("hmp_btn");
hmp_btn.onclick=otherFunction;
break;
case:"otherPage":
elem = document.getElementById("elemID");
elem.onclick=fooFunction;
break;
//etc...
}
}
This function is called with a <body onload="registerEvents()"> that is "inherited" by all the pages.
The question is, How can I get the "NameOfHTMLDocument"?. Because I don't want that JS begin doing weird things when trying to get elements that don't exist.
I found that I can get the URL of the DOM and then play a little with it to get the string that i want, but i'm not sure if this is the better way of doing it.
It Would be nice if you have a better suggestion.
Firstly I would really suggest that you create separate script tags in html documents for functionality that is used only on that page and common functionality in separate file for several reasons:
No code pollution
Ease of change
Smaller download
Secondly, you can use switch on window.location.pathname DOM variable which is everything after domain
instead of homepage, etc..
i.e.
url = vader.samplesite.com/light/saber/
window.location.pathname = /light/saber/
(look at http://www.developertutorials.com/questions/question/q-242.php )
window.location.pathname
All you need to do is some parsing, but I'm sure you'll figure that out :) If not, leave a comment.
In your <body onload="registerEvents()"> pass the object this (the BODY in the DOM) through your event function such as : <body onload="registerEvents( THIS )">.
In your function itself, call the object you passed like object.ownerDocument.URL to get the URL including the HMTL document name or object.ownerDocument.title to get the page title.

Zend headScript() and appendFile not working as expected

I'm having an issue trying to append a javascript file using headScript()->appendFile('file name') with Zend. I have my layout setup like this:
<?= $this->headScript()
->prependScript( 'BASE_URL = "' . $this->baseUrl() . '";' )
->appendFile( $this->baseUrl('js/lib/jquery/jquery-1.4.2.min.js') )
->appendFile( $this->baseUrl('js/admin.js') );
?>
Then, in my controller I am trying to append an additional js file only for this page, like:
$this->view->headScript()->appendFile( 'another/js/file.js' );
This file needs to be appended to what is already setup in the layout. However, this file gets added before the other 'appendFile' files. I've also tried
$this->headScript()->offsetSetFile(999, '/js/myfuncs.js');
But this still adds the file before the other files. This is not how I would expect this to work, especially when using the offsetSetFile method. How can I add this file after the other files? Thanks.
The answer is to use headScript()->prependFile in layout.phtml and headScript()->appendFile in a view.
I know it's a late answer but!
If you do appendFile or appendScript is uses the next available index. Thus
$this->headScript()->offsetSetFile(50, 'file');
$this->headScript()->appendFile('file2');
is equivalent to
$this->headScript()->offsetSetFile(50, 'file');
$this->headScript()->offsetSetFile(51, 'file2');
Also it is key to note that the controller code get executed first before the view/layout code. Thus in your case your appends are actually using the id's 1000, and 1001. A quick fix to this is just to explicitly use offsetSetFile for all your appends. So your code in your layout would look like:
<?=
$this->headScript()
->prependScript( 'BASE_URL = "' . $this->baseUrl() . '";' )
->offsetSetFile(500, $this->baseUrl('js/lib/jquery/jquery-1.4.2.min.js') )
->offsetSetFile(501, $this->baseUrl('js/admin.js') );
?>
I hope this helps future googler's
I've noticed that if I 'prepend' all the files in the layout, I can then use appendFile in my controller and it will appear after them. Unfortunately, then I have to list all my JS files in reverse order in the layout (since they prepend to themselves). I'd really like to keep things in order and just be able to append to my layout stack.
If prepending in the layout file is not good enough, you can either include the files in your bootstrap when you set up your view or you could set up a controller plugin if you need to prepend based on what module is being loaded.
// in your bootstrap
protected function _initHeadScript()
{
$this->bootstrap('view');
$view = $this->getResource('view');
$view->headScript()->appendFile('another/js/file.js');
}
// as a plugin
class My_Plugin_HeadScriptPlugin extends Zend_Controller_Plugin_Abstract
{
public function routeStartup(Zend_Controller_Request_Abstract $request)
{
$view = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->view;
if($request->getModuleName() == 'foo')
{
$view->headScript()->appendFile('another/js/file.js');
}
}
}
Actually, you don't need get the baseUrl 'cause ZF already does it for you. You just have to pay attention to your path. Do not use the first slash! otherwise ZF will return the remote address.
Just use '$this->_view->headLink()->appendStylesheet('css/main.css');'
http://zendframework.com/issues/browse/ZF-3282?focusedCommentId=23552&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-23552
the last comment gives an excellent solution, first include in the layout at top, then print when you need it, this way it will work

Categories

Resources