Skip to content

Instantly share code, notes, and snippets.

@Natetronn
Last active April 15, 2019 19:01
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Natetronn/5403278 to your computer and use it in GitHub Desktop.
Save Natetronn/5403278 to your computer and use it in GitHub Desktop.
Safecracker Garbage Collection

Ever run into this error before?

Uncaught TypeError: Object [object Object] has no method 'markItUp'

If you've ever used Safecracker for ExpressionEngine chances are you have!

What's happening is Safecracker is including JavaScript for custom fields in your form for you. These custom fields rely on said js to function properly. This in itself isn't a big deal but, the issue arises because Safecracker spits out this js right smack in the middle of your template wherever your Safecracker form happens to be located.

Again not the biggest issue except:

  1. Safecracker doesn't put jQuery at the top of the order. This in-turn produces our error because, something which relies on it doesn't have access to it when it needs it. Some js is looking for jQuery before it was actually loaded in other words.

  2. We might already be calling our own jQuery, probably in our footer so, if we use the include_jquery="no" param in our Safecracker form tag then we again run into this error because jQuery is loading after some script and of course we get the above issue once more.

If you checkout this great EESE answer from Justin you will have a great solution to fixing the above error. This is actually a pretty sweet way to do garbage collection allowing you to shuv all that safecracker js down in your footer and below your own jQuery scripts, where it belongs in the first place, in-turn ridding yourself of this cockroach of a bug!

This works with Safecracker and anything which makes use of Safecracker. Profile:edit tags (Zoo Visitor etc.) mimic Safecracker's parameters and variables.

So, if we take what Justin said in his EESE post we might have something like this for Profile:edit:

{exp:profile:edit return="profile" include_jquery="no" safecracker_head="no"}

	{exp:stash:set name="safecracker_head"}
		{safecracker_head}
	{/exp:stash:set}

	{!-- All your edit profile tags etc. --}

{/exp:profile:edit}

With the above code we now have all your Safecracker js garbage stored in a Stash variable waiting to be placed where ever we want it.

Let's put it in the footer where it goes.

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="/assets/js/vendor/jquery-1.8.0.min.js"><\/script>')</script>
{exp:stash:embed:partials:safecracker_head} 

</body>
</html>

Note: I'm using Low Variable with early parsing turned on for my footer and including said variable in my templates. It could have been a snippet or before that probably an embed. Today you might do something along the line of template partials. It's up to you really.

Also note: the above embed shortcut is setup to use a Stash folder which is set via config override settings. Inside that folder is another folder called partials and inside that is our safecracker_head file. This could have been a core embed just as easy but, we won't get all the great features that come with Stash embeds of course. You can read more about that setup here, here and take a look at the examples as well.

Now in our Stash folder we have a file called partials/safecracker_head.html which gets our Stash variable that we stashed in our edit profile form tag:

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

At the end of the day I'm not doing much different here than what Justin provided though, I did want to write about it and share with you just the same.

One final thought:

However you do it, whether it be via snippets, low vars, stash embeds, regular embeds, template partials or a combination of some of them together, chances are you are going to run up against parse order. With that said, don't freak out if it's not working, try a few things to beat the parse and have fun with it!

@auntialias
Copy link

If your site isn't using stash with template partials, or folders, you can just use stash:get at the bottom of the page.

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

That's all I needed to do to get rid of the Javascript Uncaught Type error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment