C5 bug or just improper javascript loading?

Permalink 1 user found helpful
Howdy,

When I do the following to load a css file from my custom block's controller.php add() function:

$html = Loader::helper('html');
$this->addHeaderItem($html->css($this::BLOCK_ROOT . '/css/mystyles.css'));


My css loads perfectly (BLOCK_ROOT is just "/blocks/mycustomblock" btw). But when I use the same technique to load javascript from my add() function:

$html = Loader::helper('html');
$this->addHeaderItem($html->css($this::BLOCK_ROOT . '/css/mystyles.css'));
$this->addHeaderItem($html->javascript($this::BLOCK_ROOT . '/js/myjavascript.js'));


it freezes up the C5 admin edit menu on the page my block resides on (the upper left side menu, being "Exit Edit Mode" - "Properties" - "Design" - etc). As well I can't click on any areas to add any further blocks to them/alter existing blocks. This happens when I do the following sequence of actions:

Dashboard-> install custom block-> add custom block instance to Main area on home page-> back to Dashboard (before exiting edit mode/approving changes just made)-> then click "back to website" from Dashboard (without having done anything while there).

Is that a C5 bug, or just me doing improper js loading? On a side note, I started using auto.js instead and my block doesn't cause this issue, but I could use knowing how to load specific js files properly (that is, if this isn't a bug).

Help me Obi-Wan Kenobi, you're my only hope.

*cough*


p.s.
I'm using version 5.4.2.2 of concrete5

Landson
 
mkly replied on at Permalink Reply
mkly
Well it might be a bug, but addHeaderItem probably won't accomplish too much in the add method anyway.

Typically AFAIK when you want to do addHeaderItem you want to do it in the on_page_view method because this gets called before the rendering of the block.

EDIT: actually I don't even know if on_page_view gets called in add and edit mode. I think my brain is asleep today.

That said, anything included in the /js and /css folders should get included automatically without needing to call addHeaderItem i think.

EDIT AGAIN: Actually this isn't true in add or edit mode. Just ignore me today I think. Sorry.

I seem to remember @jordanlev saying something about using on_start or something else instead because on_page_view doesn't get called in one particular situation but I might be imagining things. I typically use on_page_view() I wish I could find that source code that had that comment. Maybe he'll pop his head in here and enlighten me (or call me crazy).

EDIT: I don't think you need the block root or the /css or /js root on the addHeaderItem calls because I think it checks those for the file.
jordanlev replied on at Permalink Reply
jordanlev
Did someone call my name? ;)

Here's the deal (as far as I understand it): the only way to consistently load javascript into the add/edit dialog is via the "auto.js" file, and the only way to consistently load css into the add/edit dialog is with inline css (yeah, I know). Sometimes, it seems that the view.js and view.css files (and the js files in the /js/ directory and the css files in they /css/ directory) get loaded for the edit dialog, but this is just a side-effect of them having been loaded when the page was viewed in edit mode, before the block was clicked on to bring up the edit dialog (and hence it doesn't come up for the "add" dialog if it's the first time the block type is added to a page and it doesn't work if the block is in the scrapbook).

By the time your block controller's add() or edit() functions are called, all header items have already been added by the system so adding more to the queue doesn't do anything (because the system is no longer taking those items and actually adding them to the header). This shouldn't be causing errors, though -- but I can think of two possibilities for why it might: 1) You have other js (in auto.js for example) that is assuming your header items were added and is just calling functions or referencing variables that were never actually loaded, or 2) using $this::BLOCK_ROOT looks kind of weird and may be causing issues if the controller wasn't instantiated in the way you think it would be*.

So... yeah, you need to cram everything as inline js or css in the add.php/edit.php file, or use the auto.js file. If you need to load an external js file that's not one already loaded by C5 in edit mode (e.g. not a jQuery UI component), you might try loading the external javascript from javascript itself using $.getScript() (seehttp://api.jquery.com/jQuery.getScript/... ).

Would be nice if what you want to do was easier. It's not technically a bug, but certainly something that would be nice if it existed in the future. If you log a bug report about it, come back and let us know so we can upvote it.

-Jordan

*PS: It's a moot point, but just for the sake of completeness, instead of $this::BLOCK_ROOT, you might want to use self::BLOCK_ROOT, or better yet something like this:
$bv = new BlockView();
$bv->setBlockObject($this->getBlockObject());
$blockURL = $bv->getBlockURL();
$html = Loader::helper('html');            
$this->addHeaderItem($html->javascript("{$blockURL}/something.js"));
mkly replied on at Permalink Reply
mkly
And this is why @jordanlev is the beast he is.

But since I have you... what was the comment with the on_page_view() not loading with stats or something. I can't remember or find it. It's going to keep me up at night.

EDIT: Part of my stoopid on this is that I am guilty of just loading inline css and js often on my add and edit blocks.
jordanlev replied on at Permalink Reply
jordanlev
Growl!

I only vaguely recall the details of the on_page_view -- I think it was that on_page_view() in single_pages was not called if page stats were turned off (or maybe it was the on_page_view event in your package controller?). But on_page_view() in blocks was always called no matter what. (And I think Mnkras fixed the single_page/event issue as of 5.4.2, so it's no longer a concern anyway).
Mnkras replied on at Permalink Reply
Mnkras
yea thats fixed
jordanlev replied on at Permalink Reply
jordanlev
And it's not stoopid to load js/css inline in add/edit -- this area of C5 is poorly implemented and poorly documented, so that's really the easiest way. And it's entirely pragmatic -- inline css may not be valid but it works in every browser. And since we're only talking about the edit dialogs, it means the user must have javascript enabled anyway and hence accessibility isn't a concern (I doubt the C5 editing interface is even remotely usable by someone with impaired vision).
mkly replied on at Permalink Reply
mkly
Are you really going to pragmatism into the context of the 2011 web? psh... (sarcasm)
jordanlev replied on at Permalink Reply
jordanlev
Well, I just looked at the code that loads auto.js, and all it's doing is calling a c5 javascript function (on the front-end) -- "ccm_addHeaderItem". So I think to load js or css in add/edit dialogs, your best bet is to put something like this at the top of your add.php or edit.php file:
<script type="text/javascript">
ccm_addHeaderItem('<?php echo $this->getBlockURL(); ?>/css/mystyles.css', 'CSS');
ccm_addHeaderItem('<?php echo $this->getBlockURL(); ?>/js/myjavascript.js', 'JAVASCRIPT');
</script>
Mnkras replied on at Permalink Reply
Mnkras
I might add support for auto.css, think thats a good idea? its a simple change
jordanlev replied on at Permalink Reply
jordanlev
Kind of makes sense as a good short-term solution. But eventually I think a larger change should be made (well, I actually think the whole API should be overhauled some time so that it's more consistent and concise). Something like having an "on_page_edit" method (that's passed a variable denoting whether it's an "add" or "edit" operation, in case that matters), or having "on_block_add" and "on_block_edit" methods. Also, the block URL should be more easily accessible from within the block controller -- calling $this->getBlockURL() should work without having to instantiate the BlockView object, etc.
But yeah in the meantime maybe it would make sense to have auto.css.
Landson replied on at Permalink Reply
Landson
Thanks for the reply guys! This is really good stuff, it'll definitely help me out!

@jordanlev thanks for the point on not using $this::BLOCK_ROOT. I hadn't been sure if that was the best way to go about that, but I'll definitely be considering switching over to one of the techniques you showed!