Justin has posted 7 posts at DZone. You can read more from them at their website. View Full User Profile

Silverlighting Your PHP: Adding Silverlight With Nothing But Notepad

03.22.2010
| 17549 views |
  • submit to reddit

Unless you’re using Visual Studio .NET and/or Microsoft Expression Studio, you may think Silverlight has nothing to offer you. And realistically speaking, your options are limited. But as a PHP developer, you’ll be surprised at what you can get away with using just the right syntax in just the right place. It may take a little trial and error, but you can Silverlight your PHP app, adding some elegant bells and whistles, without ever cracking open a Microsoft IDE.

In this walkthrough, you’ll put into play a very simple Silverlight app that combines PHP with XAML and javascript – not a lick of .NET code in sight. This should give you a taste of the potential of Silverlight. You’ll start with a simple PHP menu, delivered in vintage header style. Next, you’ll create a Hello, World type of Silverlight app using your favorite text editor. Once that’s working, you’ll smash the two together to generate some Silverlight on the fly, finishing up with a touch of animation to make it more interesting.

 

Step 1: Classic PHP Menu

Just to have something to work with, you’re going to create a faux-dynamic menu. For the purposes of this walkthrough, you’ll use a simple array instead of creating a content database.

Create a page called PHPMenu.php:

<html>
<head>
<title>Silverlight PHP Menu</title>
<style type="text/css">
.navMenu {
height: 300px;
width: 400px;
}
</style>
</head>

<body>
<p>Just PHP:</p>
<div id="navMenuPlain" class="navMenu">
<?

// This is where you would do a fetch
$menu=array('Home','Links','About','Contact');

$n = 0;
foreach ($menu as $m) {
$n++;
echo('<h2>' . $m . '</h2>');
}
?>
</div>
</body>
</html>

 

Run this and you should see something like Figure 1.

Step 2: Hello, Silverlight!

Now, jump tracks for a few minutes and create a basic Silverlight app. If and when you begin using some of the tooling for Silverlight, such as Expression Studio and Visual Studio .NET, you’ll discover several things:

  • Creating a new project will automatically create the entire working directory structure for you, complete with executable code.
  • You’ll be able to publish that project to a variety of destinations, including locally, and have the production directory structure also created for you automatically.
  • Neither the project files nor the directory structures look ANYTHING like what you’re about to create.

About that last point: the most recent versions of Visual Studio and Silverlight have moved to an entirely different format than when they started. For instance, projects now include all necessary code and assemblies bundled up into .xap files for performance and ease of deployment. Fortunately, an older technique for creating Silverlight projects still works and comes in very handy for the type of project you’re going to create here.

Ultimately, you really only need four files to create a Silverlight app:

  • Silverlight.js – A helper file for creating the Silverlight component. This is created automatically any time you start a new Silverlight project. A current version can be found here [link to Silverlight.js]. 
  • Landing Page – The page which holds the Silverlight object. In a moment, this will be PHPMenu.php.
  • Javascript Page – This could be included in the landing page but more convenient as a separate file.
  • XAML File – This is what gets interpreted by the Silverlight plugin. Usually this is created by Expression Blend,Visual Studio, or any number of 3rd party apps coming to market. For this demo, you’ll create it by hand, via PHP. And that’s the key to Silverlighting your PHP – this doesn’t have to be an actual .xaml file, as long as the result is proper XAML syntax.

 

Start with the landing page. In Step 3 you’ll combine this code with PHPMenu.php, but for now create a file called HelloSilverlight.htm:

<html>
<head>
<title>Silverlight PHP Menu</title>
<script type="text/javascript" src="Silverlight.js"></script>
<script type="text/javascript" src="xamlFunctions.js"></script>
</head>
<body>
<p>Silverlighted PHP:</p>
<div id="navMenuSL" class="navMenu">
<script type="text/javascript">
createNavMenu();
</script>
</div>
</body>
</html>

 

Next, create the javascript. This will detect the Silverlight plugin and create a delegate, then create the Silverlight object that goes in the .htm file. You could, of course, also do all this directly in the html page you just created. Call this file xamlFunctions.js:

function createNavMenu()
{
Silverlight.createObjectEx({
source: "hello.xaml",
parentElement: document.getElementById("navMenuSL"),
id: "slNavMeu",
properties: {
width: "100%",
height: "100%",
inplaceInstallPrompt:true,
version: "3.0"
}
});
}

if (!window.Silverlight)
window.Silverlight = {};

Silverlight.createDelegate = function(instance, method) {
return function() {
return method.apply(instance, arguments);
}
}

 

Lastly, create your XAML file, referenced in the above code as “source”. In a moment, this will be turned into a PHP file to facilitate serving up some dynamic menu options. Also, as mentioned, this code is usually created using a design tool. XAML is notoriously tricky to hand-code. Not only is debugging difficult (if you get something wrong, the result is a blank space where your XAML goes), but not all of the available controls can be used the way you’re using them here. Many controls, especially those added with version 3 and now 4, currently in beta, require assemblies to instantiate. But hopefully this example will give you a solid foundation from which to build something more complex. Call this file hello.xaml:

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="navMenu_Grid">
<Canvas HorizontalAlignment="Left" Margin="0,0,0,0" Width="300" Height="400" VerticalAlignment="Top">
<Rectangle x:Name="Rect0" Fill="#FF5A2191" Height="40" Canvas.Left="20" RadiusY="15" RadiusX="15" Opacity=".5" Stroke="Black" Canvas.Top="0" Width="150" >
</Rectangle>
<TextBlock Foreground="#FFF7F1F1" Canvas.Top="10" Canvas.Left="45" Text="Hello, Silverlight!" />
</Canvas>
</Grid>

 

A few things to note about this code:

  • Nesting: Silverlight uses a variety of containers, such as Grid, Canvas, and StackPanel. You can find a description of all these elsewhere on this site and on MSDN. A good reason to use Canvas is when you want to use some…
  • Layering: Because the Rectangle control doesn’t have a Text attribute, you’ll need to create a separate TextBlock and set their respective Canvas.Top attributes so that they’re aligned correctly. The order that controls are nested on the canvas is the order they’ll appear on the page.
  • Opacity: The Opacity of a control is a value of type double ranging from 0 to 1. Here the opacity is set at 50%, or .5, to create a dimmed control.
  • RadiusX/Y: Here’s where XAML gets interesting. Simply by changing the Radius attributes, you can round the corners of the rectangle. Since these attributes can be set through javascript, you can potentially change them dynamically.

Tap your new HelloSilverlight.htm page. (Did you remember to put your Silverlight.js in the same directory?) You should see something like Figure 2.

Before you move on to Step 3, make one small tweak to your XAML file. This is where the power of Silverlight starts to rear its beautiful head. By adding three lines of code, you can give your control a nice dropshadow effect that would otherwise take miles of coding or static art to accomplish. And this doesn’t even touch on the many properties available to tinker with.

Between your <Rectangle></Rectangle> tags, add the following:

<Rectangle.Effect>
<DropShadowEffect/>
</Rectangle.Effect> 

 

Here’s the result:

 

Note that this effect, like all others, is fully configurable: DropShadowEffect Class.

 

Step 3: Bringing Two Great Tastes Together

Now that you have a working example of both PHP and Silverlight, it’s time to bring them together.

Start with your landing page.  Bringing the content of HelloSilverlight.htm into PHPMenu.php should result in the following:

<html>
<head>
<title>Silverlight PHP Menu</title>
<script type="text/javascript" src="Silverlight.js"></script>
<script type="text/javascript" src="xamlFunctions.js"></script>
<style type="text/css">
.navMenu {
height: 300px;
width: 400px;
}
</style>
</head>
<body>
<p>Just PHP:</p>
<div id="navMenuPlain" class="navMenu">
<?
// This is where you would do a fetch
$menu=array('Home','Links','About','Contact');

$n = 0;

foreach ($menu as $m) {

$n++;
echo('<h2>' . $m . '</h2>');
}

?>
</div>
<p>Silverlighted PHP:</p>
<div id="navMenuSL" class="navMenu">
<script type="text/javascript">
createNavMenu();
</script>
</div>
</body>
</html>

 

Next, in your xamlFunctions.js file, you’ll make one small change: replace “hello.xaml” with “createMenu.php”. As mentioned, your XAML source doesn’t need to be a .xaml file. Handy, that.

Now create a new file called createMenu.php:

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="navMenu_Grid">

<Canvas HorizontalAlignment="Left" Margin="0,0,0,0" Width="300" Height="400" VerticalAlignment="Top">

<?

//Database fetch goes here
$menu=array('Home','Links','About','Contact');
$n = 0;

foreach ($menu as $m) {

echo('<Rectangle x:Name="Rect' . $n . '" Fill="#FF5A2191" Height="40" Canvas.Left="20" RadiusY="15" RadiusX="15" Opacity=".5" Stroke="Black" Canvas.Top="' . ($n * 40) . '" Width="150" MouseEnter="mouseEntered" MouseLeave="mouseLeft">');

echo('<Rectangle.Effect><DropShadowEffect/></Rectangle.Effect>');
echo('</Rectangle>');
echo('<TextBlock Foreground="#FFF7F1F1" Canvas.Top="' . (($n * 40) +10) . '" Canvas.Left="45" Text="' . $m . '" />');

$n ++;

}
?>

</Canvas>

</Grid>

 

As you can see, this is essentially identical to hello.xaml, with some obvious exceptions. Rather than a single control, you’re iterating through your dynamic list, in this case just an array. Add a little counter to handle positioning, and you have a vertical column of rounded rectangles, with menu text layered over the top.

You might have also noticed the addition of “MouseEnter” and “MouseLeave” events. Those will come into play shortly, literally.

Navigate to PHPMenu.php and behold the result. You should see something like Figure 4.




And that alone is worth the price of admission. From mid-90s style navigation menu to late-90s style buttons. Vintage delicious, but all created dynamically, through XAML and Silverlight. And more importantly, all highly controllable, with properties that can be set on the fly or changed through javascript.

But what would classic buttons be without a classic rollover effect? Read on…

 

Step 4: Adding Animation

One clever aspect of XAML is the ability for developers to add resources to a layer of the nest, particularly Storyboards. In Silverlight, animation is handled by assigning a range of values, via a Storyboard, to a particular property of a particular control. By naming and targeting specific properties, you can do things like change the opacity of the control, blend its color from one shade to another, even move the control.

Unfortunately, this too takes a good bit of trial and error, as some properties don’t animate as one might expect. For example, Silverlight.net’s Quickstarts include some great starter samples for animating various parts of a canvas, including changing the color of the canvas itself: http://www.silverlight.net/learn/quickstarts/animations/. However, applying the same color-shifting technique to, say, a rectangle requires some redonkulous coding gymnastics that seem counter-intuitive, even with the full resources of an IDE like Visual Studio.

That said, you can still accomplish some nice effects even with a bare-bones app like this one. To get started, open up createMenu.php and add the following below the opening <Canvas> tag and above the PHP script:

<Canvas.Resources>
<Storyboard x:Name="fadeIn">
<DoubleAnimation x:Name="fadeInDouble" Storyboard.TargetProperty="Opacity" Storyboard. Storyboard.TargetName="Rect1" To="1" Duration="0:0:1" />
</Storyboard>
<Storyboard x:Name="fadeOut">
<DoubleAnimation x:Name="fadeOutDouble" Storyboard.TargetProperty="Opacity" Storyboard. Storyboard.TargetName="Rect1" To=".5" Duration="0:0:1" />
</Storyboard>
</Canvas.Resources>

 

A few notes about this code:

Notice that the container is Canvas.Resources. Storyboards are considered a resource for whatever container they’re located in. For example, if this was a StackPanel, you would use StackPanel.Resources.

The Storyboard should be named, so it can be referred to by the calling routine.

Within the Storyboard, the actual animation is based on the value type of the parameter being changed. This example will change the Opacity of the Rectangle. Opacity, as you’ll recall, is of type double, hence “DoubleAnimation”. In addition, the animation itself should be named, as it will also be referred to later.

Within the animation, you have a TargetProperty, in this case “Opacity”, and a TargetName, referring to the owner of that property. For now, this is hard-coded to “Rect1”.

You can use both “To” and “From” to establish the range of the effect. For example, going From “.5” To “1” would cause the control to go from half-opaque to fully solid. Usually you’ll want to set both ends of the range. But in this case, eliminating the From end of the range allows for a smoother rollover effect since these parameters default to their current values. In other words, if you start the MouseEnter animation and get to .75 opacity, then move away, the MouseLeave animation will start at .75 and go to .5.

You can also set the Duration of the animation, using H:M:S format. In this case, the animations are set to last 1 second.

Once the animations are defined, you still need to trigger them. So open your xamlFunctions.js file and add the following to the bottom:

function mouseEntered(sender, mouseEventArgs)
{
sender.findName("fadeIn").Begin();
}

function mouseLeft(sender, mouseEventArgs)
{
sender.findName("fadeOut").Begin();
}

 

As you can see, this finds the specified Storyboard and begins ALL animations within that Storyboard.

Reload PHPMenu.php and try rolling over your purple buttons. You should see some smooth fading in and out. Except, small problem, it’s only happening on one button, “Rect1”, i.e. “Links”. Not very helpful.

There was a time when this was about as good as it got. To do more, you’d need to create an animation for each control. Fortunately, Microsoft added a few tweaks to the Silverlight engine to allow parameters to be more easily referenced within javascript.

Replace the javascript you just added with the following:

 

function mouseEntered(sender, mouseEventArgs)
{
sender.findName("fadeIn").Stop();
sender.findName("fadeInDouble")["Storyboard.TargetName"] = sender.Name;
sender.findName("fadeIn").Begin();
}

function mouseLeft(sender, mouseEventArgs)
{
sender.findName("fadeOut").Stop();
sender.findName("fadeOutDouble")["Storyboard.TargetName"] = sender.Name;
sender.findName("fadeOut").Begin();
}

 

Two important points here:

  • Before assigning the animation to a new target, you need to stop it on the current one.
  • The TargetName is a child of the animation, not a child of the Storyboard. Once the animation is assigned to a new target, you can Begin the Storyboard again.

Try running PHPMenu.php. You should see some nice rollover animations, with smooth gradations from half-opacity to solid. Way better than _on and _off versions of your gifs.

You can see a demo of this code here: http://www.justinwhitney.com/silverlight1/PHPMenu.php

What you’ve just done is chisel a small ice cube from the tip of a very large iceberg. Using four basic files, you’ve generated a dynamic menu on the fly and added some simple but elegant rollover effects. Keep in mind that everything you just created is adjustable through parameters: the type of control, its dimensions, color, dropshadow, shape and direction of the dropshadow, behavior.

By combining XAML and javascript, you were able to add a splash of Silverlight to your PHP app, without using any additional development tools than what you’ve been using all along. As this series continues, you’ll get the chance to bump it up several notches with some free downloads. Then you’ll begin to see what Silverlight can really do for your PHP apps.

AttachmentSize
Figure1.png17.2 KB
Figure2.png13.76 KB
Figure3.png14.6 KB
Figure4.png25.95 KB
JustPHP.png23.83 KB
SilverlightedPHP.png24.22 KB
Published at DZone with permission of its author, Justin Whitney.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Craig McWherter replied on Mon, 2010/04/12 - 1:36pm

Visual Studio Express comes with all the tools you need to write Silverlight apps. Oh, and it's free ... http://www.microsoft.com/express/Web/

Venkata Kiran replied on Thu, 2010/10/07 - 3:17am

Hi Justin,

    I need some help regarding the silverlight with php.

    How can i add Button, Combobox silverlight controls in php(as you spcified way)?

 

    Thanks,

    Kiran

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.