views:

793

answers:

5

Depending on which page I am, I would like the content of a javascript function to change.

Example :

MasterPage

<script type="text/javascript">
    Cufon.now();
    Cufon.replace('p#characters', { fontFamily: 'Helvetica95-Black' });
</script>

Page A

<script type="text/javascript">
    Cufon.now();
    Cufon.replace('p#characters', { fontFamily: 'Helvetica95-Black' });
    Cufon.replace('p#others', { fontFamily: 'Helvetica95-Black' });
</script>

Because I do not want to do code repetition, I'm looking to a solution. I thought that maybe I could use something like a ContentPlaceHolder like this (but it doesn't work) :

<script type="text/javascript">
    Cufon.now();
    Cufon.replace('p#characters', { fontFamily: 'Helvetica95-Black' });

    <asp:ContentPlaceHolder id="cphJS" runat="server" />
</script>

Any way to solve this kind of problem ?

UPDATE

What I will like to avoid is to have code like that :

// Add by MasterPage
<script type="text/javascript">
    Cufon.now();
    Cufon.replace('p#characters', { fontFamily: 'Helvetica95-Black' });
</script>

// Add by Page A
<script type="text/javascript">
    Cufon.now();
    Cufon.replace('p#others', { fontFamily: 'Helvetica95-Black' });
</script>

// Add by Page B
<script type="text/javascript">
    Cufon.now();
    Cufon.replace('p#main', { fontFamily: 'Helvetica95-Black' });
    Cufon.replace('p#menu', { fontFamily: 'Helvetica95-Black' });
</script>

Because that kind of code work but it's not the cleaning way of doing it. I would prefer to have something like that :

<script type="text/javascript">
    Cufon.now();        
    Cufon.replace('p#characters', { fontFamily: 'Helvetica95-Black' });
    Cufon.replace('p#others', { fontFamily: 'Helvetica95-Black' });
    Cufon.replace('p#main', { fontFamily: 'Helvetica95-Black' });
    Cufon.replace('p#menu', { fontFamily: 'Helvetica95-Black' });
</script>

The result is the same. I only find that the second output is cleaner.

+5  A: 

Why not simply add the additional code in a content place holder outside of the script tag?

So, you would have something like:

<head>
   <script type="text/javascript">
      // do some stuff
   </script>
   <asp:ContentPlaceHolder runat="server" id="someid" />
</head>
...

Or, you might collect functions in an array early in the page and then execute them later on like so:

In the <head>:

var callbacks = [];
function addCallback(arg) {
   callbacks.push(arg);
}

At some other location:

addCallback(function() {
   ...
});

And then at the bottom of the page, just before the </body>:

for (var i = 0; i < callbacks.length; i++) {
   var c = callbacks[i];
   if (c && c instanceof Function)
      c();
}

Could you provide more details about the requirements? Ex: What the above code is supposed to do, does it have to be executed all at once, does it depend on local variables that are created, does it have to run at a certain time, etc.

Edit: Using a content placeholder in a new MVC project seemed to work fine for me. Intellisense didn't pick it up but it rendered correctly. Here's what the code looks like for me.

In the master page:

...
<script type="text/javascript">
    var inTheMasterPage;
    <asp:ContentPlaceHolder runat="server" id="js1">
    </asp:ContentPlaceHolder>
</script>

...

In the page:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content runat="server" ContentPlaceHolderID="js1">
    var inThePage;
</asp:Content>
...

And the rendered HTML:

    <script type="text/javascript"> 
        var inTheMasterPage;

    var inThePage;

    </script> 
</head> 
Bryan Matthews
Can you made your example more specific to my problem. Because I'm not sure how addCallback(function()... is suppose to be implemented.
Melursus
It sounds like you're going for aesthetics, so that suggestion won't give you what you want anyway.
Bryan Matthews
+1  A: 

Ideally you need to accumulate these partial scripts and render them as one block at the end of the page

Not 100% sure how to do this in MVC but here is a an example for plain ASP.NET that you should be able to shoe horn into MVC

TFD
+2  A: 

You can use RegisterClientScriptBlock. Basically, this can create the script tags and code while giving you more server-side control. With that said, you'll need to communicate with the master page. You could expose a StringBuilder as a public property of the Master Page:

StringBuilder javascriptCode = new StringBuilder();
javascriptCode.Append("Cufon.now();" + System.Environment.NewLine);
javascriptCode.Append("Cufon.replace('p#characters', { fontFamily: 'Helvetica95-Black' });" + System.Environment.NewLine);
public StringBuilder JSCode
{
    get { return javascriptCode; }
}

In the content page you add a MasterType directive to get access to the Master object:

<%@ MasterType VirtualPath="~/virtualPath/nameOfMasterPage.page" %>

And in your content page you could append more JavaScript code and call RegisterClientScriptBlock:

Master.JSCode.Append("Cufon.replace('p#others', { fontFamily: 'Helvetica95-Black' });" + System.Environment.NewLine);
ClientScriptManager clientScript = Page.ClientScript;
clientScript.RegisterClientScriptBlock(this.Page.GetType(), "MadeUpNameForJSScript", Master.JSCode.ToString(), true);

I haven't tested this code so let me know if there's any problems with it. It may be a bit of an inconvenient method but it should combine all the JavaScript into one script block on the page.

Edit: I also don't know if this will work with MVC

Bob
RegisterClientScriptBlock requires a server form, which is never used in ASP.NET MVC.
Eilon
I like the logic you use but like Eilon says, RegisterClientScriptBlock can't be use...
Melursus
+1  A: 

One of the beauties of the selectors is that the object doesn't have to exist on the page. You can also supply multiple selectors to Cufon in one hit...

So if you put this in your master page it should just work...

<script type="text/javascript">
    Cufon.now();        
    Cufon('p#characters, p#others, p#main, p#menu', { fontFamily: 'Helvetica95-Black' });
</script>
Sohnee
+2  A: 

ContentPlaceHolder is a good idea you simply missplaced it also you can override them

in Master page

<asp:contentplaceholder id="scripts" runat="server" >
   <script type="text/javascript">
       Cufon.now();
       Cufon.replace('p#characters', { fontFamily: 'Helvetica95-Black' });
   </script>
</asp:contentplaceholder>

in page A

<asp:Content ID="scriptContent" ContentPlaceHolderID="scripts" runat="server">
   <script type="text/javascript">
       Cufon.now();
       Cufon.replace('p#characters', { fontFamily: 'Helvetica95-Black' });
       Cufon.replace('p#others', { fontFamily: 'Helvetica95-Black' });
   </script>
</asp:contentplaceholder>

the content from the page will override the content from the master page

if you want to append scripts then keep your content place holder in master page

<script type="text/javascript">
    Cufon.now();
    Cufon.replace('p#characters', { fontFamily: 'Helvetica95-Black' });

    <asp:ContentPlaceHolder id="cphJS" runat="server" />
</script>

in your page A don't put the script tags

<asp:Content ID="scriptContent" ContentPlaceHolderID="cphJS" runat="server">
        Cufon.replace('p#others', { fontFamily: 'Helvetica95-Black' });
</asp:contentplaceholder>
freddoo