5

I'm trying to use SafeCracker with a Matrix field. My jQuery is being included at the bottom of my page, right before the closing </body>. My SafeCracker tag is as follows:

{exp:safecracker channel="foo" datepicker="no" error_handling="inline" include_jquery="no" preserve_checkboxes="yes" return="foo-manager/" safecracker_head="no"}
  • include_jquery is set to "no" because it will be included at the bottom of the page
  • date_picker is set to "no" because I don't need it for my form
  • safecracker_head is set to "no" because I do not want JS being included right after the form declaration; any JS the page needs should be after the jQuery include right before the <body>

Problems:

  1. In order for the JS associated with SafeCracker to work, jQuery must have been already defined. So I get a lot of errors with my current configuration. However, if I put my jQuery in the <head>, those errors go away. How can I make this work such that I can still keep jQuery at the end of my page?
  2. When safecracker_head="no", the Matrix table doesn't work. It doesn't even look like the default Matrix UI. So I am forced to set it to safecracker_head="yes" (or just remove the parameter). Then the Matrix table looks normal again. However, the parameter adds JS right after the form (and not right before </body>). How can I control where the JS is included?
  3. Finally, even when I put jQuery in the <head> and have safecracker_head="yes", I get Uncaught TypeError: Object [object Object] has no method 'markItUp' error. Any ideas why?
6

1) This is a known limitation to Safecracker. Since it injects all the JS in the body of the document, right below the form, you must ensure your jQuery library is loaded before your SC JS gets executed. There is a variable to help with this called the safecracker_head variables. I use Stash to solve the problem by manipulating the parse order and forcing the JS to be injected at the bottom of the document. https://github.com/croxton/Stash

Stash is an advanced utility. You may run into more questions than answers at first when using it, but it's seriously the best EE template add-on.

form.html

{exp:stash:set parse_tags="yes"}

    {stash:page_title}Your Page Title{/stash:page_title}
    {stash:page_content}

        {exp:safecracker
            channel="your-channel"
            safecracker_head="no"
            include_jquery="no"
        }

            [YOUR FORM HERE]

            {stash:safecracker_head}
                {safecracker_head}
            {/stash:safecracker_head}       

        {/exp:safecracker}  

    {/stash:page_content}

{/exp:stash:set}

{!-- Include your site header which is a template object (or template partial) --}

{stash:embed:structure:header}

structure/header.html

<html>
<head>
    <title>{exp:stash:get name="page_title"}
</head>
<body>

    {exp:stash:get name="page_content"}

    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js"></script>

    {exp:stash:get name="safecracker_head"}
</body>
</html>

For more information on Stash, there are loads of other good posts here on StackExchange so check those out.

2) If you use safecracker_head="no", you must include the contents it generates or the {safecracker_head} somewhere in your document. Without it, all fieldtypes relying on JS (and CSS) will fail.

3) Probably due to the order the JS is being loaded. I have seen this error too and have always fixed it using the solution I outlined above. A good debugging technique I have used it to do a "view source" and copy the generated markup on the page. Then override (or create a new one) the template with the generated contents. Then begin a process of elimination and reshuffling the code. If you can manipulate the static page to get it to work, then all you have to do is simply restructure your EE template to match.

This is a pretty tedious process sometimes, especially when different add-ons require different versions of jQuery than what you may include in the document. I know jQuery UI causes trouble for me at times and is a constant process of updating and tweaking the integration with new releases.

| improve this answer | |
  • thanks for the input. I'm already exploring Stash (using embed and set/get). I might be able to do as you suggested. Will test and get back to you. – ExpressionEngineNewbie Jan 1 '13 at 16:45
  • Related to this, Natetronn put a stash gist for dealing with the same thing for profile:edit (which uses Safecracker). It's here: gist.github.com/Natetronn/5403278 – auntialias Aug 9 '13 at 2:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.