C5-8.4.0 How to use page attributes in package without installing a block?

Permalink
I want to add a page attribute within a package and then use that attribute in various pages to load some JS if the attribute is selected.

I know I can make a block to work with that attribute. But this block will have to be added to each page AND I'll have to set the attribute on that each page anyway.

Is there any functionality in concrete5 where I can programmatically work with the attribute on a global basis from the package without the need to install blocks?

Is a Dashboard single page the right choice? How can I load JS based on that page's value on a global basis from the package throughout the whole site?

linuxoid
 
Gondwana replied on at Permalink Reply
Gondwana
There's probably an event you can hook.
linuxoid replied on at Permalink Reply
linuxoid
As I clarified above and below, the JS has to load on pages or whole site.

Would the 'on_page_view' event be suitable for the page logic? I wouldn't know what page and what type of page is viewed, but as long as the attribute is present on any page I need to load the JS.

For the whole site I guess I can use the 'on_start' event.

How can I load the JS? As a *js file in the footer with addFooterItem?
hutman replied on at Permalink Reply
hutman
You could do it in your theme header, just do

$c = \Page::getCurrentPage();
if($c->getAttribute('attribute_handle')){
//include the script tag
}
linuxoid replied on at Permalink Reply
linuxoid
Sorry, I wasn't clear, I've updated the original post to make it clearer. I need to install a custom page attribute from a package (I know how to) and then to enable/disable a JS (somewhere, where?) from the package on certain pages or the whole site based on the value of the attribute. All from the package without a block. Is it possible?
mnakalay replied on at Permalink Best Answer Reply
mnakalay
on_page_view will work. Once the even triggers you get the view like this
$v = \View::getInstance();

And then you can load your stuff either by requiring assets or adding it to the header/footer
if (is_object($v)) {
    $v->requireAsset('javascript', 'yourscriptname');
    // OR
    $v->addFootererItem('yourscript);
}

To check for your attribute, once the event triggers you just do the usual
$page = Page::getCurrentPage();
if ($page && is_object($page) && !$page->isError()) {
    $yourAttrValue = $page->getAttribute('your_attr_handle');
}
linuxoid replied on at Permalink Reply
linuxoid
I may be missing something here. The following in the package controller doesn't work:
public function on_start()
   {
        $js = 
        '<script>
        $(document).ready(function(){
            ConcreteAlert.error({
                title: "Hello"
            });
        });
        </script>';
        Events::addListener('on_page_view', function () {
            $v = \View::getInstance();
            if (is_object($v)) {$v->addFooterItem($js);
                $page = Page::getCurrentPage();
                if ($page && is_object($page) && !$page->isError()) {

'on_before_render' doesn't work either.
JohntheFish replied on at Permalink Reply
JohntheFish
Put a few die(__LINE__); in through the code and remove them until you find out at which stage it doesn't work.

Or use a debugger and breakpoints to trace it.
linuxoid replied on at Permalink Reply
linuxoid
2 problems:

1. It failed this:
if (is_object($dc)) {

2. And the $js was not visible to the event function.

I removed the check, moved the variable inside the event and now this works:
public function on_start()
{
        Events::addListener('on_page_view', function () {
            $js = 
            '<script>
            $(document).ready(function(){
                ConcreteAlert.error({
                    title: "Copy disabled"
                });
            });
            </script>';
            $v = \View::getInstance();
            if (is_object($v)) {
                $page = Page::getCurrentPage();
                if ($page && is_object($page) && !$page->isError()) {

So that's a global set up, it adds the JS for the whole site, even the Dashboard. How can I
- load the JS only for that page which has been loaded?
- load the JS only for the user side excluding the Dashboard?
mnakalay replied on at Permalink Reply
mnakalay
you can use
$page->isAdminArea()

to check whether it's an admin page or not.

As for the attribute, since you're using a checkbox most likely you can just do
$attr = $page->getAttribute('your_handle');
if (!empty($attr)) {
    // do something
}
linuxoid replied on at Permalink Reply
linuxoid
Thank you very much, you help a lot!

I got that with the admin page check. I didn't know I could do that. I'll try that.

But what about enabling the JS only for the page which has it, not the whole site? Because once you add the footer in the package, it stick throughout. Maybe there's another event more suitable for that?
mnakalay replied on at Permalink Reply
mnakalay
I have packages using this technique and the js is only added when the attribute has the value I want. In your code it's not the case, you are adding the js to the footer no matter what.

Now if you're thinking about a caching issue, maybe put your code in a js file and register it as an asset and require it when the attribute has the proper value.
linuxoid replied on at Permalink Reply
linuxoid
You rock! Thanks a lot for your help. Your suggestion worked.
I'm going to release a package with that soon.
mnakalay replied on at Permalink Reply
mnakalay
We guessed as much ;-)