Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inline scripts #36

Closed
fisharebest opened this issue Sep 23, 2014 · 15 comments
Closed

Inline scripts #36

fisharebest opened this issue Sep 23, 2014 · 15 comments

Comments

@fisharebest
Copy link
Contributor

As well as external resources (files), it is often useful to manage inline resouces (scripts) at the same time.

For example, ZendFramework offers this feature via its headScript->appendScript() and headScript->appendFile() methods. I have coded something similar in many projects.

Translated to stolz/assets, it would look something like this:

/* load the libraries */
Asset::addJs('jquery.js');
Asset::addJs('jquery.widget.js');
/* use the libraries */
Asset::addInlineJs('jQuery("#abc").widget();');

When you come to render the data, you would get this:

<script src="asset-pipeline.js"></script>
<script>jQuery("#abc").widget();</script>

We collect the inline scripts, and render them after the external scripts.

Does this sort of feature have a place in this project?

@Stolz
Copy link
Owner

Stolz commented Sep 24, 2014

@fisharebest I have no plan to include such feature as it would need a heavy modification of the code. May be for the future when I refactor the code to be more object oriented instead of a bunch of array functions :/

@Stolz Stolz closed this as completed Sep 24, 2014
@fisharebest
Copy link
Contributor Author

it would need a heavy modification of the code

FYI, this is how I achieve it.

class Assets extends \Stolz\Assets\Manager {
    protected $inline_js = '';

    public function addInlineJs($js) {
        $this->inline_js .= '<script>' . $js . '</script>';
    }

    public function js($attributes = null) {
        return parent::js($attributes) . $this->inline_js;
    }

    public function resetJs() {
        parent::resetJs();
        $this->inline_js = '';
    }
}

@Stolz
Copy link
Owner

Stolz commented Sep 25, 2014

Well, when I said it would involve a heavy modification of the code I had in mind integrating the inline scripts with the javascript assets workflow (respecting the "First In First Out' policy, don't duplicate assets, pipeline support, dependencies, etc...).

Your approach is much simpler, defining a different flow for inline JS assets, independent from normal JS assets. In that case it may have a place. I'll look into it.

Just one quick note, in order to preserve original function signature you better change last function to

public function resetJs() {
    $this->inline_js = '';
    return parent::resetJs();
}

@fisharebest
Copy link
Contributor Author

In that case it may have a place. I'll look into it.

As I said originally, I have been using this technique which I picked up from the Zend Framework.

However, I've been re-examining exactly how I've been using it - and pretty much everything I'm doing could be implemented more cleanly using better markup and static scripts.

So, if you were looking into it, there is no need ;-)

@hotrush
Copy link

hotrush commented Oct 28, 2014

+1

@erickmonteiro
Copy link

Hello, in laravel 5 where I put the code?

thank you in advance

class Assets extends \Stolz\Assets\Manager {
protected $inline_js = '';

public function addInlineJs($js) {
    $this->inline_js .= '<script>' . $js . '</script>';
}

public function js($attributes = null) {
    return parent::js($attributes) . $this->inline_js;
}

public function resetJs() {
$this->inline_js = '';
return parent::resetJs();
}

}

@Stolz
Copy link
Owner

Stolz commented Mar 18, 2015

@erickmonteiro, you can put it anywhere you want as long as the place is listed in your composer.json autoload section and you use the right namespace .

Since in L5 the app directory is autoloaded with psr-4 you could put it in app/Assets/ directory and use the App\Assets namespace.

If you still want to use the Assets facade with your new functionality then you will need to use a custom service provider. You can extend the official one and change the 'stolz.assets' binding to return an instance of your class i.e.:

return new \App\Assets\Manager($app['config']['assets']);

@judgej
Copy link

judgej commented Mar 21, 2015

Is this something incorporated into the library yet, or do we still need to extend it as shown here? Being able to mix file and URL-based assets with in-line JS is an incredibly usefult feature, and a must-have for my general use (how other's mileage varies, I don't know).

@hotrush
Copy link

hotrush commented Mar 21, 2015

@judgej I do this via View::composer

@judgej
Copy link

judgej commented Mar 21, 2015

@hotrush what part of the problem does the View::composer solve? It sounds interesting, but so far as I can see, it is a technique that avoids the need to fetch a value in a controller (or a parent view) and explicitly pass it into a view. I'm guessing it is how the $errors collection is always available in all views, all the time. Presumably you have something that collects inline JS from various places, and makes it available for binding to some or other view?

@hotrush
Copy link

hotrush commented Mar 22, 2015

@judgej in my case i need to pass some data from php to javascript (but it can be modified as you want).
Here an example:
In my BaseController i have next:

/**
 * Data that will be forward to layout as js variables
 * Key => Value array
 * Array to json convert manually
 * @var array
 */
protected $scriptComposer = array();

in setupLayout() method of this controller i have

// inject inline script into layout
View::composer('script-composer', function($view) {
    $view->with('scriptComposer', $this->scriptComposer);
});

in layout view

@include('script-composer')
{{ Assets::js() }}

script composer view (it may bind key->value data, but can be modified for your purposes)

@if(isset($scriptComposer) && !empty($scriptComposer))
<script type="text/javascript">
    @foreach($scriptComposer as $key=>$value)
        var {{ $key }} = {{ $value }};
    @endforeach
</script>
@endif

and in controllers method i do next

$this->scriptComposer['userID'] = 123;

@judgej
Copy link

judgej commented Mar 22, 2015

Thanks, that makes sense. So here the controllers throw together key/value data, and the View::composer is used to make sure that key/value data is available to any JS running on the page. Your static JS assets then know what data to look for, and how to use it.

I think I would want to pass in fragments of JS too - more than just variables - and some of those fragments would come from sub-views within the page, but this would certainly work for that too.

Edit: sorry if this is turning into a support forum thread - wasn't my intention and I'll stop now :-)

@Nuranto
Copy link

Nuranto commented Jun 30, 2018

+1

With a little modification :

Translated to stolz/assets, it would look something like this:

/* load the libraries */
Asset::addJs('jquery.js');
Asset::addJs('jquery.widget.js');
/* use the libraries */
Asset::addInlineJs('jQuery("#abc").widget();');

When you come to render the data, you would get this:

<script src="asset-pipeline.js"></script>

with jQuery("#abc").widget(); at the end of asset-pipeline.js file, minified

@Stolz
Copy link
Owner

Stolz commented Jul 9, 2018

@Nuranto please take a look at Laravel Blade stacks. They allow you to accomplish the inline assets feature very easily.

https://laravel.com/docs/5.6/blade#stacks

@Nuranto
Copy link

Nuranto commented Jul 11, 2018

Yes, I'm using that already.
But merging and minifying it at the end of the pipeline would be better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants