Cloudflare's Rocket Loader + Wordpress -> Ignore scripts? - javascript

I'm trying to make Cloudflare's Rocket Loader work on my WP site. Everything works fine except for the WP Visual Editor. I followed the advice here but it doesn't work:
How do I add custom attributes to javascript tags in Wordpress?
Cloudflare says that in order to make Rocket Loader ignore a javascript file I need to add the data-cfasync="false" tag before my script:
<script data-cfasync="false" src="/javascript.js"></script>
https://support.cloudflare.com/entries/22063443--How-can-I-have-Rocket-Loader-ignore-my-script-s-in-Automatic-Mode-
Rocket loader doesn't ignore my JS files.
Here's my code:
function rocket_loader_attributes( $url )
{
$ignore = array (
'http://www.mysite.com/wp-includes/js/tinymce/tiny_mce.js?ver=349-21274',
'http://www.mysite.com/wp-admin/js/editor.js?ver=3.4.2'
);
if ( in_array( $url, $ignore ) )
{ // this will be ignored
return "$url' data-cfasync='false";
}
return $url;
}
add_filter( 'clean_url', 'rocket_loader_attributes', 11, 1 );
What is wrong with my code?
I'm currently using Rocket Loader on Automatic mode.
Can anyone help?
Maybe you can point me in the right direction.
Thank you.

I have found the solution for this!
As it's written in this article:
Controlling Cloudflare Rocket Loader
Your script was almost right, but the manual mode is broken. You need to switch to automatic mode, and then make some modifications:
function rocket_loader_attributes_start() {
ob_start();
}
function rocket_loader_attributes_end() {
$script_out = ob_get_clean();
$script_out = str_replace(
"type='text/javascript' src='{rocket-ignore}",
'data-cfasync="false"'." src='",
$script_out);
print $script_out;
}
function rocket_loader_attributes_mark($url) {
// Set up which scripts/strings to ignore
$ignore = array (
'script1.js'
);
//matches only the script file name
preg_match('/(.*)\?/', $url, $_url);
if (isset($_url[1]) && substr($_url[1], -3)=='.js') {
foreach($ignore as $s) {
if (strpos($_url[1], $s)!==false)
return "{rocket-ignore}$url";
}
return "$url' data-cfasync='true";
}
return "$url";
}
if (!is_admin()) {
add_filter( 'clean_url', 'rocket_loader_attributes_mark', 11, 1);
add_action( 'wp_print_scripts', 'rocket_loader_attributes_start');
add_action( 'print_head_scripts', 'rocket_loader_attributes_end');
}

Notice in the example that the tag does not have the type='text/javascript' attribute. For some reason Rocket Loader requires data-cfasync='false' to be used without the type='text/javascript'... a bug?
Your code does add the data-cfasync='false' attribute, but does not override the WordPress behaviour of adding the type='text/javascript' attribute also, which makes Rocket Loader not to "ignore" your script.
It might be tricky to override this WordPress behaviour since the relevant code does not support a filter...

Ernest Marcinko's solution works fine; however a simpler (and potentially safer) solution these days is to use the script_loader_tag hook, added in WordPress 4.1.
See this answer for an example.

Related

wordpress how to add javascript to wp-admin

I am having a hard time on an easy task but seems like I can not find the answer.
I need to add some js code to the wp-admin page of a wordpress and woocommerce.
For this I have the following code on the functions.php:
function my_enqueue() {
wp_enqueue_script('chcol01', plugin_dir_url(__FILE__) . '/aldisjs/admChangeColorScr.js');
}
add_action( 'admin_enqueue_scripts', 'my_enqueue' );
and I have this code on admChangeColorScr.js located on plugins/aldisjs:
function chcol(){
alert("now what?");
}
What I expected is an alert notice on the wp-admin page when I relod but it does not happen.
What I am doing wrong??
First of all, you've defined the chcol function in your javascript file BUT YOU HAVE NEVER CALLED/USED IT!
Second point in your code, when you try to inject your js file to admin (or any other page on wordpress), first check whether you're actually on that page or not. Although, admin_enqueue_scripts action hook should do the trick for you.
For example, in your case, first check whether you're actually on the admin panel or not then inject/enqueue your js file! It never hurts to double check!!!
function my_enqueue() {
if(is_admin()){ // if it returns true
// Then run wp_enqueue_script() function!
}
}
add_action( 'admin_enqueue_scripts', 'my_enqueue' );

TypeError Jquery(...).function is not a function

I'm having an issue with calling a method that has got me completely stumped. I have a set of methods in an external js class that's used for libraries outside core js for the WP theme.
(Sorry About the unending line)
external.js
(function(a){
var b=0;a.fn.mobileMenu=function(c){function e(a){return a.is("ul, ol")}function f(){return a(window).width()<d.switchWidth}function g(c){if(c.attr("id")){return a("#mobileMenu_"+c.attr("id")).length>0}else{b++;c.attr("id","mm"+b);return a("#mobileMenu_mm"+b).length>0}}function h(a){if(a.val()!==null){document.location.href=a.val()}}function j(b){b.css("display","none");a("#mobileMenu_"+b.attr("id")).show()}function k(b){b.css("display","");a("#mobileMenu_"+b.attr("id")).hide()}function l(b){if(e(b)){var c='<div class="td_mobile_menu_wrap"><select id="mobileMenu_'+b.attr("id")+'" class="mobileMenu">';c+='<option value="">'+d.topOptionText+"</option>";b.find("li").each(function(){var b="";var e=a(this).parents("ul, ol").length;for(i=1;i<e;i++){b+=d.indentString}var f=a(this).find("a:first-child").attr("href");var g=b+a(this).clone().children("ul, ol").remove().end().text();c+='<option value="'+f+'">'+g+"</option>"});c+="</select></div>";b.parent().append(c);a("#mobileMenu_"+b.attr("id")).change(function(){h(a(this))});j(b)}else{alert("mobileMenu will only work with UL or OL elements!")}}function m(a){if(f()&&!g(a)){l(a)}else if(f()&&g(a)){j(a)}else if(!f()&&g(a)){k(a)}}var d={switchWidth:td_switch_width_normal,topOptionText:"Menu",indentString:"-"};return this.each(function(){if(c){a.extend(d,c)}var b=a(this);a(window).resize(function(){m(b)});m(b)})}})(jQuery);
And then the core
site.js
jQuery('#td-top-menu .sf-menu').mobileMenu();
and i end up with the error:
Uncaught TypeError: jQuery(...).mobileMenu is not a function
Somewhere along the line, i've managed to break this code and yet i'm not truly sure. I've stripped my header down to just the necessary scripts and nothing causes the error. My current JQuery CDN is the standard downloaded one from google cdn. I was under the impressional that i would get this issue because it cannot resolve the method. But if both scripts are there (I've logged external.js method to see that the script isn't broken), i don't see why it's throwing this error.
The site is http://whatzbuzzing.com to see the error first hand. As a wordpress distribution, i was under the impression that something has gone wrong outside the two files shown because they haven't been edited at all.
In accordance with the order of requests in Chrome Networks panel, you're loading external.js before jquery.min.js. Maybe you could try to fetch jquery.min.js before fetching of external.js? Sorry if I missed anything in your question.
this happens when multiple jquery files are loaded, not a very uncommon thing in a wordpress site.
in your case the problem is here
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.12.0.min.js"></script>
jquery comes bundled with wordpress, all you have to do is to properly enqueue your script with jquery as a dependency
function enqueue_my_external_script() {
wp_enqueue_script( 'externaljs', '//example.com/path/to/external.js', array( 'jquery') );
}
add_action( 'wp_enqueue_scripts', 'enqueue_my_external_script' );
if you're calling this from a theme you can use get_template_directory_uri to get the theme directory's url like this
function enqueue_my_external_script() {
wp_enqueue_script( 'externaljs', get_template_directory_uri() . '/path/to/external.js', array( 'jquery') );
}
add_action( 'wp_enqueue_scripts', 'enqueue_my_external_script' );
wp_enqueue_script function
wp_enqueue_scripts action hook

Drupal 7 override jquery js file in custom theme

Is it possible to rewrite/override a default Drupal 7.26 jquery used in custom template scripts variable ?
I mean one of the js files:
<script type="text/javascript" src="http://drupal.dev/misc/jquery.js?v=1.4.4"></script>
by one which comes by custom theme ?
I tried this in sites/all/MYTPL/template.php but it doesn't work:
$scripts['misc/jquery.js']['data'] = $base_theme . '/js/packages/jquery-2.1.0.min.js';
I would like to know if someone managed it without using any modules such as jQuery Update ?
=== UPDATED ===
Actually I solved it by help of accepted answer with some modifications based on #cojomojo 's answer:
function THEMEname_js_alter(&$javascript) {
// Swap out jQuery to use an updated version of the library.
$javascript['misc/jquery.js']['data'] = drupal_get_path('theme', 'THEMEname') . '/js/packages/jquery-2.1.0.min.js';
}
Use this code inside your theme's template.php file, in hook_js_alter.
function [YOUR_THEME]_js_alter(&$js)
{
$jqKey = "my-new-jquery"; // a key for new jquery file entry
$js[$jqKey] = $js['misc/jquery.js']; // copy the default jquery settings, so you don't have to re-type them.
$js[$jqKey]['data'] = "https://code.jquery.com/jquery-2.1.0.min.js"; // the path for new jquery file.
$js[$jqKey]['version'] = '2.1.0'; // your jquery version.
unset($js['misc/jquery.js']); // delete drupal's default jquery file.
}
So you have a few options to do this. Here they are:
You can use hook_js_alter like so:
<?php
function hook_js_alter(&$javascript) {
// Swap out jQuery to use an updated version of the library.
$javascript['misc/jquery.js']['data'] = drupal_get_path('module', 'jquery_update') . '/jquery.js';
}
?>
Or in order to avoid breakage like 2pha mentioned you can run two versions of jquery side by side. jQuery already has the functionality to run along side a different version of jQuery (or, really, along side any other JavaScript library that uses the $ symbol as a function or variable). This is the noConflict() function. You can view the API page here: http://api.jquery.com/jQuery.noConflict/
To use this functionality within your project, simply tell the browser about your new jQuery library and that you'll be referencing it via your custom noConflict identifier. Here is an example of how you would implement this in a custom theme.
MyTheme/page.tpl.php
<head>
<title><?php print $head_title; ?></title>
<?php print $head; ?>
<?php print $styles; ?>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script type="text/javascript">
var $jq = jQuery.noConflict();
</script>
<?php print $scripts; ?>
</head>
Another possible method is to swap jQuery with the preprocess page like so:
<?php
function yourModuleOrThemeName_preprocess_page(&$variables) {
// exclude backend pages to avoid core js not working anymore
// you could also just use a backend theme to avoid this
if (arg(0) != 'admin' || !(arg(1) == 'add' && arg(2) == 'edit') || arg(0) != 'panels' || arg(0) != 'ctools') {
$scripts = drupal_add_js();
$new_jquery = array(drupal_get_path('theme', 'YOURTHEME') . '/js/jquery-1.7.1.min.js' => $scripts['core']['misc/jquery.js']);
$scripts['core'] = array_merge($new_jquery, $scripts['core']);
unset($scripts['core']['misc/jquery.js']);
$variables['scripts'] = drupal_get_js('header', $scripts);
}
}
?>
To me the best method would be to either run two version of jQuery side by side (the version that Drupal 7 uses by default and whatever your theme requires) or swapping jQuery with the preprocess page. The hook_js_alter has potential for breaking anything that requires the different version of jQuery. All the potential ways to do what you ask are here: https://drupal.org/node/1058168
Maybe use the hook hook_js_alter.
Keep in mind though that other modules will depend on jQuery and if they use something that has changed between versions, you may encounter problems.

Drupal - OpenLayers - Alter popup behavior

I have modified the popup behavior js file: openlayers_behavior_popup.js directly in the module located at openlayers/plugins/behaviors.
It's working fine per my expected but I do not want to put my own modification in the original module, I want to add it attach to my existing module but I don't know how to do this.
I want the site not to take the behavior at openlayers/plugins/behaviors but follow with my popup behavior code from my own module.
Drupal.openlayers.addBehavior('openlayers_behavior_popup', function (data, options) {
// normal
var popupSelect = new OpenLayers.Control.SelectFeature(layers,
{
// my change here!!
},
onUnselect: function(feature) {
// normal
}
}
);
});
How can I alter the behavior code of openlayers?
I have solved my issue on this topic by load the modification javascript file in my custom module as following:
function mycustom_openlayers_init() {
// you might want to load only at some specific page
// if you want so, please have a look to function arg() of drupal
// place condition before loading the js file below
drupal_add_js ( drupal_get_path ( 'module', 'mycustom_openlayers' ) . '/js/openlayers_behavior_popup.js', array(
'weight' => '9999',
) );
}
By specifying the setting of weight bigger, my javascript is loaded after loading the original openlayers popup file and then it overrides the behavior of the original to take mine instead.
I don't know if it is the right thing to do but it works for me.
Please let me know if other people could give me a programmatic solution on that and better than above.

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