Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7019 Articles
article-image-integrating-yahoo-user-interface-library-yui-moodle
Packt
13 May 2011
6 min read
Save for later

Integrating Yahoo! User Interface Library (YUI) with Moodle

Packt
13 May 2011
6 min read
  Moodle JavaScript Cookbook Over 50 recipes for making your Moodle system more dynamic and responsive with JavaScript In this article, we will cover: Initializing the YUI 3 library Loading YUI 3 modules Loading YUI 2 modules from YUI 3 Attaching basic event handlers Attaching advanced DOM event handlers Implementing Event Delegation Debugging with the YUI console Introduction There are a lot of common tasks that need to be performed when writing JavaScript. A large proportion of this simply involves dealing with differences between web browsers. The need for a way to hide or abstract the specifics of each browser into a standard interface gave rise to sets of tools known as JavaScript libraries. One of the leading libraries in use on the web today is the Yahoo! User Interface Library (YUI). Moodle includes a copy of the YUI as its preferred JavaScript library. YUI provides developers with access to a wide range of tools for enhancing their web applications: The YUI Library is a set of utilities and controls, written with JavaScript and CSS, for building richly interactive web applications using techniques such as DOM scripting, DHTML and AJAX. YUI is available under a BSD license and is free for all uses. YUI is proven, scalable, fast, and robust. Built by frontend engineers at Yahoo! and contributors from around the world, it's an industrial-strength JavaScript library for professionals who love JavaScript. Yahoo! Developer Network http://developer.yahoo.com/yui/ In this article, we will learn the basics of working with YUI. We will learn how to initialize the YUI and make it ready for use within our code and load additional modules from versions 2 and 3 of the YUI. We will also learn how to manage the execution of code by attaching events to our controls, and finally how to debug our code with YUI logging tools. Initializing the YUI 3 library In this recipe, we will learn how to initialize the YUI 3 environment within Moodle, which will get us ready to start using YUI 3 features. Moodle takes care of most of the initial setup, namely loading the required CSS and JavaScript files, so all we need to be concerned with is activating the YUI environment. This example will show how to execute JavaScript code from within the YUI environment. We will set up a small YUI script which will simply display a message including the version number of the active YUI environment in a JavaScript alert box. This provides a simple view of what is required to get YUI up and running that we will build on further in the subsequent recipes. Getting ready We begin by setting up a new PHP file yui_init.php in the cook directory with the following content: <?php require_once(dirname(__FILE__) . '/../config.php'); $PAGE->set_context(get_context_instance(CONTEXT_SYSTEM)); $PAGE->set_url('/cook/yui_init.php'); $PAGE->requires->js('/cook/yui_init.js'); echo $OUTPUT->header(); echo $OUTPUT->footer(); ?> Notice that the preceding code references a JavaScript file yui_init.js, which has the following content: YUI().use ( function(Y) { alert('Hello from YUI ' + Y.version); } ); How to do it... We have created a PHP file that sets up a Moodle programming environment and includes a JavaScript file, in a way now familiar to us from previous recipes. What is new here is the content of the JavaScript file, which is where we will make ready the YUI 3 environment. Moodle has already included all the JavaScript files required for YUI (this happened when we output the value returned from $OUTPUT->header();). This means we now have a global object named YUI available within our JavaScript code. We create a new instance of the YUI object with the statement YUI() and then immediately call the use method. The only parameter we will pass to the use method is an anonymous function. This is just like a regular JavaScript function, except that it has no name specified; hence it is "anonymous". A name is not required, as it is not referred to again, but it is simply passed directly to the use method. This function itself accepts a single input parameter Y, which will be a reference to the new instance of the YUI object. (Note that the use method is also used to load additional YUI modules; this is the subject of the next recipe.) The anonymous function just created is the most important part of the code to take note of as this is where we will be putting our entire code that will be making use of the YUI features. In this example, you can see that we are just creating a JavaScript alert with a short message including the value of Y.version, which is simply a string containing the version number of YUI that has been loaded as seen in the following screenshot: Here, we can see that our code has successfully initialized the YUI 3.2.0 environment and is ready for us to start using the features available within the YUI and its additional modules. How it works... We have created a new instance of the global object YUI, and called the use method, passing in an anonymous function that contains the code we wish to run. When the new instance of the YUI object is fully loaded, it makes a call to our anonymous function, and our code is executed. In this example, our code displays a short message containing the version number of the YUI instance we created, confirming that we have a fully functional YUI 3 environment as a basis to implement further YUI features. Loading additional YUI modules YUI has a whole host of additional modules providing a very wide range of functionalities. Some examples of commonly used functionalities provided by additional modules include: Animation Drag and drop Manipulating DOM elements Handling DOM events (that is an input button's "click" event) Handling data (JSON/XML) For a current list of all the modules available, please refer to the Yahoo! Developer Network website for YUI 3 at the URL: http://developer.yahoo.com/yui/3/ How to do it... The loading of additional modules is achieved via the use method of the YUI object. In the previous recipe we learned how to run code via the use method with the following syntax: YUI().use ( function(Y) { /* <code to execute> */ } ); Note that the use method takes an arbitrarily long number of arguments (one or more) and only the last argument must be the anonymous function described in the previous recipe. The preceding arguments are a list of one or more modules you wish to load. So for example, to load the Animation module (anim) and the DOM Event Utility module (event), we would use the following syntax in place of the preceding one: YUI().use ( "anim", "event", function(Y) { /* <code to execute> */ } ); Now all of the features of these two additional modules (anim and event) will be available within the anonymous function that contains the code we want to execute. This technique will be used to load the modules we require in the examples contained in the subsequent recipes.
Read more
  • 0
  • 0
  • 2262

article-image-pfsense-faqs
Packt
13 May 2011
4 min read
Save for later

pfSense FAQs

Packt
13 May 2011
4 min read
  pfSense 2 Cookbook A practical, example-driven guide to configuring even the most advanced features of pfSense 2.0       Read more about this book       (For more resources related to this subject, see here.) Q: What are the minimum hardware requirements for pfSense? A: The minimum requirements for a pfSense installation are 500Mhz, 128MB RAM, and 1GB hard disk space. Q: How does pfSense identify and assign interfaces? A: pfSense, like any other computer operating system, references each NIC by some unique value (fxp0, em0, em1, and so on). These unique identifiers are often associated with the driver being used and make it easier for us humans to use than the associated MAC address (00:80:0c:12:01:52). Taking that concept a step further, an interface is simply a named placeholder for each port: fxp0=WAN, em0=LAN, em1=DMZ, and so on. Q: How to enable the Secure Shell (SSH) service in pfSense? A: SSH is a networking protocol that allows encrypted communication between two devices. Enabling SSH allows secure access to the pfSense console remotely, just as if you were sitting in front of the physical console. Browse to System | Advanced | Secure Shell. Check Enable Secure Shell. You will be prompted for credentials when you connect (use the same username and password as the webGUI), but checking Disable password login for Secure Shell will allow you to use RSA keys instead. Leave the SSH port blank to use the default port: (Move the mouse over the image to enlarge it.) Save the changes and the SSH service will be started. Enabling the Secure Shell turns on pfSense's built-in SSH server to listen to requests on the port you've specified (port 22 by default). Like all pfSense services (unless otherwise noted), the SSH service will listen on every available interface. Like other services, firewall's rules are used to grant or deny access to these services.   Q: How does pfSense assign DNS servers to the DHCP clients? A: Specify any DNS server to be automatically assigned to our DHCP clients. If left blank, pfSense will automatically assign DNS servers to our clients in one of the following two ways: If DNS Forwarder is enabled, then the IP address of the interface is used. This is because the DNS Forwarder turns the pfSense machine itself into a DNS server, so the IP of the pfSense machine (that is, the gateway, which varies by interface) is assigned to each client. If DNS Forwarder isn’t enabled, then the DNS Servers configured on the General Setup page are used. And of course if, Allow DNS server list to be overridden by DHCP/PPP on WAN is enabled in General Setup, then the DNS servers obtained through the WAN will be used instead.   Q: What happens if the Register DHCP Leases in DNS Forwarder is enabled? A: If the Register DHCP Leases in DNS Forwarder option is enabled, pfSense will automatically register any devices that specify a hostname when submitting a DNS request. The downside, of course, is that not all devices submit a hostname and even when they do, it is sometimes cryptic. I prefer to only register important devices using DHCP static mappings, and all other (unimportant/unknown) devices can be referenced using their IP addresses. Q: What is an alias? What are the different types of aliases in pfSense? A: An alias is a place-holder (that is a variable) for information that may change. Aliases provide a degree of separation between our rules and values that may change in the future (for example, IP addresses, ports, and so on). It's best to use aliases whenever possible. The different types of aliases are as follows: Host alias: Selecting Host(s) as an alias Type allows you to create an alias that holds one or more IP addresses. Network alias: Selecting Network(s) as an alias Type allows you to create an alias that holds one or more networks (that is ranges of IP addresses). Port alias: Selecting Port(s) as an alias Type allows you to create an alias that holds one or more ports. OpenVPN Users alias: Selecting OpenVPN Users as an alias Type allows you to create an alias that holds one or more OpenVPN usernames. URL alias: Selecting URL as an alias Type allows you to create an alias that holds one or more URLs. URL Table alias: Selecting URL Table as an alias Type allows you to create an alias that holds a single URL pointing to a large list of addresses. This can be especially helpful when you need to import a large list of IPs and/or subnets. Using an alias: Aliases can be used anywhere you see a red textbox. Simply begin typing and pfSense will display any available aliases that match the text you've entered.
Read more
  • 0
  • 0
  • 4802

article-image-installation-silverstripe-24
Packt
13 May 2011
11 min read
Save for later

Installation of SilverStripe 2.4

Packt
13 May 2011
11 min read
  SilverStripe 2.4 Module Extension, Themes, and Widgets: Beginner's Guide Create smashing SilverStripe applications by extending modules, creating themes, and adding widgets         Read more about this book       (For more resources on SilverStripe, see here.) Setting up the environment There are many possible scenarios and environments you might require, depending on the complexity of your project. However, we'll keep this short and simple: We'll set up a development environment, which is based on Windows (Windows XP or newer) as it is the most common operating system on desktops and laptops. We'll also set up one live or deployment environment, which is based on Linux as it is the most common operating system for web servers. We'll use Ubuntu in our example as it is freely available and widely used. If you prefer a different distribution some paths and commands will vary, but the general approach should be very similar. In case you want to use a testing or staging environment as well, we'll assume that you simply reuse the previous setup—so we don't need to configure another system. Now that we've decided on the general purpose of the systems and their operating systems, we'll need to choose between different implementations for setting up the web server and database. Specifically, whether to use prebuilt packages or select the components ourselves. To demonstrate both approaches we'll use a prebuilt package on our development machine (as we want to get up and running quickly) and handpick the components on our live site, where we want to have maximum control. To keep our development and live environments closely related, we'll use the same applications for both—disqualifying Windows-only solutions: For the web server we'll use the Apache HTTP Server (http://httpd.apache.org) as it's the most widely used, cross-platform server. Alternatives would be Microsoft's Internet Information Services (http://www.iis.net), which are only available on Windows, and Lighttpd (http://www.lighttpd.net) or Nginx (http://nginx.org), which are both fast, but not as widely used as the Apache web server, and are a little trickier to set up. For the database we'll use the popular MySQL (http://www.mysql.com). Alternatively you could use Microsoft SQL Server (https://www.microsoft.com/sqlserver/2008/en/us/default.aspx), which requires Windows; PostgreSQL (http://www.postgresql.org), SQLite (http://www.sqlite.org), or an Oracle database (http://www.oracle.com/us/products/database/index.html). However, each of these alternatives requires an additional SilverStripe module to support its specific SQL dialect, which generally receive less attention than MySQL. Unless you have a good reason for changing the database, like you're already using MS SQL for everything else, stick with MySQL. For a change the programming language PHP (http://www.php.net) doesn't require any decisions as there are no alternative implementations. For the prebuilt package we'll use XAMPP (http://www.apachefriends.org/en/xampp.html), which matches our requirements. It uses the Apache HTTP Server and MySQL and is available on Windows, Linux, Mac OS X, and Solaris. If your development machine doesn't use Windows, you should still be able to follow the installation steps with minor variations. On Windows there's also Microsoft's Web Platform Installer (http://www.microsoft.com/web/downloads/platform.aspx). It doesn't only include the web server, database and PHP, but also SilverStripe itself (http://www.microsoft.com/web/gallery/silverstripecms.aspx)—which can be downloaded on demand among many other web applications. However, as this is very different to our live site, we won't cover it. If you're looking for a, Windows-only solution this is nevertheless an interesting option as it is very easy to set up. The Windows development system Let's start off by setting up our development system, based on the freely available XAMPP package. Time for action - installing XAMPP We'll assume that the operating system is Windows XP or newer—for Linux, Mac OS X, and Solaris you should only need to get a different download file and do some minor variations of the steps described: Download the XAMPP package at http://www.apachefriends.org/en/xampp-windows.html. We're using the 7zip package as it doesn't require an installation, is compact to download and also portable: you can copy it to a USB drive and use the environment on any Windows computer. Extract the archive to a top-level folder on your internal drive (C: for example), or your portable external drive (U: for example). To do this, you'll need the free 7zip archive utility, which you can download at http://www.7-zip.org. Open up the file xampp/mysql/bin/my.ini and add the following line in the [mysqld] section: lower_case_table_names=2 This setting is important for exchanging database dumps between Windows and Linux systems. As Windows paths are case insensitive, MySQL lowercases database and table names by default (as they are internally stored as folders and files), but only on Windows. On Linux proper cases are preserved, which leads to problems when using dumps on different platforms. The previous statement forces MySQL on Windows to behave like on Linux. Inside the XAMPP folder, start the file xampp-control.exe and use it to Start Apache, MySql and Mercury. XAMPP's control panel should look like this after starting the three applications: If a service doesn't start, check that its port is not already in use—this is the main reason for problems. To do this, open the command line tool and enter netstat-ao. This will show you the ports currently in use and the process IDs (PIDs) of the processes using them. Using Window's Task-Manager you can then find out the name of the process causing the problem, and stop or reconfigure it. The following screenshot illustrates this scenario—the web server cannot be started as Skype is already using port 80: After successfully starting all three services, navigate to http://localhost in your browser. This should redirect you to XAMPP's welcome page. In case you need to send e-mails for testing purposes, you'll need to perform two additional steps to configure your SMTP server: Enable SMTP relaying of non-local mail. However, ensure that no one can access your mail server from outside or you might be abused as a spam relay (your router or firewall will protect you). In XAMPP's control panel, click on Admin... next to the Mercury label. Next go to Configuration, MercuryS SMTP Server and on the Connection control tab uncheck Do not permit SMTP relaying of non-local mail. Provide a DNS server so domain names can be looked up: Under Configuration, MercuryE SMTP Client fill in the field Name server with your provider's DNS server. That's it for our general purpose development machine. In case you want to run automatic tests or generate translation files, you'll also need to install PHPUnit through PEAR: While XAMPP includes PEAR and PHPUnit, the bundled versions are hopelessly outdated. Furthermore the update process doesn't work reliably, so we'll better start anew. First remove xampp/php/PEAR/, xampp/php/pear.bat, xampp/php/pear.ini, xampp/php/peardev.bat and xampp/php/pear-update.bat. Next enable PHP's cURL extension: Open xampp/php/php.ini, find the line ;extension=php_curl.dll and remove the leading semicolon. Then download http://pear.php.net/go-pear.phar into xampp/php/. Next install PEAR on the command line (start it as an admin user). Note that you must be in the folder xampp/php/ for the following commands to work: php go-pear.phar Now we can use PEAR to update its channels and upgrade all packages: pear update-channelspear upgrade --alldeps Finally you can install PHPUnit and all of its dependencies: pear channel-discover pear.phpunit.depear channel-discover components.ez.nopear channel-discover pear.symfony-project.compear install phpunit/PHPUnit That's it, you've successfully installed PHPUnit! The Linux live system Next we'll set up our live system. Thanks to package managers this isn't much harder—you just shouldn't be afraid of the shell. Time for action - installing the requirements by hand In our example we're using Ubuntu, so we'll rely on its package manager Apt, abbreviation of Advanced Package Tool. Note that we won't only install the bare necessities, but also some more tools to make our system ready for production. Open the terminal and install the Apache HTTP Server together with PHP and PHP's GD library (needed for image manipulation) through the following commands. Note that all required dependencies are added automatically, though you may need to manually accept them: sudo apt-get install apache2 php5 php5-gd Next we'll install MySQL and its binding to PHP, again through the terminal. You'll be prompted for a password, which we'll need again later on. sudo apt-get install mysql-server php5-mysql Enable Apache's rewrite module, which SilverStripe requires to use pretty URLs: sudo a2enmod rewrite Edit the file /etc/apache/sites-available/default and replace the line AllowOverride None with AllowOverride All inside the <Directory /var/www/> block. This enables the rewrite module inside the /var/www/ folder. Install Alternative PHP Cache (APC), which will accelerate PHP programs—SilverStripe benefits a lot from this. While there are some alternatives, it is currently planned that APC will be included in PHP 6, which makes it sound like a future-proof decision for our installation: sudo apt-get install php-apc If you want to see APC in action, you'll need its management tool. By default it is located in the file /usr/share/doc/php-apc/apc.php.gz. Unpack and copy it to your web-root to see detailed statistics on how well it's working for you, but protect it against unauthorized access (you can set credentials inside the file). Edit the file /etc/php5/apache2/php.ini, using whatever text-editor you prefer (this can be quite a sensitive topic with programmers). Replace the line ;date.timezone = with date.timezone = US/New_York or your current location. See http://php.net/manual/en/timezones.php for all possible values. Note that removing the semicolon at the beginning is important, otherwise the line will be considered a comment. Restart the web server to apply all the settings we've just made: sudo /etc/init.d/apache2 reload Now it's time to test our installation. Go to the directory /var/www/ which is the default web-root directory: cd /var/www/ It should already contain a file index.html, which you can view if you visit http://127.0.0.1 in your browser (or whichever IP address you can access your server under). However, this is only a static HTML file. To see if PHP is also working, first set the file permissions, assuming our current user is ubuntu (which we'll use to edit files) and the web server is run as www-data (which is the default). So we'll make our user the owner of the files with full permissions, and set the group to the one of the web server with read and execute permissions only: sudo chown ubuntu:www-data -R /var/www/sudo chmod 0755 -R /var/www/ After adding new files, you'll need to rerun these two commands. Next create a file index.php in /var/www/: touch index.php Add the following code to it: <?php phpinfo();?> In your browser load the page http://127.0.0.1/index.php (again use your specific IP address). The output should look something like this: This shows that PHP is working. Also check that you can find mod_rewrite and a full section on APC in the output to be sure they are enabled. That's it, our live system is now ready for action. We haven't installed PEAR as we'll assume that testing and translating is done in the development environment, not on the live server. We've also left out how to install and configure an SMTP server. Unfortunately this is pretty complicated and beyond the scope of this article—especially since you don't want to become a spam relay. If your provider or distribution hasn't already set this up for you, take a look at a specific SMTP server how-to and documentation—Postfix (http://www.postfix.org) is widely used for example.
Read more
  • 0
  • 0
  • 2235

article-image-microsoft-dynamics-nav-diagnosing-code-problems
Packt
13 May 2011
7 min read
Save for later

Microsoft Dynamics NAV: Diagnosing Code Problems

Packt
13 May 2011
7 min read
No one writes perfect code on their first attempt. When running hundreds or even thousands of lines of code at a time, it can be extremely difficult to determine exactly where an error occurred and what caused it. That's why we have tools like the Debugger, Code Coverage, and Client Monitor in Microsoft Dynamics NAV. For the most part the recipes in this article will not deal with writing your own code or writing better code. Instead, we will focus more on how you can determine what is happening with the code you have already written. Using the debugger This recipe will show you how to use the debugger to examine the code that is currently executing. We will demonstrate how to go through the code line-by-line and watch how values and objects change. How to do it... Create a new codeunit from Object Designer. Add the following global variable: Add the following global text constant: Add a global function called ChangeCustomerName. The function should take in the following parameter: Add the following code to the function: Customer.Name := NewName; Add the following code to the OnRun trigger: Customer.FINDFIRST; ChangeCustomerName(Text001); Customer.VALIDATE("Post Code"); Save and close the codeunit. From the Tools menu in the NAV client select Debugger | Active (Shift + Ctrl + F11). From the Tools menu in the NAV client select Debugger | Breakpoint on Triggers (Shift + Ctrl + F12). Run the codeunit. How it works... When you run the codeunit, the Microsoft Dynamics NAV Debugger window will appear just like the one shown in the following screenshot: (Move the mouse over the image to enlarge it.) Before we get into the details of this window, we need to understand what caused it to appear. Setting the debugger to Active from the Tools | Debugger menu means that the debugger window will open every time the system encounters an error. In this case, though, we know our code doesn't produce any errors. We want to look at it anyway so we turn on the Breakpoint on Triggers option as well. There are five components to the debugger window. The first is the menu and toolbar at the very top. They function just like any other toolbars you've seen. You can mouse over each button to get a tool tip of what it does. The second component sits right below and contains the actual code from the current object. Here you can see a small yellow arrow pointing to the first line of our codeunit in the OnRun trigger. This is the line that is about to execute. Note that it has NOT executed yet. We'll explore each of the other three components as we move through our code. Use the F8 key or click on the Step Into button on the toolbar. The window will now look like the one shown in the following screenshot: (Move the mouse over the image to enlarge it.) The yellow arrow has moved to the second line of code and the first line has executed. Notice the red text in the bottom left-hand corner. This is the Variables window (bottom left window). It lists all the variables and their values from the current object. At first, our customer variable was uninitialized because we had not executed the Customer.FINDFIRST line. That line retrieved a record from the database causing the value of the variable to change. This text will only remain red until you take another step into the program. The next line of code that will execute is: ChangeCustomerName(Text001); What is this Text001 variable? If you're unsure of the value of a text constant, or you don't want to scroll through a possibly long list of variables in the Context window, you can add a shortcut to the Watch List (bottom right window). Right-click on Text001 and go to Add Watch. The variable will be added to the Watch List along with its current value. Go ahead and hit F8 to step into the next line. (Move the mouse over the image to enlarge it.) The yellow arrow jumps to the function that we just called. That brings us to our last window, the Call Stack (bottom middle window). It is important to know how you got to the code you are currently viewing. By looking at the Call Stack you can see that we were in the OnRun trigger of the codeunit and then jumped to the ChangeCustomerName function. You can click on each level of the stack to see the code for that object. (Move the mouse over the image to enlarge it.) You may not always want to go through your code line-by-line, though. Try hitting the F5 key or the Go command from the Debug menu. This will cause you to jump to the next function which is called instead of the next line. You will find yourself in a complete new object, the Customer table. Notice how the Context menu completely changes because the old variables are no longer in scope. They do not belong to the current object being examined. There's more... One common annoyance is trying to stop the debugger. You will find yourself in the middle of debugging your code and have that "Aha! I know what's wrong!" moment. You will click on the "X" to close the window only to have the debugger pop right back up at you. From the Debug menu click on Stop Debugging (Shift + F5). This will stop the debugger until you turn it on again and, more importantly, allow you to continue with your development. Stop Debugging also performs a rollback of the changes that have happened to the database since you started the debugger. Setting breakpoints Stepping through code line-by-line or function-by-function can take forever. Luckily there is an easy way to tell the debugger to stop right where we want it to. How to do it... Create and save the same codeunit discussed in the Using the debugger recipe in this article. Design the codeunit. Go to the following line of code in the OnRun trigger: ChangeCustomerName(Text001); Press F9 twice. Go to the following line of code in the OnRun trigger: VALIDATE("Post Code"); Press F9 once. Your window should look like the following screenshot: Save and close the codeunit. From the Tools menu in the NAV client select Debugger | Active (Shift + Ctrl + F11). Run the codeunit. How it works... When running the debugger on this codeunit, it should stop on Customer.VALIDATE("Post Code") line of code. This is because we have set a breakpoint here, which was the filledin red circle at the left of that line. The debugger stops right where we tell it to, that is right before that line of code executes. You will notice another mark. It is a red circle that is not filled. This is used to mark old breakpoints that you are not currently using. This is useful when you are trying to debug large amounts of code and want to temporarily remove a breakpoint or remember where you had one. There's more... The debugger is not perfect by any means. Some might even say it has a mind of its own sometimes. It doesn't always stop exactly where you want it to. It is common practice to set a breakpoint on a few successive lines of code in order to ensure that you stop in the general area.
Read more
  • 0
  • 0
  • 2016

article-image-silverstripe-24-creating-our-own-theme
Packt
12 May 2011
8 min read
Save for later

SilverStripe 2.4: Creating our Own Theme

Packt
12 May 2011
8 min read
Time for action - files and folders for a new theme We could start off from scratch, but let's not make it more complicated than necessary: Simply copy the BlackCandy theme to a new folder in the same directory. We'll just call it bar as the page should be for a bar business. Now reload the CMS backend and you should be able to switch to the new bar theme. As we won't use any of the available images we can delete all image files, but leave the folder intact—we'll add our own pictures later on. Basic layout Next, we'll create our page's general layout. Time to put our template skills into action! Here's the basic layout we want to create: So far it's a pretty basic page. We'll take a good look at the templates and basic structure but won't spend much time on the HTML and CSS specifics. Do, however pay attention on how to set up the different CSS files to make the most out of them. We won't list every line of code involved. If you'd prefer, you can simply copy the missing parts from the code provided here (Ch:2) File themes/bar/templates/Page.ss This page is pretty empty. We'll later add an intro page with a different structure, so the code these templates will share is rather limited. Time for action - the base page Add the following code to the file themes/bar/templates/Page.ss: <!doctype html> <html lang="$ContentLocale"> <head> <meta charset="utf-8"/> <% base_tag %> <title> <% if MetaTitle %> $MetaTitle <% else %> $Title <% end_if %> </title> $MetaTags(false) <link rel="shortcut icon" href="favicon.ico"/> <!--[if lt IE 9]> <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"> </script> <![endif]--> </head> <body> $Layout <noscript> <br/>&nbsp;<br/>&nbsp;<br/>&nbsp;<br/>&nbsp;<br/>&nbsp;<br/>&nbsp; <div><p> <b>Please activate JavaScript.</b><br/> Otherwise you won't be able to use all available functions properly... </p></div> </noscript> </body> </html> What just happened? The highlighted parts are SilverStripe specific: First, we set the language of our content. Depending on what you've selected during the installation process this can vary. By default, it will be: <html lang="en-US"> Setting the page's base; this can be useful when referencing images and external files. Depending on how you set up your system this will vary. Setting the title just like in the BlackCandy theme. Next, adding meta tags without the title element. These are only set if you actually enter them in the CMS on the Metadata tab on the desired page's Content tab. Empty fields are simply left out in the output. Only the SilverStripe note is set in any case. Finally, including the page's specific layout. The JavaScript we include for Internet Explorer versions before 9 fixes their inability to correctly render HTML5 tags. To learn more about the specific code, head over to https://code.google.com/p/html5shim/. Why HTML5? The motivation behind it isn't to stay buzz-word compliant. While HTML5 is not a finished standard yet, it already adds new features and makes the development a little easier. Take a look at the doctype declaration for example: that's much shorter than XHTML. Now there's a real chance of actually remembering it and not needing to copy it every time you start from scratch. New features include some very handy tags, but we'll come to those in the next code sample. The output on the final HTML page for the second and third elements (we've already taken a look at the first) in the header looks like the following listing. Which part in the template is responsible for which line or lines? <title>home</title> <meta name="generator" content="SilverStripe - http://silverstripe.org" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <meta name="keywords" content="some keyword" /> <meta name="description" content="the description of this page" /> Did you notice that there is no reference to a CSS file and the styling is still applied? Remember that CSS files are automagically included if you stick to the naming convention we've already discussed. File themes/bar/templates/Layout/Page.ss Now let's move beyond the basics and do something a bit more interesting. Time for action - the layout page Add the following code to the file themes/bar/templates/Layout/Page.ss: <div> <img src="$ThemeDir/images/background.jpg" alt="Background" id="background"/> </div> <section id="content" class="transparent rounded shadow"> <aside id="top"> <% include BasicInfo %> </aside> <% include Menu %> <section class="typography"> $Content $Form </section> </section> <% include Footer %> We rely on just three includes which are very easy to reuse on different pages. We then reference the page's content and possible forms (no comments will be required). The only template part we've not yet covered is the $ThemeDir. This is replaced by the path to our theme, in our case themes/bar/. So you don't need to worry about hard-coded paths when copying template files between different themes. You only need to take care of paths in the CSS files as they are not processed by the template engine. The includes: BasicInfo.ss, Menu.ss, and Footer.ss In the previous code segment, we've referenced three includes. Let's not forget to create them. Time for action - the includes The includes we're yet to explore are Menu.ss, BasicInfo.ss, and Footer.ss. The menu is very simple, we only include the first level, highlighting the currently active item, as we won't have more subpages: <nav id="menu"> <ul> <% control Menu(1) %> <li class="$Linkingmode"> <a href="$Link">$MenuTitle</a> </li> <% end_control %> </ul> </nav> BasicInfo.ss only contains the $ThemeDir placeholder besides good old HTML: <a href="home"> <img src="$ThemeDir/images/logo.png" alt="Logo" id="logo"/> </a> <ul id="details-first"> <li>Phone: <b>01 23456789</b></li> <li>Contact: <a href="contact">contact@bar.com</a></li> <li>Address: <a href="location">Bar Street 123</a></li> </ul> <div id="details-second"> <div class="left">Opening hours:</div> <div class="right"><p> <b>Mon - Thu 2pm to 2am</b><br/> <b>Fri - Sat 2pm to 4am</b> </p></div> </div> <a href="http://www.facebook.com/pages/"> <img src="$ThemeDir/images/facebook.png" alt="Facebook" id="facebook"/> </a> Be sure to replace bar.com with your own domain. However, using it here is quite fitting because we're making a page for a bar and http://www.bar.com is only a placeholder itself. It's derived from foobar or foo bar, a placeholder name often used in computer programming. But take a look at the site yourself for more information. Finally, the footer makes use of the $Now placeholder and the date formatter .Year to retrieve the current year: <footer> <span><a href="imprint">Imprint</a></span> <span>&copy; Bar $Now.Year</span> </footer> Have a go hero - create the layout and pages Now that we've gone over all of the content, it's time to build the page. Feel free to copy some code as we're not a typing class, but take careful note of every SilverStripe specific part, so you understand what you're doing. We use three includes, so create these files and remove the rest still available from BlackCandy as well as the unused templates/Layout/Page_results.ss. And don't forget to flush the cache by appending ?flush=all to the page's URL! When working with includes it will save you a lot of trouble. We've hardcoded some links to different pages in the template files. Make sure you add all necessary pages including the imprint, but don't add it to the menu.
Read more
  • 0
  • 0
  • 2646

article-image-ibm-lotus-domino-creating-action-buttons-and-adding-style-views
Packt
11 May 2011
7 min read
Save for later

IBM Lotus Domino: Creating Action Buttons and Adding Style to Views

Packt
11 May 2011
7 min read
IBM Lotus Domino: Classic Web Application Development Techniques A step-by-step guide for web application development and quick tips to enhance applications using Lotus Domino Provide view navigation buttons Simple views intended to provide information (for example, a table of values) or links to a limited number of documents can stand alone quite nicely, embedded on a page or a view template. But if more than a handful of documents display in the view, you should provide users a way to move forward and backward through the view. If you use the View Applet, enable the scroll bars; otherwise add some navigational buttons to the view templates to enable users to move around in it. Code next and previous navigation buttons If you set the line count for a view, only that number of rows is sent to the browser. You need to add Action buttons or hotspots on the view template to enable users to advance the view to the next set of documents or to return to the previous set of documents—essentially paging backward and forward through the view. Code a Next button with this formula: @DbCommand("Domino"; "ViewNextPage") Code a Previous button with this formula: @DbCommand("Domino"; "ViewPreviousPage") Code first and last buttons Buttons can be included on the view template to page to the first and last documents in the view. Code an @Formula in a First button's Click event to compute and open a relative URL. The link reopens the current view and positions it at the first document: @URLOpen("/"+@WebDbName+"/"+@Subset(@ViewTitle;-1) + "?OpenView&Start=1") For a Last button, add a Computed for Display field to the view template with this @Formula: @Elements(@DbColumn("":"NoCache"; "" ; @ViewTitle; 1)) The value for the field (vwRows in this example) is the current number of documents in the view. This information is used in the @Formula for the Last button's Click event: url := "/" + @WebDbName + "/" + @Subset(@ViewTitle;-1) ; @URLOpen(url + "?OpenView&Start=" + @Text(vwRows)) When Last is clicked, the view reopens, positioned at the last document. Please note that for very large views, the @Formula for field vwRows may fail because of limitations in the amount of data that can be returned by @DbColumn. Let users specify a line count As computer monitors today come in a wide range of sizes and resolutions, it may be difficult to determine the right number of documents to display in a view to accommodate all users. On some monitors the view may seem too short, on others too long. Here is a strategy you might adapt to your application, that enables users to specify how many lines to display. The solution relies on several components working together: Several Computed for display fields on the view template A button that sets the number of lines with JavaScript Previous and Next buttons that run JavaScript to page through the view The technique uses the Start and Count parameters, which can be used when you open a view with a URL. The Start parameter, used in a previous example, specifies the row or document within a view that should display at the top of the view window on a page. The Count parameter specifies how many rows or documents should display on the page. The Count parameter overrides the line count setting that you may have set on an embedded view element. Here are the Computed for display fields to be created on the view template. The Query_String_Decoded field (a CGI variable) must be named as such, but all the other field names in this list are arbitrary. Following each field name is the @Formula that computes its value: Query_String_Decoded: Query_String_Decoded vwParms: @Right(@LowerCase(Query_String_Decoded); "&") vwStart: @If(@Contains(vwParms; "start="); @Middle(vwParms; "start="; "&"); "1") vwCount: @If(@Contains(vwParms; "count="); @Middle(vwParms; "count="; "&"); "10") vwURL: "/" + @WebDbName + "/"+ @Subset(@ViewTitle;1) + "?OpenView" vwRows: @Elements(@DbColumn("":"NoCache"; ""; @ViewTitle; 1)) countFlag "n" newCount: "1" Add several buttons to the view template. Code JavaScript in each button's onClick event. You may want to code these scripts inline for testing, and then move them to a JavaScript library when you know they are working the way you want them to. The Set Rows button's onClick event is coded with JavaScript that receives a line count from the user. If the user-entered line count is not good, then the current line count is retained. A flag is set indicating that the line count may have been changed: var f = document.forms[0] ; var rows = parseInt(f.vwRows.value) ; var count = prompt("Number of Rows?","10") ; if ( isNaN(count) | count < 1 | count >= rows ) { count = f.vwCount.value ; } f.newCount.value = count ; f.countFlag.value = "y" ; The Previous button's onClick event is coded to page backward through the view using the user-entered line count: var f = document.forms[0] ; var URL = f.vwURL.value ; var ctFlag = f.countFlag.value ; var oCT = parseInt(f.vwCount.value) ; var nCT = parseInt(f.newCount.value) ; var oST = parseInt(f.vwStart.value) ; var count ; var start ; if ( ctFlag == "n" ) { count = oCT ; start = oST - oCT ; } else { count = nCT ; start = oST - nCT ; } if (start < 1 ) { start = 1 ; } location.href = URL + "&Start=" + start + "&Count=" + count ; The Next button pages forward through the view using the user-entered line count: var f = document.forms[0] ; var URL = f.vwURL.value ; var ctFlag = f.countFlag.value ; var oCT = parseInt(f.vwCount.value) ; var nCT = parseInt(f.newCount.value) ; var start = parseInt(f.vwStart.value) + oCT ; if ( ctFlag == "n" ) { location.href = URL + "&Start=" + start + "&Count=" + oCT ; } else { location.href = URL + "&Start=" + start + "&Count=" + nCT ; } Finally, if First and Last buttons are included with this scheme, they need to be recoded as well to work with a user-specified line count. The @formula in the First button's Click event now looks like this: count := @If(@IsAvailable(vwCount); vwCount; "10") ; parms := "?OpenView&Start=1&Count=" + count ; @URLOpen("/" + @WebDbName + "/" + @Subset(@ViewTitle;-1) + parms) ;7 The @formula in the Last button's Click event is also a little more complicated. Note that if the field vwRows is not available, then the Start value is set to 1,000. This is really more for debugging since the Start parameter should always be set to the value of vwRows: start := @If(@IsAvailable(vwRows); @Text(vwRows); "1000") ; count := @If(@IsAvailable(vwCount); vwCount; "10") ; parms := "?OpenView&Start=" + start + "&Count=" + count ; url := "/" + @WebDbName + "/" + @Subset(@ViewTitle;-1) ; @URLOpen(url + parms) ; Code expand and collapse buttons for categorized views Two other navigational buttons should be included on the view template for categorized views or views that include document hierarchies. These buttons expand all categories and collapse all categories respectively: The Expand All button's Click event contains this @Command: @Command([ViewExpandAll]) The Collapse All button's Click event contains this @Command: @Command([ViewCollapseAll]) Co-locate and define all Action buttons Action Bar buttons can be added to a view template as well as to a view. If Action buttons appear on both design elements, then Domino places all the buttons together on the same top row. In the following image, the first button is from the view template, and the last three are from the view itself: If it makes more sense for the buttons to be arranged in a different order, then take control of their placement by co-locating them all either on the view template or on the view. Create your own Action buttons As mentioned previously, Action Bar buttons are rendered in a table placed at the top of a form. But on typical Web pages, buttons and hotspots are located below a banner, or in a menu at the left or the right. Buttons along the top of a form look dated and may not comply with your organization's web development standards. You can replace the view template and view Action buttons with hotspot buttons placed elsewhere on the view template: Create a series of hotspots or hotspot buttons on the view template, perhaps below a banner. Code @formulas for the hotspots that are equivalent to the Action Bar button formulas. Define a CSS class for those hotspots, and code appropriate CSS rules. Delete or hide from the Web all standard Action Bar buttons on the view template and on the view.
Read more
  • 0
  • 0
  • 5684
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-ibm-lotus-domino-exploring-view-options-web
Packt
11 May 2011
8 min read
Save for later

IBM Lotus Domino: exploring view options for the web

Packt
11 May 2011
8 min read
Views are important to most Domino applications. They provide the primary means by which documents are located and retrieved. But working with views on the Web is often more complicated or less satisfactory than using views with the Notes client. Several classic view options are available for web applications, all of which have draw-backs and implementation issues. A specific view can be displayed on the Web in several different ways. So it is helpful to consider view attributes that influence design choices, in particular: View content View structure How a view is translated for the Web How a view looks in a browser Whether or not a view template is used View performance Document hierarchy In terms of content, a view contains: Data only Data and HTML tags In terms of structure, views are: Uncategorized Categorized In terms of the techniques used by Domino to translate views for the Web, there are four basic methods: Domino-generated HTML (the default) Developer-generated HTML (the view contains data and HTML tags) View Applet (used with data only views) XML (the view is transmitted to the browser as an XML document) The first three of these methods are easier to implement. Two options on the Advanced tab of View Properties control which of these three methods is used: Treat view contents as HTML Use applet in the browser If neither option is checked, then Domino translates the view into an HTML table and then sends the page to the browser. If Treat view contents as HTML is checked, then Domino sends the view to the browser as is, assuming that the developer has encoded HTML table tags in the view. If Use applet in the browser is checked, then Domino uses the Java View Applet to display the view. (As mentioned previously, the Java Applets can be slow to load, and they do require a locally installed JVM (Java Virtual Machine)). Using XML to display views in a browser is a more complicated proposition, and we will not deal with it here. Pursue this and other XML-related topics in Designer Help or on the Web. Here is a starting point: http://www.ibm.com/developerworks/xml/ In terms of how a view looks when displayed in a browser, two alternatives can be used: Native styling with Designer Styling with Cascading Style Sheets In terms of whether or not a view template is used, there are three choices: A view template is not used The default view template is used A view template created for a specific view is used Finally, view performance can be an issue for views with many: Documents Columns Column formulas Column sorting options Each view is indexed and refreshed according to a setting on the Advanced tab of View Properties. By default, view indices are set to refresh automatically when documents are added or deleted. If the re-indexing process takes longer, then application response time can suffer. In general, smaller and simpler views with fewer column formulas perform better than long, complicated and computationally intensive views. The topics in this section deal with designing views for the Web. The first few topics review the standard options for displaying views. Later topics offer suggestions about improving view look and feel. Understand view Action buttons As you work with views on the Web, keep in mind that Action buttons are always placed at the top of the page regardless of how the view is displayed on the Web (standard view, view contents as HTML) and regardless of whether or not a view template is used. Unless the Action Bar is displayed with the Java applet, Action buttons are rendered in a basic HTML table; a horizontal rule separates the Action buttons from the rest of the form. Bear in mind that the Action buttons are functionally connected to but stylistically independent of the view and view template design elements that display lower on the form. Use Domino-generated default views When you look at a view on the Web, the view consists only of column headings and data rows. Everything else on the page (below any Action buttons) is contained on a view template form. You can create view templates in your design, or you can let Domino provide a default form. If Domino supplies the view template, the rendered page is fairly basic. Below the Action buttons and the horizontal rule, standard navigational hotspots are displayed; these navigational hotspots are repeated below the view. Expand and Collapse hotspots are included to support categorized views and views that include documents in response hierarchies. The view title displays below the top set of navigational hotspots, and then the view itself appears. If you supply a view template for a view, you must design the navigational hotspots, view title, and other design elements that may be required. View contents are rendered as an HTML table with columns that expand or contract depending upon the width of cell contents. If view columns enable sorting, then sorting arrows appear to the right of column headings. Here is an example of how Domino displays a view by default on the Web: In this example, clicking the blue underscored values in the left-most Last Name column opens the corresponding documents. By default, values in the left-most column are rendered as URL links, but any other column—or several columns—can serve this purpose. To change which column values are clickable, enable or disable the Show values in this column as links option on the Advanced tab of Column Properties: Typically a title, subject, or another unique document attribute is enabled as the link. Out of the box default views are a good choice for rapid prototyping or for one-time needs where look-and-feel are less important. Beyond designing the views, nothing else is required. Domino merges the views with HTML tags and a little JavaScript to produce fully functional pages. On the down side, what you see is what you get. Default views are stylistically uninspiring, and there is not a lot that can be done with them beyond some modest Designer-applied styling. Many Designer-applied styles, such as column width, are not translated to the Web. Still, some visual improvements can be made. In this example, the font characteristics are modified, and an alternate row background color is added: Include HTML tags to enhance views Some additional styling and behavior can be coded into standard views using HTML tags and CSS rules. Here is how this is done: In this example, <font> tags surround the column Title. Note the square brackets that identify the tags as HTML: Tags can also be inserted into column value formulas: "[<font color='darkblue'>]" + ContactLast + "[</font>]" When viewed with a browser, the new colors are displayed as expected. But when the view is opened in Notes, it looks like this: (Move the mouse over the image to enlarge it.) The example illustrates how to code the additional tags, but frankly the same effects can be achieved using Designer-applied formatting, so there is no real gain here. The view takes longer to code and the final result is not very reader-friendly when viewed with the Notes client. That being said, there still may be occasions when you want to add HTML tags to achieve a particular result. Here is a somewhat more complicated application of the same technique. This next line of code is added to the Title of a column. Note the use of <sup> and <font> tags. These tags apply only to the message See footnote 1: Last Name[<sup><font color='red'>]See footnote 1[</font></sup>] The result achieves the desired effect: More challenging is styling values in view columns. You do not have access to the <td> or <font> tags that Domino inserts into the page to define table cell contents. But you can add <span> tags around a column value, and then use CSS rules to style the span. Here is what the column formula might look like: "[<span class='column1'>]" + ContactLast + "[</span>]" Here is the CSS rule for the column1 class: .column1 { background-color: #EEE; cursor: default; display: block; font-weight: bold; text-decoration: none; width: 100%; } These declarations change the background color of the cell to a light gray and the pointer to the browser default. The display and width declarations force the span to occupy the width of the table cell. The text underscoring (for the link) is removed and the text is made bold. Without the CSS rule, the view displays as expected: With the CSS rule applied, a different look for the first column is achieved:
Read more
  • 0
  • 0
  • 9010

article-image-zenoss-core-3-tips-and-tricks
Packt
10 May 2011
4 min read
Save for later

Zenoss Core 3: Tips and Tricks

Packt
10 May 2011
4 min read
Zenoss Core 3.x Network and System Monitoring Importing devices and attributes Tip: If you already have a list of the SNMP capable devices by hostname or IP address, Zenoss Core can import them via the zenbatchload command. In its simplest form, zebatchload will process a text file that lists one device per line. Here's a sample list of devices that I will call deviceList.txt: device01 router02 web03 Since zenbatchload is a Zenoss Core daemon, we need to run it as the zenoss user. Here are the commands: su - zenoss <enter zenoss user's password> zenbatchload deviceList.txt The zenbatchload import utility will not update devices that are already in the device inventory. Editing and moving organizers Tip: Editing organizers: You can change the name or description of an organizer by selecting the organizer and then clicking on Edit. You can find the Edit option by clicking on the Actions menu button (which looks like a sprocket) at the bottom of the Infrastructure sidebar. See the following screenshot: Moving organizers: You can nest organizers by dragging and dropping one organizer into another one to create a hierarchy. You can only nest similar organizers, which means that you cannot move a system into a group or a group into a location. Zeneventlog—unable to connect to Windows Tip: If you see an event that indicates zeneventlog is unable to connect to Windows, that's an indication Zenoss Core is not able to authenticate to the Windows server. Check the Configuration Properties (zProperties) of the device to ensure you have the correct username and password set. The following screenshot shows the WMI specific zProperties: Remember, the zWinUser and zWinPassword properties must be an administrator on the Windows server you're monitoring. It's possible that each of your Windows servers could require a different username and password. The zWinUser property can be either a local or a domain account. If you use a domain account, specify the domain for the zWinuser value (for example, mojoactiveadministrator). Zenoss Core does not collect WMI data Tip: It's possible that Zenoss Core isn't collecting any data from the Windows Servers via WMI, but there are no events reported. You can check the following zProperties at the device or class level: Make sure the device is using the zenoss.wmi.WinServiceMap collector plugin Set the zWmiMonitorIgnore property to False in the Configuration Properties for the device or device class If you want to collect event logs, set the zWinEventlog property to True in the Configuration Properties for the device or device class Acknowledging an event Tip: Acknowledging an event signals to other team members and to Zenoss Core that you are aware of the event and, presumably, taking action. Acknowledging the event is good communication among your team, but Zenoss Core can also escalate event severities or alerts based on an event status. A common way to escalate an event or an alert is by the event count. For example, we can instruct Zenoss Core to escalate the event severity from Error to Critical if the event hasn't been acknowledged after a specified number of monitoring cycles. Or if we're dealing with alerts, Zenoss Core can be configured to alert the next person on call, in the event you fall asleep on the roof at 3 in the morning and don't realize the database server has been down for 15 minutes. To acknowledge an event: Select the event from the Event Console by clicking on it. Click on the on Acknowledge Events button (the icon that looks like a check mark). A check mark will appear next to the event. See the following screenshot: In the screenshot all the events are acknowledged, except the first one.
Read more
  • 0
  • 0
  • 13125

article-image-cms-made-simple-application-user-defined-tags
Packt
10 May 2011
9 min read
Save for later

CMS Made Simple: Application of User-Defined Tags

Packt
10 May 2011
9 min read
CMS Made Simple Development Cookbook Over 70 simple but incredibly effective recipes for extending CMS Made Simple with detailed explanations – useful for beginners and experts alike! These recipes have been specially selected to demonstrate capabilities. While they may be useful as provided, they are designed to show the range of what can be done with tags, and to provide examples of useful operations such as setting Smarty variables, interfacing with the database, interacting with modules, and consuming data from remote web services. You are encouraged to use these recipes as starting points for your own projects. Introduction One of the most popular uses of CMS Made Simple involves an administrator who creates a basic site structure and template, and one or more editors who maintain page content without having to worry about the site layout. In this configuration, you can think of the CMS essentially as a big template engine with some utilities to add content. Each page of the site comprises a page template with areas that get populated with various kinds of content. These areas are either tags or variables, where the distinction is that a tag involves the execution of code, while a variable is a simple substitution of values. The CMS comes with a large assortment of built-in tags, including the fundamental "content" tag and a variety of useful supporting tags for building navigation, links, including images, and so forth. Because CMS Made Simple can be seen as being built around tags, it is not surprising that there are facilities for creating your own tags. You can create tags directly through the Admin panel—these are called User-Defined Tags or UDTs. If you want even more extensive capabilities in your tag, you can have those capabilities by creating a file that follows a few basic conventions. The template engine used by CMS Made Simple comes from the Smarty project. Pages are Smarty templates, and the built-in CMS tag types are all Smarty tags. Behind the scenes, both UDTs and file-based tags also become Smarty tags. For additional information on Smarty, the documentation provided by the Smarty project is invaluable. You can read more at http://www.smarty.net/docsv2/en/ Displaying the User's IP address from a User-Defined Tag This recipe demonstrates creating a very simple User-Defined Tag, and using it to display information, that it gets from PHP globally-defined variables. Getting ready For this recipe, you will need to have CMS Made Simple installed and working. You will need login access to the site's Administration area as a member of the "admin" group, or as a member of a group with permissions to "Modify User-Defined Tags" and "Manage All Content". How to do it... Log in to your CMS Administration area. Using the top menu, go to "Extensions" and click on "User Defined Tags". Click on the "Add User Defined Tag" button. In the "Name" field type "user_ip". In the "Code" text area, type the following code: echo 'Welcome user from '.$_SERVER['REMOTE_ADDR'].' -- enjoy your visit!'; Click on the "Submit" button. Using the top menu, go to "Content" and click on "Pages". Click on the "Add New Content" button. In the "Title" and "Menu Text" fields, type "Tag Test". In the "Content" text area, type the following code: {user_ip} Click on the "Submit" button. View your site from the user side. Click on the new "Tag Test" page. How it works... User-Defined Tags work by linking a piece of PHP code to a tag which is recognized by Smarty. When Smarty parses a template and encounters that tag, it executes the code in question, and substitutes the tag markup with any output from that PHP code. When we create a UDT in the CMS Made Simple admin area, the name we enter into the text field becomes the tag which Smarty will look for, and the code we enter into the text area is the PHP associated with the tag. This recipe is an example of outputting text directly from a User-Defined Tag. It works by echoing a string, that then replaces the {user_ip} tag in the content. This substitution of the tag can take place either in a page template or in the page content, which might seem a little confusing since it's stated earlier that Smarty processes tags that it finds in templates. The confusion, though, is mostly due to terminology; CMS Made Simple processes both layout templates and page content through Smarty, so while it is being processed, page content serves as a template from Smarty's perspective. The User-Defined Tag we create accesses one of the PHP "superglobals"—the $_SERVER variable . This variable contains information about the HTTP request and some environmental information about the PHP server. In this case, we're getting the user's IP address information to display. Using the CmsObject and the current content object in a User-Defined Tag This recipe shows you how to access the Page Content object via the CmsObject in a User-Defined Tag. The primary technique that it demonstrates—getting a reference to the CmsObject and using the CmsObject to get a reference to other important CMS runtime objects—is one that you will use to solve many different kinds of problems. In this recipe, we use the CmsObject to get a reference to the Page Content object. Once we have a reference to this object, we can call upon its methods to report all kinds of interesting information about the current page content. Getting ready For this recipe, you will need login access to your site's Administration area with permission to "Modify User-Defined Tags" and "Manage All Content". How to do it... Log in to your CMS Administration area. Using the top menu, go to "Extensions" and click on "User Defined Tags". Click on the "Add User Defined Tag" icon. In the "Name" field, type "content_description". In the "Code" field, type the following code: $gCms = cmsms(); $contentops = $gCms->GetContentOperations(); $content_obj = $contentops->getContentObject(); echo 'Current content object is "'.$content_obj->Name().'"<br />'; echo 'which was created on '.$content_obj->GetCreationDate().'<br />'; echo 'its alias is "'.$content_obj->Alias().'"<br />'; echo 'and its URL is "'.$content_obj->GetURL().'"<br />'; Click on the "Submit" button. Using the top menu, select "Content" and click on "Pages". Click on the "Add New Content" button. Enter "New Content Page" into the "Title" and "Menu Text" fields. In the "Content" field, enter: {content_description} Click on the "Submit" button. View your site from the user side. Click on the new "Content Page" page. How it works... CMS Made Simple uses an internal object called "CmsObject" to keep track of a great deal of what it needs to serve content. This information includes the site hierarchy, the installed and active modules, references to the database, and more. The CmsObject is available to Modules, Tags, and User-Defined Tags via the cmsms() function. In this recipe, we want to display information from the current Content object. However, this object is not directly accessible. To get access to this object, we need to make a static call to the ContentOperations object, but this object is also not directly accessible from our code. To get access to these objects, we need to get references to them. We start by gaining access to the CmsObject by calling the global cmsms() function. From our reference to the CmsObject, we request a reference to the ContentOperations object, that we then use to request a reference to the current content object. Once we have the current content object, we can call assorted methods on it to retrieve information about the current content. In this recipe, we get the content's name, when it was last modified, its alias, and its URL. Since this recipe is an example, we don't format these various pieces of information or use a template, but simply echo them. In a production UDT or one in which there's any complexity to what is being displayed, it would be more advisable to use the values to populate Smarty variables for later display, or use a template for formatting them. There's more... There are a number of interesting objects, that CmsObject manages. References can be requested to: BookmarkOperations— used in the Admin area ContentOperations—which has methods to handle Content and content metadata Db— which wraps the ADODB database API GlobalContentOperations— which has methods to handle Global Content Blocks GroupOperations— which has methods to handle Admin Groups HierarchyManager— which has methods for handling site content hierarchies ModuleOperations— which has methods for managing Modules Smarty— which wraps the Smarty template engine StylesheetOperations—which has methods for handling TemplateOperations— which has methods for handling Smarty templates UserOperations— which has methods for handling Admin Users UserTagOperations— which has methods for handling User-Defined Tags Getting attributes using page_attr If you're looking to display information about the current content object, CMS Made Simple has a custom Smarty tag that provides some attributes: {page_attr}. You can use this tag to display page attribute information—simply by specifying a key to the information you're requesting. For example, to get the page's "image" attribute, you could use the tag {page_attr key="image"}. Other keys that are supported include: target image thumbnail extra1 extra2 extra3 searchable pagedata disable_wysiwyg content_en As you can see, this is not as rich a collection of information as you can get from the content object directly using your own UDT. Old code and the use of globals If you look at old modules or User-Defined Tags that have been posted in the CMS Made Simple forum, you may see the following code: global $gCms; instead of the $gCms = cmsms() used here. For a long time, the use of the global declaration was the preferred way to access the CmsObject. This approach is now deprecated for a number of reasons, most important of which is a security issue and also including portability of code between CMS Made Simple 1.x and the upcoming 2.x versions. While use of the global declaration to access the CmsObject will likely still work, it is strongly discouraged.  
Read more
  • 0
  • 0
  • 4733

article-image-microsoft-dynamics-gp-understanding-reporting-tools
Packt
09 May 2011
11 min read
Save for later

Microsoft Dynamics GP: Understanding Reporting Tools

Packt
09 May 2011
11 min read
Microsoft Dynamics GP 2010 Reporting Create and manage business reports with Dynamics GP Our goal is to select the reporting tool that has the best capability to meet our required condition. Of course we will consider all of our reporting tools against each individual challenge. In reality, however, we will have to consider the varying conditions we need to meet with each challenge, and accept some trade-offs in our reporting tool's ability to meet all of our conditions. Intended audience A report almost always turns out useless when it hasn't been designed and created with the eventual end user in mind. Not only is it likely that the report will not provide the critical data our end user requires, but in many cases, the reporting tool we've selected to design the report may not even contain the functionality we require to meet the requirements of the end user. This can lead to ballooning investments in time and money and is often has the feel of trying to fit a square peg in a round hole! For the most part, our reporting audiences can be classified as either external or internal consumers of our organization's data. External consumers include auditors who require insight into the financial health of our organization, potential investors, and current stakeholders. On the other hand, internal consumers can range from operations personnel such as a warehouse manager, members of the accounting team, as well as members of the executive team. For external auditors who require insight into our organization's transaction journals, the default reports that come with tools such as Report Writer and SmartList Builder can easily be modified to provide auditors with the exact information they need. Although these reports are internal to GP, we can convert them to printouts or, in the case of SmartLists, export them to Excel and send the finished document over to the auditor. Other external consumers, such as potential investors and current stakeholders are primarily interested in seeing a summary of our organization's financial statement. This can be provided via numerous types of financial statements, and fortunately, Management Reporter can be used to create a wide variety of professional-looking financial statements that can then be distributed externally. One thing to keep in mind about most of our internal users is that they are more likely to operate within GP on a daily basis. We can assume that most of these users already have a GP login and are familiar with navigating through the GP environment. By creating reports with a reporting tool that is built-in to GP, we can add a new dimension to the user's GP experience without having to introduce the user to another application and another environment. Tools such as SmartList Builder and Report Writer allow us to develop such reports, and users will more than likely appreciate the ease of access that comes with their new reports. But, this is not to say that all internal users want to see their new reports in GP. It's entirely likely that members of our executive team will not have access to GP, much less the time or desire to navigate through the raw output that comes from SmartLists or posting journals designed in Report Writer. Instead, our executive team members want to see summarized information in a single, easy-to-reach location. Reporting tools such as the pre-defined SSRS Reports Library, Analysis Cubes for Excel, and Management Reporter are all alike in that they can provide these team members with a central repository of summary reports that do not require a GP user login to view. For a better, more visual understanding of the relationship between internal and external report consumers and the tools that they would most likely benefit from, take a look at the following image: Data sources Since the end result of the kind of reports is to present our end user with data from our ERP solution, we should be concerned with the source of that data. At first glance, the answer seems obvious: if we're trying to provide data from our ERP environment, shouldn't we pull it straight from the underlying company database itself? Unfortunately, the answer is not always that simple. We must be aware of potential performance impacts against our company databases that might result from our reporting processes. Additionally, even though our focus is primarily on GP 2010, we must keep in mind that data can reside in other, non-GP related data marts, as well. These separate data sources may exist due to other proprietary applications. If our end user wants to include information from separate data sources in his or her report, we need to be sure that we have a reporting tool that can access this data and use it in conjunction with what we are pulling from our GP database. By their very nature, some of the reporting tools can easily be used to combine data from multiple data sources. One tool that lends itself to this kind of reporting is the Analysis Cubes for Excel product. Because this product is built on a data warehouse, we have a ready-made location in which data extracted from multiple data sources can be transformed for consistency purposes and then loaded into the data warehouse. The transformation piece of this is critical, as one of the biggest challenges of using disparate data sources is finding a way to join the data together through some common key value(s). For example, one data source may refer to customers via a unique eight digit numeric customer code, whereas the other data source may refer to the same customer with a ten digit alpha-numeric code. In order to combine these two sets of data, we need to find a way to relate the eight digit codes to their corresponding ten digit codes from the other data source! Although Analysis Cubes for Excel offers a unique environment in which data from multiple data sources can be staged, other reporting tools we've discussed can also pull data from multiple data sources. This is largely due to the flexibility they offer in the form of using SQL queries to extract data for reports. For example, in SSRS, we can use SQL queries to create the data set from which our report is built. These SQL queries offer us flexibility to pull data from multiple tables, multiple databases, and even multiple servers. Unlike Analysis Cubes, however, the transformation required to create commonality between these different data sources must be done entirely within the SQL query. While this can be achieved, it is usually the domain of those with more advanced technical skills, and it can also cause an unnecessary drain on system resources each time the report is generated. SQL queries can also be used to generate data for SmartList Builder and Excel Report Builder reports, although this does create some limitations that may or may not be an issue for our end users. The image below shows where each reporting tool falls in the spectrum of reporting against a single data source or multiple data sources: Latency Latency deals with the idea that, depending on the reporting tool we select, the data in our report may lag a bit behind the actual data that exists in our ERP environment. Although it is likely that our users will profess a need for real-time data in all of our reports, in reality, this is not always easy to achieve. While it may be relatively easy to display up-to-the minute transactional data with certain reporting tools, this is usually only half the battle in reporting. To provide reports capable of analyzing large data sets and offering insight into trends in our data, we cannot rely on simple reporting tools that spit nothing but raw transactional data back at us. Instead, we must use reporting tools that can analyse large amounts of data and return to us a summarized look at the trends and movements within our organization. To do this requires a blend of time, money, and resources. So, while ERP applications like GP 2010 have long since been able to provide us with reporting tools that can spit raw data back at us, the effort to provide reporting tools that can truly help us aggregate and make sense of our large data sets are increasingly gaining in importance. For example, reporting tools like Management Reporter allow us to create a structure in which bits of data can be summarized into meaningful financial statements that provide both inside and outside stakeholders a look at the health of our organization. With such an analytical tool, we can see the big picture, or the trends, in our organization's data, even though this data originally came to us in the form of individual journal entries. The process of creating a financial statement in Management Reporter is two-fold: Creating the structure, or the building blocks of our report Generating the content of our report Although this is usually a fairly quick process, made even faster by the fact that we are using only standardized information from our general ledger, it still requires some time and resources to ensure that our reports are up to date. Here, then, we see an example of a great reporting tool that provides up-to-date data without too much of a drain on resources; however, we are limited to viewing this data in the rigid structure of a financial statement. But what happens when our users tell us that they want the same analytical capabilities provided by Management Reporter, but for other modules in GP, and with the flexibility to quickly and easily modify their reports? This sounds like a job for Analysis Cubes for Excel! The trade-off, however, comes in the form of extraordinarily large time delay (or latency) between the data found in the cubes and what actually exists in our production databases. Because Analysis Cubes stages data in a data warehouse and then processes the data into cubes for faster querying by the end user. The end-result means users will spend less time sorting through copious amounts of transactional data and more time analysing organizational trends that can be used to provide organizational advantage. While this data may not be up-to the minute (more than likely, it won't even be up-to-the hour), this should not scare our report-users away from this tool. Instead, we need to remind them that trends found in our data are often the result of a length of time far greater than the latency of our data; in fact, the cost and impact of reacting to every minute shift in a trend analysis caused by the addition of last minute data to our data set can often have far reaching and devastating consequences on our overall business plan! And finally, let's not overstate the importance of tools such as SmartList and Excel Reports Builder in the face of far more sophisticated reporting tools like Management Reporter and Analysis Cubes. Tools such as SmartList and Excel Reports Builder do a great job of providing transactional data quickly and accurately. Because these tools don't offer much in the way of analysis, they do the best job of any reporting tool of providing up-to-the minute data without a major drain on costs or performance. These tools also provide search mechanisms that make it easier to navigate to a specific transaction among hundreds and thousands of others. Tools such as these, while probably not much use to an executive team member, can be incredibly valuable to day-to-day operations personnel such as the Customer Service representative who must quickly navigate to a customer's transactions within GP. Using SmartList, for example, our representative can quickly find the right transaction and use the drilldown functionality to actually open the transaction directly in GP. So, while presenting real-time data can be achieved, we must determine from our end user whether the goal is to see purely transactional data that can be retrieved quickly and easily, or if there is a larger goal of using a report for trend analysis or to provide a summary of a large set of data. As we've seen, the opposing concepts of this reporting challenge consist of real time reporting versus potential data lag. While most of the tools we've discussed tend to lean towards real-time reporting, we can see from the following image that some tools do a better job of providing real-time data. Even though some tools do provide real-time data, some of these tools, like Management Reporter, require the user to go through a more defined report-generation process that can take some extra time to access the data.  
Read more
  • 0
  • 0
  • 1575
article-image-sage-3d-data-plotting
Packt
09 May 2011
6 min read
Save for later

Sage: 3D Data Plotting

Packt
09 May 2011
6 min read
  Sage Beginner's Guide Unlock the full potential of Sage for simplifying and automating mathematical computing        Time for action – make an interactive 3D plot Let's make an interactive 3D plot. var('x, y') p3d = plot3d(y^2 + 1 - x^3 - x, (x, -pi, pi), (y, -pi, pi)) p3d.show() If you run this example in the notebook interface, a Java applet called Jmol will run in the cell below the code. If you run it from the interactive shell, Jmol will launch as a stand-alone application. Clicking and dragging on the figure with the left mouse button will rotate the plot in 3D space. Clicking and dragging with the centre button, or moving the scroll wheel, zooms in and out. Right-clicking brings up a menu that allows you to set various options for Jmol. Since Jmol is also used to visualize the 3D structures of molecules, some of the options are not relevant for plotting functions. Here is a screenshot of the function, plotted with Jmol: What just happened? We made a cool 3D plot that allowed us to explore a function of two variables. When running Jmol as an applet in a worksheet, you can click on the "Get Image" link below the plot to save an image of the plot in its current state. However, the image quality is not particularly high because it is saved in JPEG format. When Jmol is called from the command line, it runs as a stand-alone application, and more options are available. You can save files in JPEG, GIF, PPM, PNG, or PDF format. Note that the PDF format is a bitmap embedded in a PDF file, rather than a true vector representation of the surface. The syntax for using plot3d is very simple: plot3d(f(x,y), (x, x_min, x_max), (y, y_min, y_max)) There are a few optional arguments to the show method that you can use to alter the appearance of the plot. Setting mesh=True plots a mesh on the surface, and setting dots=True plots a small sphere at each point. You can also use the transformation keyword argument to apply a transformation to the data—see the plot3d documentation for more information. Higher quality output We can improve the quality of saved images using ray tracing, which is an algorithm for generating images that is based on optical principles. Sage comes with ray tracing software called Tachyon, which can be used to view 3D plots. To activate Tachyon, use the show method with the viewer keyword as shown below: p3d.show(viewer='tachyon', frame=False, axes=True) Depending on the speed of your computer, the ray tracing may require a few seconds to a few minutes. The frame keyword selects whether or not to draw a box around the outer limits of the plot, while the axes keyword determines whether or not the axes are drawn. Parametric 3D plotting Sage can also plot functions of two variables that are defined in terms of a parameter. You can make very complex surfaces in this way. Time for action – parametric plots in 3D We will plot two interlocking rings to demonstrate how complex surfaces are easily plotted using three functions of two parameters: var('u, v') f1 = (4 + (3 + cos(v)) * sin(u), 4 + (3 + cos(v)) * cos(u), 4 + sin(v)) f2 = (8 + (3 + cos(v)) * cos(u), 3 + sin(v), 4 + (3 + cos(v)) * sin(u)) p1 = parametric_plot3d(f1, (u, 0, 2 * pi), (v, 0, 2 * pi), texture="red") p2 = parametric_plot3d(f2, (u, 0, 2 * pi), (v, 0, 2 * pi), texture="blue") combination = p1 + p2 combination.show() The result should look like this: What just happened? We made a very complex 3D shape using the parametric_plot3d function. The optional arguments for this function are the same as the options for the plot3d function. Contour plots Sage can also make contour plots, which are 2-D representations of 3-D surfaces. While 3D plots are eye-catching, a 2D plot can be a more practical way to convey information about the function or data set. Time for action – making some contour plots The following code will demonstrate four different ways to make a 2D plot of a 3D surface with Sage: var('x, y') text_coords = (2, -3.5) cp = contour_plot(y^2 + 1 - x^3 - x, (x, -3, 3), (y, -3, 3), contours=8, linewidths=srange(0.5, 4.0, 0.5), fill=False, labels=True, label_colors='black', cmap='gray', colorbar=False) cp += text("Contour", text_coords) ip = implicit_plot(y^2 + 1 - x^3 - x, (x, -3, 3), (y, -3, 3)) ip += text("Implicit", text_coords) rp = region_plot(y^2 + 1 - x^3 - x < 0, (x, -3, 3), (y, -3, 3), incol=(0.8, 0.8, 0.8)) # color is an (R,G,B) tuple rp += text("Region", text_coords) dp = density_plot(y^2 + 1 - x^3 - x, (x, -3, 3), (y, -3, 3)) dp += text("Density", text_coords) show(graphics_array([cp, ip, rp, dp], 2, 2), aspect_ratio=1, figsize=(6, 6)) The output should be as follows: What just happened? The plots we made demonstrate four different ways of visualizing the function we plotted in the previous example. All four functions follow the same syntax as plot3d: contour_plot(f(x,y), (x, x_min, x_max), (y, y_min, y_max)) contour_plot plots level curves on the surface. In other words, z is constant on each curve. implicit_plot does the same thing, but only plots the curve where z=0. region_plot determines the curve for which z=0, and then fills in the region where z<0. Finally, density_plot converts the z value of the function to a color value and plots a color map of the z values over the x-y plane. We used the contour plot to demonstrate some of the keyword arguments that can be used to control the appearance of the plot. Here is a summary of the options we used: KeywordDescriptioncontoursThe number of contours to drawlinewidthsA list of line widths, corresponding to the number of contoursfillTrue to fill in between the contourslabelsTrue to label each contourlabel_colorsColor to use for labelscmapColor map to use for contour linescolorbarTrue to display the a scale bar showing the color map Summary In this article we learned about making three-dimensional plots and contour plots. Further resources on this subject: Plotting Data with Sage [Article] Creating Line Graphs in R [Article] Graphical Capabilities of R [Article] What Can You Do with Sage Math? [Article] Python Multimedia: Enhancing Images [Article] Python Multimedia: Fun with Animations using Pyglet [Article]
Read more
  • 0
  • 0
  • 10616

article-image-wordpress-3-building-widget
Packt
06 May 2011
10 min read
Save for later

WordPress 3: Building a Widget

Packt
06 May 2011
10 min read
  WordPress 3 Plugin Development Essentials Create your own powerful, interactive plugins to extend and add features to your WordPress site         Read more about this book       (For more resources on WordPress, see here.) The plan What exactly do we want this plugin to do? Our widget will display a random bit of text from the database. This type of plugin is frequently used for advertisement rotations or in situations where you want to spruce up a page by rotating content on a periodic basis. Each instance of our plugin will also have a "shelf life" that will determine how frequently its content should be randomized. Let's take a moment to come up with some specifications for this plugin. We want it to do the following: Store multiple chunks of content, such as bits of Google Adsense code Be able to randomly return one of the chunks Set a time limit that defines the "shelf life" of each chunk, after which the "random" chunk will be updated Widget overview Even if you are already familiar with widgets, take a moment to look at how they work in the WordPress manager under Appearance | Widgets. You know that they display content on the frontend of your site, usually in a sidebar, and they also have text and control forms that are displayed only when you view them inside the manager. If you put on your thinking cap, this should suggest to you at least two actions: an action that displays the content on the frontend, and an action that displays the form used to update the widget settings inside the manager. There are actually a total of four actions that determine the behavior of a standard widget, and you can think of these functions as a unit because they all live together in a single widget object. In layman's terms, there are four things that any widget can do. In programmatic terms, the WP_Widget object class has four functions that you may implement: The constructor: The constructor is the only function that you must implement. When you "construct" your widget, you give it a name, a description, and you define what options it has. Its name is often __ construct(), but PHP still accepts the PHP 4 method of naming your constructor function using the name of the class. widget(): It displays content to users on the frontend. form(): It displays content to manager users on the backend, usually to allow them to update the widget settings. update(): It prepares the updated widget settings for database storage. Override this function if you require special form validation. In order to make your widget actually work, you will need to tell WordPress about it by registering it using the WordPress register_widget() function. If you want to get a bit more information about the process, have a look at WordPress' documentation here. Let's outline this in code so you can see how it works. Preparation As always, we're going to go through the same setup steps to get our plugin outlined so we can get it activated and tested as soon as possible. Create a folder inside the wp-content/plugins/ directory. We are naming this plugin "Content Rotator", so create a new folder inside wp-content/ plugins/ named content-rotator. Create the index.php file. Add the Information Head to the index.php file. If you forgot the format, just copy and modify it from the Hello Dolly plugin like we did in the previous article, Anatomy of a WordPress Plugin. We're giving you bigger sections of code than before because hopefully by now you're more comfortable adding and testing them. Here is what our index.php looks like: <?php/*------------------------------------------------------------------------------Plugin Name: Content RotatorPlugin URI: http://www.tipsfor.us/Description: Sample plugin for rotating chunks of custom content.Author: Everett GriffithsVersion: 0.1Author URI: http://www.tipsfor.us/------------------------------------------------------------------------------*/// include() or require() any necessary files here...include_once('includes/ContentRotatorWidget.php');// Tie into WordPress Hooks and any functions that should run onload.add_action('widgets_init', 'ContentRotatorWidget::register_this_widget');/* EOF */ Add the folders for includes and tpls to help keep our files organized. Add a new class file to the includes directory. The file should be named ContentRotatorWidget.php so it matches the include statement in the index.php file. This is a subclass which extends the parent WP_Widget class. We will name this class ContentRotatorWidget, and it should be declared using the extends keyword. <?php /*** ContentRotatorWidget extends WP_Widget** This implements a WordPress widget designed to randomize chunksof content.*/class ContentRotatorWidget extends WP_Widget { public $name = 'Content Rotator'; public $description = 'Rotates chunks of content on a periodic basis'; /* List all controllable options here along with a default value. The values can be distinct for each instance of the widget. */ public $control_options = array(); //!!! Magic Functions // The constructor. function __construct() { $widget_options = array( 'classname' => __CLASS__, 'description' => $this->widget_desc, ); parent::__construct( __CLASS__, $this->name,$widget_ options,$this->control_options); } //!!! Static Functions static function register_this_widget() { register_widget(__CLASS__); } } /* EOF */ This is the simplest possible widget—we constructed it using only the __ construct() function. We haven't implemented any other functions, but we are supplying enough information here for it to work. Specifically, we are supplying a name and a description, and that's enough to get started. Let's take a moment to explain everything that just happened, especially since the official documentation here is a bit lacking. When we declared the ContentRotatorWidget class, we used the extends keyword. That's what makes this PHP class a widget, and that's what makes object-oriented code so useful. The __construct() function is called when an object is first created using the new command, so you might expect to see something like the following in our index. php file: <?php $my_widget = new ContentRotatorWidget();?> However, WordPress has obscured that from us—we just have to tell WordPress the classname of the widget we want to register via the register_widget() function, and it takes care of rest by creating a new instance of this ContentRotatorWidget. There is a new instance being created, we just don't see it directly. Some of the official documentation still uses PHP 4 style examples of the constructor function— that is to say that the function whose name shares the name of the class. We feel that naming the constructor function __construct is clearer. You may have wondered why we didn't simply put the following into our index.php file: register_widget('ContentRotatorWidget'); // may throw errors if called too soon! If you do that, WordPress will try to register the widget before it's ready, and you'll get a fatal error: "Call to a member function register() on a non-object". That's why we delay the execution of that function by hooking it to the widgets_ init action. We are also tying into the construct of the parent class via the parent::__ construct() function call. We'll explain the hierarchy in more detail later, but "parent" is a special keyword that can be used by a child class in order to call functions in the parent class. In this case, we want to tie into the WP_Widget __ construct() function in order to properly instantiate our widget. Note our use of the PHP __CLASS__ constant—its value is the class name, so in this case, we could replace it with ContentRotatorWidget, but we wanted to provide you with more reusable code. You're welcome. Lastly, have a look at the class variables we have declared at the top of the class: $name, $description, and $control_options. We have put them at the top of the class for easy access, then we have referenced them in the __construct() function using the $this variable. Note the syntax here for using class variables. We are declaring these variables as class variables for purposes of scope: we want their values to be available throughout the class. Please save your work before continuing. Activating your plugin Before we can actually use our widget and see what it looks like, we first have to activate our plugin in the manager. Your widget will never show up in the widget administration area if the plugin is not active! Just to be clear, you will have to activate two things: your plugin, and then your widget. The code is simple enough at this point for you to be able to quickly track down any errors. Activating the widget Now that the plugin code is active, we should see our widget show up in the widget administration area: Appearance | Widgets. Take a moment to notice the correlation between the widget's name and description and how we used the corresponding variables in our constructor function. Drag your widget into the primary widget area to make it active. Once it has been activated, refresh your homepage. Your active widget should print some text in the sidebar. (Move the mouse over the image to enlarge it.) Congratulations! You have created your first WordPress widget! It is printing a default message: function WP_Widget::widget() must be over-ridden in a sub-class, which is not very exciting, but technically speaking you have a functional widget. We still need to enable our widget to store some custom options, but first we should ensure that everything is working correctly. Having problems? No widget? If you have activated your plugin, but you do not see your widget showing up in the widget administration area, make sure you have tied into a valid WordPress action! If you misspell the action, it will not get called! The action we are using in our index.php is widgets_init—don't forget the "s"! White screen? Even if you have PHP error-reporting enabled, sometimes you suddenly end up with a completely white screen in both the frontend and in the manager. If there is a legitimate syntax error, that displays just fine, but if your PHP code is syntactically correct, you end up with nothing but a blank page. What's going on? A heavy-handed solution for when plugins go bad is to temporarily remove your plugin's folder from /wp-content/plugins, then refresh the manager. WordPress is smart enough to deactivate any plugin that it cannot find, so it can recover from this type of surgery. If you are experiencing the "White Screen of Death", it usually means that something is tragically wrong with your code, and it can take a while to track it down because each time you deactivate the plugin by removing the folder, you have to reactivate it by moving the folder back and reactivating the plugin in the WordPress manager. This unenviable situation can occur if you accidentally chose a function name that was already in use (for example, register()—don't use that as a function name). You have to be especially careful of this when you are extending a class because you may inadvertently override a vital function when you meant to create a new one. If you think you may have done this, drop and do 20 push-ups and then have a look at the original parent WP_Widget class and its functions in wp-includes/widgets.php. Remember that whenever you extend a class, it behooves you to look at the parent class' functions and their inputs and outputs. If this sounds like Greek to you, then the next section is for you.
Read more
  • 0
  • 0
  • 2990

article-image-silverstripe-24-customizing-layout
Packt
06 May 2011
10 min read
Save for later

SilverStripe 2.4: Customizing the Layout

Packt
06 May 2011
10 min read
Templates and themes All pages within SilverStripe are rendered using a template, which is basically an HTML/XHTML file with added control code. A template allows you to make conditional statements, create menus, access data stored in the database, and much more. Instead of using PHP for these enhancements, templates rely on a dedicated template engine. When the user accesses a page the engine replaces the control code with PHP. This transformation is then evaluated by the web server to regular markup code, which every browser can display. A theme consists of a collection of template, CSS, and image files. Design-specific JavaScript is also stored here. Together they form the layout of a page. Switching between themes You can have multiple themes and switch between them whenever you like. You're definitely encouraged to give everything described here a try. It helps you in becoming an active developer instead of a passive user. So let's get things started! Time for action - change the default theme Simply perform the following steps in the CMS and you're all set: Log into the CMS by appending /admin to your page's base URL. Provide the credentials you defined during the installation and you should be logged-in. Go to the general configuration page by clicking on the globe within the Page Tree section. The default text of this element is Your Site Name. The Theme is set to (Use default theme) by default; change this to tutorial. Click on the Save button. Go to the base URL / and reload the page. What just happened? We've successfully changed the theme of our website. It's as easy as that. Note that you need to package your theme into a subfolder of themes/ to be able to switch between them. While you can also put the contents of a theme directly into the mysite/ folder, keeping your system modularized is a good practice. Therefore we won't integrate the layout into the site specific folder and will instead always create a dedicated, switchable theme. Getting more themes After unpacking a theme, copy it to the themes/ folder, change the theme in the CMS, and you're good to go. Using a prebuilt theme really is that simple. Next, we'll take a look at the facilities for building our own themes—specifically, the template engine that powers all themes in SilverStripe. By the end of this article and next, you'll even be ready to upload and share your own themes with the rest of the community at the address above. New contributions are always welcome. Template engine As described earlier, the SilverStripe architecture consists of three layers, each serving a specific purpose. The one responsible for the layout is called View, which we'll cover in detail in this article. Another template engine? One might wonder why it is necessary to learn another template language, while there are already so many others available and PHP can do all of it as well. The main reasons behind this are: The template engine and the rest of the system fit perfectly together. After getting the hang of it, it makes the creation of templates and communication with the other layers faster and easier. The available control code is very simple. Designers without a lot of programming knowledge can create feature-rich layouts. It enforces good coding practice. Without the ability to use raw PHP, one cannot by-pass the other layers and undermine the architecture. Only layout and rendering information should be used within templates. Taking a look at BlackCandy First of all, switch back to the BlackCandy theme as we want to take a better look at it. Within your installation, navigate to the folder themes/blackcandy/ and you'll see three folders: css/, images/, and templates/. The images/ folder contains any image used in your theme; if you like, you can create subfolders to keep things organized. The remaining folders are a bit more complicated, so let's break them down. CSS At first this looks a bit messy—five files for the CSS; couldn't we use just a single one? We could, but many developers consider it a good practise splitting the functionality into different parts, making it easier to navigate later on. Sticking to this convention adds functionality as well. This is a common principle, called convention over configuration. If you do things the way they are expected by the system, you don't need to configure them specifically. Once you know the "way" of the system, you'll work much quicker than if you had to configure the same things over and over again. editor.css This file is automagically loaded by SilverStripe's what you see is what you get (WYSIWYG) editor. So if you apply the correct styling via this file, the content in the CMS' backend will look like the final output in the frontend. Additionally you'll have all custom elements available under the Styles dropdown, so the content editors don't need to mess around with pure HTML. As this file is not automatically linked to the frontend, it's common practice to put all frontend styling information into typography.css and reference that file in editor.css: @import "typography.css"; If you want to provide any styling information just for the CMS, you can put it below the @import. layout.css, form.css, and typography.css These files are automagically included in the frontend if they are available in your theme. While layout.css is used for setting the page's basic sections and layout, form.css deals with the form related styling. typography.css covers the layout of content entered into the CMS, generally being imported by editor.css as we've just discussed. Elements you will include here are headers (<h1>, <h2>, and so on), text (for example <p>), lists, tables, and others you want to use in the CMS (aligning elements, <hr>, and so on). ie6.css This file isn't part of the SilverStripe convention, but is a useful idea you might want to adopt. You must include it manually but it will still be a good idea to stick to this naming schema: ie.css for styling elements in any version of Internet Explorer, ie6.css for Internet Explorer 6 specifics, and so on. What about performance? Cutting down on the number of files being loaded is an effective optimization technique for websites. We'll take a look at how to do that. Templates Now that we've discussed the styling, let's take a look at how to put the content together with the help of templates. Learning the very basics Before we continue, some basic facts and features of templates: Templates must use the file extension .ss instead of .html or .php. Templates can be organized alongside their PHP Controllers, so you can use the same powerful mechanism as in the other layers. We'll take a better look at what this means a little later. Page controls consist of placeholders and control structures, which are both placed within the regular markup language. Placeholders start with a $ and are processed and replaced by the template engine. Control structures are written between opening <% and closing %>. They look a bit like HTML tags and they are used the same way. Some consist of a single element, like HTML's <br>, whereas others consist of two or more. Starting to use templates Now that we've covered the basics, let's put them into practice. Time for action - using site title and slogan We shall use placeholders, taking a look at the code level and how to use them in the CMS: Open the file themes/blackcandy/templates/Page.ss in your preferred editor. If the syntax highlighting is disabled due to the unknown file extension, set it to HTML. Find the two placeholders $SiteConfig.Title and $SiteConfig.Tagline in the code. Go to the general configuration page in the CMS, the one where we've changed the theme. Edit the Site title and Site Tagline/Slogan to something more meaningful. Save the page. Go to the base URL and hit refresh. If you view the page's source, you can see that the two placeholders have been replaced by the text we have just entered in the CMS. If you are wondering about the short doctype declaration: there is nothing missing, this is HTML5, which SilverStripe is already using in its default theme. If you prefer XHTML or an older HTML standard, you can freely change it. The CMS happily works with all of them. What just happened? The file we've just edited is the base template. It's used for every page (unless specifically overwritten). You can define your general layout once and don't have to repeat it again. You should always try to avoid repeating code or content. This is generally called don't repeat yourself (DRY) or duplication is evil (DIE). SilverStripe supports you very well in doing this. The site title and slogan are globally available. You can use them on every page and they share the same content across the whole website. These placeholders are prefixed with SiteConfig. as well as a $ sign. In the CMS they are all available on the site's root element, the one with the globe. By default, there are just two, but we'll later see how to add more. Other placeholders are available on specific pages or can be different on each page. We'll come to those next. Layout Looking again at the Page.ss we've just opened, you'll also see a $Layout placeholder. This is replaced by a file from the themes/blackcandy/templates/Layout folder. There are only two files available by default and for every standard page Page.ss is used. When a page is loaded, the template engine first finds the base templates/Page.ss (excluding the theme specific part of the path as this can vary). It's evaluated and the $Layout is replaced by templates/Layout/Page.ss, which is also evaluated for further SilverStripe controls. Ignore Page_results.ss for the moment. It's only used for search queries which we'll cover later. We'll also add more page types so the layout's Page.ss can then be replaced by a more specific template, while the base templates/Page.ss is always used. Includes Both Page.ss files include statements like <% include BreadCrumbs %>. These controls are replaced by files from the themes/blackcandy/templates/Includes/ folder. For example, the above include grabs the themes/blackcandy/templates/Includes/BreadCrumbs.ss file. Note that filenames are case sensitive. Otherwise you're free to select a meaningful name. Try sticking to one naming convention to make your own life easier later on, and also note that you mustn't include the <code>.ss</code> extension. If you're seeing a Filename cannot be empty error, make sure the included file really exists. Have a go hero - using page name, navigation label, and metadata title Now that we've explored all available files and how they are used, let's take a better look at the system. In the CMS backend, go to the Home page. Change the text currently entered into Page name, Navigation label (both in the Main tab), and Title (Metadata tab). Take a look at: Where on the page they are used In which file they are located (take a look at all three possible locations) What template placeholders represent them You might notice $MetaTitle, $Title, and $MenuTitle in your template files (for the moment ignore the appended .XML). We will explore these later on.
Read more
  • 0
  • 0
  • 2456
article-image-installing-microsoft-dynamics-nav
Packt
06 May 2011
4 min read
Save for later

Installing Microsoft Dynamics NAV

Packt
06 May 2011
4 min read
The installation of Dynamics NAV Classic components remains more or less similar to the Dynamics NAV 5.0 version. Thus, in this article, we have used the NAV 5.0 version for installation of Dynamics NAV Classic components and the Dynamics NAV 2009 SP1 version for installation of RTC and the other new components introduced after the release of NAV 2009. Installing a Classic client Classic client installation, also called a C/SIDE client, is more or less the same for all the versions of Navision Financials, Navision, Microsoft Business Solutions—Navision, or Dynamics NAV. We have illustrated an example of 5.0 SP1 Dynamics NAV C/SIDE client installations as follows: Starting with the startup screen of the installation disk, the process is fairly easy and well defined through the various installation stages. Click on C/SIDE Client for Microsoft Dynamics NAV under the Install section of the screen to run the installation wizard. If we want to install multiple versions of NAV on the same machine, there is a work around to do that. Install the latest version and copy the client (C:program filesMicrosoft Dynamics NAV...) folder(s) for the rest of the versions that we want to use. Once we have copied the client files, use fin.exe or finsql.exe to run the appropriate version of Dynamics NAV; this is not supported by the standard product and must not be used in a client production environment. The installation process takes us through the setup wizard. In a network installation, we would typically select Minimum as the Install option. This needs the least amount of disk space. We can also select this option if we need just the client executables.   If we select Custom, we will get a few options to select from the following: Help: This is the option for installing Dynamics NAV Online Help. It is recommended to have this option always on. Demo Database: This is the option to install a demonstration database with the CRONUS company. This is not needed typically in a network installation. We may need to install this option in a single user installation. Backup of Demo Database: If selected, this option will copy a backup (.fbk file) of the demo database to the program folder. Commerce Integration, Employee Portal: These options need to be selected if we are installing Employee Portal, Commerce Gateway, or Commerce portal (discontinued now) components. Business Notification Manager: This is the option to send automatic business event notifications from NAV. Outlook Integration: This feature installs components for Dynamics NAV and Microsoft Outlook Integration. This also installs a toolbar in Microsoft Outlook. Gantt Server: The OLAP component that facilitates management of shop floor production using visual status updates and plans. There is also the option to change the installation path, by clicking on the Change... button at the bottom. The following are some of the key program files and what they do: Fin.exe: This is a client executable for the Microsoft Dynamics NAV C/SIDE client. Finsql.exe: This is a client executable for the Microsoft Dynamics NAV C/SIDE client for SQL Server option. CRONUS.flf: This file and the files with extension .flf are the license files for Microsoft Dynamics NAV and are responsible for granting appropriate access to the application areas, based on what has been bought from Microsoft. Fin.stx: The local settings, system menu captions, and regional settings are kept as system text in the .stx file. Fin.etx: The error messages for the system errors and not the application errors generated by business logic are stored in this error text file. Database.fdb: This is the Microsoft Dynamics Classic database file. Database.fbk: This is the Microsoft Dynamics Classic database backup. The wonders of the ZUP file are as follows: In the versions prior to Microsoft Dynamics NAV 2009, all local client settings such as column widths, report filters, and displayed form columns, were stored in the .zup file for the users on their local application data folder. A parameter for client executables fin.exe, fin sql.exe—ID=<name> saves the ZUP file with this ID, thus providing the ability to group the ZUP files together and giving the ability to back up different ZUP files. In the Dynamics NAV 2009 RoleTailored client version, the .zup file is replaced by the following files and tables where the local settings are stored: ClientUserSettings.Config PersonalizationStore.xml CustomSettings.config Table 2000000075 User Metadata Table 2000000071 Object Metadata Upwards compatibility: It is recommended to upgrade the client executables to the latest version, if not the database. However, with NAV 2009 this may not be true.
Read more
  • 0
  • 0
  • 3909

article-image-plotting-data-sage
Packt
05 May 2011
14 min read
Save for later

Plotting Data with Sage

Packt
05 May 2011
14 min read
Sage Beginner's Guide Unlock the full potential of Sage for simplifying and automating mathematical computing Confusion alert: Sage plots and matplotlib The 2D plotting capabilities of Sage are built upon a Python plotting package called matplotlib. The most widely used features of matplotlib are accessible through Sage functions. You can also import the matplotlib package into Sage, and use all of its features directly. This is very powerful, but it's also confusing, because there's more than one way to do the same thing. To further add to the confusion, matplotlib has two interfaces: the command-oriented Pyplot interface and an object-oriented interface. The examples in this chapter will attempt to clarify which interface is being used. Plotting in two dimensions Two-dimensional plots are probably the most important tool for visually presenting information in math, science, and engineering. Sage has a wide variety of tools for making many types of 2D plots. Plotting symbolic expressions with Sage We will start by exploring the plotting functions that are built in to Sage. They are generally less flexible than using matplotlib directly, but also tend to be easier to use. Time for action – plotting symbolic expressions Let's plot some simple functions. Enter the following code: p1 = plot(sin, (-2*pi, 2*pi), thickness=2.0, rgbcolor=(0.5, 1, 0), legend_label='sin(x)') p2 = plot(cos, (-2*pi, 2*pi), thickness=3.0, color='purple', alpha=0.5, legend_label='cos(x)') plt = p1 + p2 plt.axes_labels(['x', 'f(x)']) show(plt) If you run the code from the interactive shell, the plot will open in a separate window. If you run it from the notebook interface, the plot will appear below the input cell. In either case, the result should look like this: What just happened? This example demonstrated the most basic type of plotting in Sage. The plot function requires the following arguments: graphics_object = plot(callable symbolic expression, (independent_var, ind_var_min, ind_var_max)) The first argument is a callable symbolic expression, and the second argument is a tuple consisting of the independent variable, the lower limit of the domain, and the upper limit. If there is no ambiguity, you do not need to specify the independent variable. Sage automatically selects the right number of points to make a nice curve in the specified domain. The plot function returns a graphics object. To combine two graphics objects in the same image, use the + operator: plt = p1 + p2. Graphics objects have additional methods for modifying the final image. In this case, we used the axes_labels method to label the x and y axes. Finally, the show function was used to finish the calculation and display the image. The plot function accepts optional arguments that can be used to customize the appearance and format of the plot. To see a list of all the options and their default values, type: sage: plot.options {'fillalpha': 0.5, 'detect_poles': False, 'plot_points': 200, 'thickness': 1, 'alpha': 1, 'adaptive_tolerance': 0.01, 'fillcolor': 'automatic', 'adaptive_recursion': 5, 'exclude': None, 'legend_label': None, 'rgbcolor': (0, 0, 1), 'fill': False} Here is a summary of the options for customizing the appearance of a plot: KeywordDescriptionalphaTransparency of the line (0=opaque, 1=transparent)fillTrue to fill area below the linefillalphaTransparency of the filled-in area (0=opaque, 1=transparent)fillcolorColor of the filled-in areargbcolorColor of the line Sage uses an algorithm to determine the best number of points to use for the plot, and how to distribute them on the x axis. The algorithm uses recursion to add more points to resolve regions where the function changes rapidly. Here are the options that control how the plot is generated: KeywordDescriptionadaptive_recursionMax depth of recursion when resolving areas of the plot where the function changes rapidlyadaptive_toleranceTolerance for stopping recursiondetect_polesDetect points where function value approaches infinity (see next example)excludeA list or tuple of points to exclude from the plotplot_pointsNumber of points to use in the plot Specifying colors in Sage There are several ways to specify a color in Sage. For basic colors, you can use a string containing the name of the color, such as red or blue. You can also use a tuple of three floating-point values between 0 and 1.0. The first value is the amount of red, the second is the amount of green, and the third is the amount of blue. For example, the tuple (0.5, 0.0, 0.5) represents a medium purple color. Some functions "blow up" to plus or minus infinity at a certain point. A simplistic plotting algorithm will have trouble plotting these points, but Sage adapts. Time for action – plotting a function with a pole Let's try to plot a simple function that takes on infinite values within the domain of the plot: pole_plot = plot(1 / (x - 1), (0.8, 1.2), detect_poles='show', marker='.') print("min y = {0} max y = {1}".format(pole_plot.ymax(), pole_plot.ymin())) pole_plot.ymax(100.0) pole_plot.ymin(-100.0) # Use TeX to make nicer labels pole_plot.axes_labels([r'$x$', r'$1/(x-1)$']) pole_plot.show() The output from this code is as follows: What just happened? We did a few things differently compared to the previous example. We defined a callable symbolic expression right in the plot function. We also used the option detect_poles='show' to plot a dashed vertical line at the x value where the function returns infinite values. The option marker='.' tells Sage to use a small dot to mark the individual (x,y) values on the graph. In this case, the dots are so close together that they look like a fat line. We also used the methods ymin and ymax to get and set the minimum and maximum values of the vertical axis. When called without arguments, these methods return the current values. When given an argument, they set the minimum and maximum values of the vertical axis. Finally, we labeled the axes with nicely typeset mathematical expressions. As in the previous example, we used the method axes_labels to set the labels on the x and y axes. However, we did two special things with the label strings: r'$frac{1}{(x-1)}$' The letter r is placed in front of the string, which tells Python that this is a raw string. When processing a raw string, Python does not interpret backslash characters as commands (such as interpreting n as a newline). Note that the first and last characters of the string are dollar signs, which tells Sage that the strings contain mark-up that needs to be processed before being displayed. The mark-up language is a subset of TeX, which is widely used for typesetting complicated mathematical expressions. Sage performs this processing with a built-in interpreter, so you don't need to have TeX installed to take advantage of typeset labels. It's a good idea to use raw strings to hold TeX markup because TeX uses a lot of backslashes. To learn about the typesetting language, see the matplotlib documentation at: http://matplotlib.sourceforge.net/users/mathtext.html Time for action – plotting a parametric function Some functions are defined in terms of a parameter. Sage can easily plot parametric functions: var('t') pp = parametric_plot((cos(t), sin(t)), (t, 0, 2*pi), fill=True, fillcolor='blue') pp.show(aspect_ratio=1, figsize=(3, 3), frame=True) The output from this code is as follows: What just happened? We used two parametric functions to plot a circle. This is a convenient place to demonstrate the fill option, which fills in the space between the function and the horizontal axis. The fillcolor option tells Sage which color to use for the fill, and the color can be specified in the usual ways. We also demonstrated some useful options for the show method (these options also work with the show function). The option aspect_ratio=1 forces the x and y axes to use the same scale. In other words, one unit on the x axis takes up the same number of pixels on the screen as one unit on the y axis. Try changing the aspect ratio to 0.5 and 2.0, and see how the circle looks. The option figsize=(x_size,y_size) specifies the aspect ratio and relative size of the figure. The units for the figure size are relative, and don't correspond to an absolute unit like inches or centimetres. The option frame=True places a frame with tick marks around the outside of the plot. Time for action – making a polar plot Some functions are more easily described in terms of angle and radius. The angle is the independent variable, and the radius at that angle is the dependent variable. Polar plots are widely used in electrical engineering to describe the radiation pattern of an antenna. Some antennas are designed to transmit (or receive) electromagnetic radiation in a very narrow beam. The beam shape is known as the radiation pattern. One way to achieve a narrow beam is to use an array of simple dipole antennas, and carefully control the phase of the signal fed to each antenna. In the following example, we will consider seven short dipole antennas set in a straight line: # A linear broadside array of short vertical dipoles # located along the z axis with 1/2 wavelength spacing var('r, theta') N = 7 normalized_element_pattern = sin(theta) array_factor = 1 / N * sin(N * pi / 2 * cos(theta)) / sin(pi / 2 * cos(theta)) array_plot = polar_plot(abs(array_factor), (theta, 0, pi), color='red', legend_label='Array') radiation_plot = polar_plot(abs(normalized_element_pattern * array_factor), (theta, 0, pi), color='blue', legend_label='Radiation') combined_plot = array_plot + radiation_plot combined_plot.xmin(-0.25) combined_plot.xmax(0.25) combined_plot.set_legend_options(loc=(0.5, 0.3)) show(combined_plot, figsize=(2, 5), aspect_ratio=1) Execute the code. You should get a plot like this: What just happened? We plotted a polar function, and used several of the plotting features that we've already discussed. There are two subtle points worth mentioning. The function array_factor is a function of two variables, N and theta. In this example, N is more like a parameter, while theta is the independent variable we want to use for plotting. We use the syntax (theta, 0, pi) in the plot function to indicate that theta is the independent variable. The second new aspect of this example is that we used the methods xmin and xmax to set the limits of the x axis for the graphics object called combined_plot. We also used the set_legend_options of the graphics object to adjust the position of the legend to avoid covering up important details of the plot. Time for action – plotting a vector field Vector fields are used to represent force fields such as electromagnetic fields, and are used to visualize the solutions of differential equations. Sage has a special plotting function to visualize vector fields. var('x, y') a = plot_vector_field((x, y), (x, -3, 3), (y, -3, 3), color='blue') b = plot_vector_field((y, -x), (x, -3, 3), (y, -3, 3), color='red') show(a + b, aspect_ratio=1, figsize=(4, 4)) You should get the following image: What just happened? The plot_vector_field function uses the following syntax: plot_vector_field((x_function,y_function), (x,x_min,x_max), (y,y_ min,y_max)) The keyword argument color specifies the color of the vectors. Plotting data in Sage So far, we've been making graphs of functions. We specify the function and the domain, and Sage automatically chooses the points to make a nice-looking curve. Sometimes, we need to plot discrete data points that represent experimental measurements or simulation results. The following functions are used for plotting defined sets of points. Time for action – making a scatter plot Scatter plots are used in science and engineering to look for correlation between two variables. A cloud of points that is roughly circular indicates that the two variables are independent, while a more elliptical arrangement indicates that there may be a relationship between them. In the following example, the x and y coordinates are contrived to make a nice plot. In real life, the x and y coordinates would typically be read in from data files. Enter the following code: def noisy_line(m, b, x): return m * x + b + 0.5 * (random() - 0.5) slope = 1.0 intercept = -0.5 x_coords = [random() for t in range(50)] y_coords = [noisy_line(slope, intercept, x) for x in x_coords] sp = scatter_plot(zip(x_coords, y_coords)) sp += line([(0.0, intercept), (1.0, slope+intercept)], color='red') sp.show() The result should look similar to this plot. Note that your results won't match exactly, since the point positions are determined randomly. What just happened? We created a list of randomized x coordinates using the built-in random function. This function returns a random number in the range 0 <= x < 1. We defined a function called noisy_line that we then used to create a list of randomized y coordinates with a linear relationship to the x coordinates. We now have a list of x coordinates and a list of y coordinates, but the scatter_plot function needs a list of (x,y) tuples. The zip function takes the two lists and combines them into a single list of tuples. The scatter_plot function returns a graphics object called sp. To add a line object to the plot, we use the following syntax: sp += line([(x1, y1), (x2,y2)], color='red') The += operator is a way to increment a variable; x+=1 is a shortcut for x = x + 1. Because the + operator also combines graphics objects, this syntax can be used to add a graphics object to an existing graphics object. Time for action – plotting a list Sometimes, you need to plot a list of discrete data points. The following example might be found in an introductory digital signal processing (DSP) course. We will use lists to represent digital signals. We sample the analogue function cosine(t) at two different sampling rates, and plot the resulting digital signals. # Use list_plot to visualize digital signals # Undersampling and oversampling a cosine signal sample_times_1 = srange(0, 6*pi, 4*pi/5) sample_times_2 = srange(0, 6*pi, pi/3) data1 = [cos(t) for t in sample_times_1] data2 = [cos(t) for t in sample_times_2] plot1 = list_plot(zip(sample_times_1, data1), color='blue') plot1.axes_range(0, 18, -1, 1) plot1 += text("Undersampled", (9, 1.1), color='blue', fontsize=12) plot2 = list_plot(zip(sample_times_2, data2), color='red') plot2.axes_range(0, 18, -1, 1) plot2 += text("Oversampled", (9, 1.1), color='red', fontsize=12) g = graphics_array([plot1, plot2], 2, 1) # 2 rows, 1 column g.show(gridlines=["minor", False]) The result is as follows: What just happened? The function list_plot works a lot like scatter_plot from the previous example, so I won't explain it again. We used the method axes_range(x_min, x_max, y_min, y_max) to set the limits of the x and y axes all at once. Once again, we used the += operator to add a graphics object to an existing object. This time, we added a text annotation instead of a line. The basic syntax for adding text at a given (x,y) position is text('a string', (x,y)). To see the options that text accepts, type the following: sage: text.options {'vertical_alignment': 'center', 'fontsize': 10, 'rgbcolor': (0, 0, 1), 'horizontal_alignment': 'center', 'axis_coords': False} To display the two plots, we introduced a new function called graphics_array, which uses the basic syntax: graphics_array([plot_1, plot_2, ..., plot_n], num_rows, num_columns) This function returns another graphics object, and we used the show method to display the plots. We used the keyword argument gridlines=["minor", False] to tell Sage to display vertical lines at each of the minor ticks on the x axis. The first item in the list specifies vertical grid lines, and the second specifies horizontal grid lines. The following options can be used for either element: "major"Grid lines at major ticks"minor"Grid lines at major and minor ticksFalseNo grid lines Try playing with these options in the previous example.  
Read more
  • 0
  • 0
  • 25149
Modal Close icon
Modal Close icon