Yii Framework Forum: Pure javascript in views - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Pure javascript in views Support embedding of pure javascript code in views Rate Topic: ***** 1 Votes

#1 User is offline   seb 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 240
  • Joined: 29-June 09

Posted 25 April 2012 - 05:44 AM

Now there is no standard good way to embed javascript snippets into views.
Usually these snippets are code that does job specific to each page, like register event handlers.
Yii supports this via CHtml helpers, for example CHtml::ajaxLink, but I never liked this approach, because very soon your view became a mix of HTML and php arrays.

From the first sight helpers seems to be easier way to do ajax requests, but when something doesn't work as expected it can be really hard to find the reason and solve problem
I think having pure JS code which does the same job is much better and for some time I used something like this:
//here view code, mostly HTML with php snippets to insert variables
//...
//...
//block with JS code
<?php
<?php
Yii::app()->clientScript->registerScript('settings-script', <<<EOD
    initForms('myform');
    $('.sel-image').live('click',function() {
        $('#preview img').attr('src', $(this).find('img').attr('src'));
        $(this).parent().addClass('active');;
        $(this).parent().siblings().removeClass('active');
        $('#SettingsData_stdImg').attr('value', $(this).attr('rel'));
        return false;
    });
EOD
);
?>


But this way JS code is embedded into the php string and you can forget about code highlight and completions.
So I started to search for better solutions.
One of approaches is to have separate folder where we have JS files for controllers / actions (similar structure to the 'views' folder) - http://weavora.com/b...ript-from-html/ and (in russian) - http://sergebezborod...framework.html.

I do not like this because js code now is too far from the view and what I want is just to be able to put js code into view (but at the same time I do not want it to be rendered in-place, but it should go into page head or end or jQuery 'ready' section).

I looked for solutions for Rails and found many advice like in this question.
For me this Rails solution can be implemented in Yii using clips. In the view file we do:
<?php //$this->beginClip('js-page-end'); ?>
<script type="text/javascript">
    alert('my script');
</script>
<?php //$this->endClip(); ?>


And then we render this clip in the layout:
//layout HTML
//...
//render clip with js, if there is no such clip then it will return empty string
<?php $this->renderClip('js-page-end'); ?>


Easy and good solution, but it will not work for the ajax requests where we use renderPartial and in this case layout is not rendered.

And, finally, the solution suggested by Tsunu.
He added a beginScript() and endScript() to the client script component, so code looks like this:
<?php $clientScript = Yii::app()->clientScript; ?>
<?php $clientScript->beginScript('my-script'); ?>
<script type="text/javascript">
    alert('my script');
</script>
<?php $clientScript->endScript(); ?>


There is a little hack here - CClientScript automatically wraps script into <script> tags, so in the endScript() Tsunu uses strip_tags($script) before register it using parent registerScript() method.

In conclusion - I think the last solution is close to ideal and it would be good to have support for this in the core CClientScript class.
3

#2 User is offline   bennouna 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,168
  • Joined: 05-January 12
  • Location:Morocco

Posted 25 April 2012 - 06:06 AM

Hello, there's something I'm missing here. I just jumped on to the thread you mention, and I still can't get it.

If you want just to embed JS code into your views, what prevents you from doing like this
<?php
    // some PHP code
    …
?>
<script type="text/javascript">
    alert('my script');
</script>
<?php
    // other PHP code
    …
?>


On the other hand, the following syntax allows specifying where to embed the JS (head, at the end of html elements, or on document ready):
<?php Yii::app()->clientScript->registerScript('script', <<<JS
    alert('my script');
JS
, CClientScript::POS_READY);?>


So imho, if you don't care about JS placement, just embed it straight like in the first case, otherwise, use Yii's registerScript method, whether you're waiting for document ready (DOM manipulation for instance), or just not to hold on the HTML parsing, or even for easier debugging (all JS code at the same places).

So, what am I missing? :unsure:
1

#3 User is offline   StasuSS 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 60
  • Joined: 20-February 12
  • Location:Kaluga, Russia

Posted 25 April 2012 - 07:23 AM

[quote name='seb' timestamp='1335350687' post='150283']
I think having pure JS code which does the same job is much better and for some time I used something like this:
//here view code, mostly HTML with php snippets to insert variables
//...
//...
//block with JS code
<?php
<?php
Yii::app()->clientScript->registerScript('settings-script', <<<EOD
    initForms('myform');
    $('.sel-image').live('click',function() {
        $('#preview img').attr('src', $(this).find('img').attr('src'));
        $(this).parent().addClass('active');;
        $(this).parent().siblings().removeClass('active');
        $('#SettingsData_stdImg').attr('value', $(this).attr('rel'));
        return false;
    });
EOD
);
?>


But this way JS code is embedded into the php string and you can forget about code highlight and completions.
So I started to search for better solutions.


so thi is why it is not acceptable for him..
Things are very seldom what they seem. In my experience, they’re usually a damn sight worse. (Inquisitor Titus Drake)
0

#4 User is offline   seb 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 240
  • Joined: 29-June 09

Posted 26 April 2012 - 01:31 AM

View Postbennouna, on 25 April 2012 - 06:06 AM, said:

Hello, there's something I'm missing here. I just jumped on to the thread you mention, and I still can't get it.

If you want just to embed JS code into your views, what prevents you from doing like this
<?php
    // some PHP code
    …
?>
<script type="text/javascript">
    alert('my script');
</script>
<?php
    // other PHP code
    …
?>


Yes, this works, but this way it will be hard to find pieces of JS inside the document. Also usually I wan to include script into the jQuery ready block (or other specific place), but not just anywhere.

View Postbennouna, on 25 April 2012 - 06:06 AM, said:

On the other hand, the following syntax allows specifying where to embed the JS (head, at the end of html elements, or on document ready):
<?php Yii::app()->clientScript->registerScript('script', <<<JS
    alert('my script');
JS
, CClientScript::POS_READY);?>

...

Yes, StasuSS is right - as I mentioned above that I used heredoc strings before, but this way you have php string instead of JS code and editors / IDEs can not recognize it.
0

#5 User is offline   bennouna 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,168
  • Joined: 05-January 12
  • Location:Morocco

Posted 26 April 2012 - 03:54 AM

View Postseb, on 26 April 2012 - 01:31 AM, said:

Yes, this works, but this way it will be hard to find pieces of JS inside the document. Also usually I wan to include script into the jQuery ready block (or other specific place), but not just anywhere.

Yes, that's the downside, and I generally don't do that.

Quote

Yes, StasuSS is right - as I mentioned above that I used heredoc strings before, but this way you have php string instead of JS code and editors / IDEs can not recognize it.

Yes in fact with the present way of doing it, we can only have either advantage: code completion or correct JS/jQuery handling :lol:
For the moment, I'm just happy that my IDE matches braces inside heredoc strings :D

Bottom line: +1 for the feature request :)

Quote

I do not like this because js code now is too far from the view and what I want is just to be able to put js code into view (but at the same time I do not want it to be rendered in-place, but it should go into page head or end or jQuery 'ready' section).

PS I guess I've read your message way too fast, you haven't used coreScriptPosition property, so I thought that you didn't care about putting your script in $(document).ready(), while at the same time you said it in your explanation
0

#6 User is offline   samdark 

  • Having fun
  • Yii
  • Group: Yii Dev Team
  • Posts: 3,788
  • Joined: 17-January 09
  • Location:Russia

Posted 26 April 2012 - 10:30 AM

FYI, PhpStorm works fine with JavaScript in PHP strings/heredoc.
Yii 1.1 Application Development Cookbook

Enjoying Yii? Star us at github: 1.1 and 2.0.
0

#7 User is offline   seb 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 240
  • Joined: 29-June 09

Posted 26 April 2012 - 11:01 AM

View Postsamdark, on 26 April 2012 - 10:30 AM, said:

FYI, PhpStorm works fine with JavaScript in PHP strings/heredoc.

Yes, but others don't. I have vim for editing and Netbeans for debugging. Maybe vim can be tuned to highlight js in strings, but Netbeans not.
Also it is not difficult to write own CClientScript subclass to support this.
But I believe that Yii core should support this and more then that - advertise this approach somehow through the docs.

Maybe my feature request looks too narrow, but I mentioned this in other Yii 2 discussion topics - in would be good to review the approach to support JS code and AJAX requests.
For example, look here (tutorial for rails 3):

Quote

Up until version 3, Ruby on Rails generated obtrusive JavaScript. The resulting code wasn’t clean, but even worse, it was tightly coupled to the Prototype JavaScript framework. This meant that unless you created a plugin or hacked Rails, you had to use the Prototype library with Rail’s JavaScript helper methods.

Replace the "Ruby on Rails" with "Yii" and "Prototype" with "jQuery" and here is the description of current situation with JS code in Yii.
0

#8 User is offline   FelikZ 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 2
  • Joined: 20-April 12

Posted 26 December 2012 - 03:44 AM

So what in conclusion?
I've mentioned to use this solution:

<?php Yii::app()->clientScript->registerScript('script', <<<JS
    alert('my script');
JS
, CClientScript::POS_READY);?>


but its realy dirty, IMHO. Does any body found better at all?
0

#9 User is offline   seb 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 240
  • Joined: 29-June 09

Posted 26 December 2012 - 07:15 AM

View PostFelikZ, on 26 December 2012 - 03:44 AM, said:

but its realy dirty, IMHO. Does any body found better at all?


Yes, see the last solution in my first post:

Quote

And, finally, the solution suggested by Tsunu.
He added a beginScript() and endScript() to the client script component, so code looks like this:
<?php $clientScript = Yii::app()->clientScript; ?>
<?php $clientScript->beginScript('my-script'); ?>
<script type="text/javascript">
    alert('my script');
</script>
<?php $clientScript->endScript(); ?>



So you can have pure js code blocks inside the view file.
To make this work you need to extend CClientScript as described in this forum post.
I currently use a bit modified code:

class AppClientScript extends CClientScript {

    protected $activeScriptId;
    protected $activeScriptPosition;

    public function beginScript($id, $pos = parent::POS_READY) {

        $this->activeScriptId = $id;
        $this->activeScriptPosition = $pos;

        ob_start();
        ob_implicit_flush(false);
    }

    public function endScript() {

        $script = ob_get_clean();
        $script = strip_tags($script, '<p><a><br><span><div><b><i><strong>');
        parent::registerScript($this->activeScriptId, $script, $this->activeScriptPosition);

    }
}

1

#10 User is offline   SpikyJT 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 5
  • Joined: 16-November 10

Posted 26 February 2013 - 11:05 AM

This is a great idea, but strip_tags() is too restrictive, as it removes any tags you may use in your jQuery DOM manipulation. The answer above improves this, but is not complete. Since strip_tags() uses a whitelist, it is not really practical. It think preg_replace() will be more appropriate. Like this:
preg_replace( '%</?script[^>]*>\s*%', '', $script )

0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users