Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

Template Questions /

Clear/block all Javascript Requirements


Reply


7 Posts   5746 Views

Avatar
david_nash

Community Member, 55 Posts

1 May 2009 at 7:54pm

I'm creating a template and I don't want any of the existing javascript stuff to get loaded. I want to block/clear it all. Is this a bad idea?

In my page.php init() function if I do Requirements::clear() nothing happens. Why would that be?

At the moment I am manually explicitly blocking each javascript file. Here's the code if you want to do it (SS2.3):

class Page_Controller extends ContentController {
   
   public function init() {
      parent::init();
      Requirements::block('jsparty/prototype.js');
      Requirements::block('jsparty/behaviour.js');
      Requirements::block('jsparty/prototype_improvements.js');
      Requirements::block('sapphire/javascript/Validator.js');
      Requirements::block('sapphire/javascript/i18n.js');
      Requirements::block('sapphire/javascript/lang/en_US.js');
   }
...
}

Is there an easier way?

The reason I want to do this is because I like jquery. But when I add it as a requirement and then try to use it I think prototype is getting loaded later so if I try to use $('#MyID') it tells me it that is null, and I'm guessing it's because of prototype.

What are your thoughts?

Avatar
david_nash

Community Member, 55 Posts

14 May 2009 at 12:33pm

I forged ahead despite the massive controversy my post created. Here's my thoughts:

I couldn't use the built in Form/Input objects, because whenever I did that it would show a javascript error 'behaviour not defined'. This was coming from the validation js code.

That wasn't too much of a problem, I like having more control over my HTML and it meant I could use jQuery's validation plugin, which I really like.

But it did mean extra work - I had to code all the HTML forms and inputs by hand.

There's no problem with using both prototype and jquery, as long as you use the Requirements class in the init() function of the controller. I was calling my javascript through the template in the head, and then the prototype.js was getting loaded just before the end of the body, which apparently is "best practise". But it also means that prototype was getting called last and over-riding the '$' object.

Another way I could have got around this by using 'jQuery' instead of '$' in the js - but it seems crazy to me to be loading both prototype/scriptaculous and jquery when I only want jquery.

I read that the next major release of SS will ditch prototype in favour of jquery. Until then I'll probably use this method - it does take longer but I think gives a leaner, more efficient site.

Avatar
Willr

Forum Moderator, 5513 Posts

15 May 2009 at 12:08pm

I read that the next major release of SS will ditch prototype in favour of jquery....

AFAIK this is not quite correct, yes we are moving towards jQuery esp if Form Validation work as planned is completed for 2.4 but prototype will still be around for a few odd things while we slowly transition over to it.

If you setup your jQuery file like - http://doc.silverstripe.com/doku.php?id=jquery#examples you should still be able to use $().

Avatar
Louis

Community Member, 1 Post

28 May 2009 at 8:42am

Edited: 28/05/2009 8:46am

Rather than block the JS entirely, I decided I'd follow what the userforms module does.

First off, you can add to Page_Controller the following, which will disable not only prototype, but also its own Validator.js and the Behaviour script Form's Validator.php class adds. This means your forms have absolutely no JS validation, and no messy code is inserted at the bottom of the page that you don't want.

class Page_Controller extends ContentController {
   
   function init() {
      // block prototype validation
      Validator::set_javascript_validation_handler('none');
      
      // load the jquery
      //Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery-packed.js');
      //Requirements::javascript(THIRDPARTY_DIR . '/jquery/plugins/validate/jquery.validate.min.js');

      parent::init();
   }

I had to place this in Page_Controller, since I was borrowing the SearchField, and I saw no need to apply validation to a search field. The trade off, of course, is now I'm responsible for the validation methods, but I'd prefer that anyway.

Now, inspecting UserDefinedForm.php, it appears that despite all the EditableFormField mentions, those are simple DataObjects, and that it actually uses the same basic Form used everywhere.

So how does it do validation? Ignoring the customization bits, it uses jquery.validate.min.js, and code like the following:

      // Build actions
      $actions = new FieldSet(
         new FormAction("process", $this->SubmitButtonText)
      );
      
      // Do we want to add a clear form.
      if($this->ShowClearButton) {
         $actions->push(new ResetFormAction("clearForm"));
      }
      // return the form
      $form = new Form( $this, "Form", $fields, $actions, new RequiredFields(array_keys($fieldValidation)));
      $form->loadDataFrom($this->failover);
      
      $FormName = $form->FormName();

      // Set the Form Name
      $rules = $this->array2json($fieldValidationRules);
      $messages = $this->array2json($fieldValidation);
      

      // set the custom script for this form
      Requirements::customScript(<<<JS
         (function($) {
            $(document).ready(function() {
               $defaults
               $("#$FormName").validate({
                  errorClass: "required",   
                  messages:
                     $messages
                  ,
                  
                  rules:
                      $rules
               });
               $CustomDisplayRules
            });
         })(jQuery);
JS
);

It continues to use the jQuery compatible-mode wrapper, because other code might use prototype for more than just form validation.

Here's the documentation on that validate method: http://docs.jquery.com/Plugins/Validation#Validate_forms_like_you.27ve_never_been_validating_before.21

Overall, jQuery's validation is both impressive and kind of scary-huge. I'll have to dig into it a touch more, but it looks easy enough.

The best part about doing this? It feels like I'm running on the future, today. Even the forum module has been rewritten to use jQuery. And I don't have any ugly code at the bottom, or useless JS in every request.

P.S. There's an ugly bug when you edit a posting on this forum with a code block in it. (Or at least when I just edited this post here, now.) It adds a <br> tag to the beginning of every line. It added a second one when I hit save, saw the <br>s in the edited post, and edited it again. Not fun, though easy to fix on my end. (Find/Replace)

Avatar
Willr

Forum Moderator, 5513 Posts

28 May 2009 at 11:21am

P.S. There's an ugly bug when you edit a posting on this forum with a code block in it. (Or at least when I just edited this post here, now...

Yea this was fixed very recently. ss.org probably just hasn't been updated with the fixed code. I shall do that now

Avatar
Tama

Community Member, 130 Posts

4 October 2011 at 2:55pm

Edited: 04/10/2011 2:56pm

Following on from this:

Is it possible to block javascript on the website but not in the CMS?

We're using a later version of jQuery which is conflicting with the Silverstripe version of jQuery.

Adding this code to /mysite/Page.php stops Silverstripe from loading it's jQuery on the website and the CMS - which breaks the CMS:

   public function init() {
      parent::init();
      
      // Stop Silverstripe from loading it's own version of jQuery.
      Requirements::block(SAPPHIRE_DIR .'/thirdparty/jquery/jquery.js');
   }

Avatar
Tama

Community Member, 130 Posts

5 October 2011 at 2:15pm

As a follow up this specific problem seems to have come from having $SilverStripeNavigator included in our main Page.ss template.