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
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials - Front-End Web Development

341 Articles
article-image-being-cross-platform-haxe
Packt
26 Jul 2011
10 min read
Save for later

Being Cross-platform with haXe

Packt
26 Jul 2011
10 min read
  haXe 2 Beginner's Guide Develop exciting applications with this multi-platform programming language What is cross-platform in the library The standard library includes a lot of classes and methods, which you will need most of the time in a web application. So, let's have a look at the different features. What we call standard library is simply a set of objects, which is available when you install haXe. Object storage The standard library offers several structures in which you can store objects. In haXe, you will see that, compared to many other languages, there are not many structures to store objects. This choice has been made because developers should be able to do what they need to do with their objects instead of dealing with a lot of structures, which they have to cast all the time. The basic structures are array, list, and hash. All of these have a different utility: Objects stored in an array can be directly accessed by using their index Objects in a list are linked together in an ordered way Objects in an hash are tied to what are called "keys", but instead of being an Int, keys are a String There is also the IntHash structure that is a hash-table using Int values as keys. These structures can be used seamlessly in all targets. This is also, why the hash only supports String as indexes: some platforms would require a complex class that would impair performances to support any kind of object as indexes. The Std class The Std class is a class that contains methods allowing you to do some basic tasks, such as parsing a Float or an Int from a String, transforming a Float to an Int, or obtaining a randomly generated number. This class can be used on all targets without any problems. The haxe package The haxe package (notice the lower-case x) contains a lot of class-specific to haXe such as the haxe.Serializer class that allows one to serialize any object to the haXe serialization format or its twin class haxe.Unserializer that allows one to unserialize objects (that is "reconstruct" them). This is basically a package offering extended cross-platform functionalities. The classes in the haxe package can be used on all platforms most of the time. The haxe.remoting package This package also contains a remoting package that contains several classes allowing us to use the haXe remoting protocol. This protocol allows several programs supporting it to communicate easily. Some classes in this package are only available for certain targets because of their limitations. For example, a browser environment won't allow one to open a TCP socket, or Flash won't allow one to create a server. Remoting will be discussed later, as it is a very interesting feature of haXe. The haxe.rtti package There's also the rtti package. RTTI means Run Time Type Information. A class can hold information about itself, such as what fields it contains and their declared types. This can be really interesting in some cases, such as, if you want to create automatically generated editors for some objects. The haxe.Http class The haxe.Http class is one you are certainly going to use quite often. It allows you to make HTTP requests and retrieve the answer pretty easily without having to deal with the HTTP protocol by yourself. If you don't know what HTTP is, then you should just know that it is the protocol used between web browsers and servers. On a side-note, the ability to make HTTPS requests depends on the platform. For example, at the moment, Neko doesn't provide any way to make one, whereas it's not a problem at all on JS because this functionality is provided by the browser. Also, some methods in this class are only available on some platforms. That's why, if you are writing a cross-platform library or program, you should pay attention to what methods you can use on all the platforms you want to target. You should note that on JS, the haxe.Http class uses HttpRequest objects and as such, they suffer from security restrictions, the most important one being the same-domain policy. This is something that you should keep in mind, when thinking about your solution's architecture. You can make a simple synchronous request by writing the following: var answer = Http.requestUrl("http://www.benjamindasnois.com"); It is also possible to make some asynchronous requests as follows: var myRequest = new Http("http://www.benjamindasnois.com"); myRequest.onData = function (d : String) { Lib.println(d); } myRequest.request(false); This method also allows you to get more information about the answer, such as the headers and the return code. The following is an example displaying the answer's headers: import haxe.Http; #if neko import neko.Lib; #elseif php import php.Lib; #end class Main { static function main() { var myRequest = new Http("http://www.benjamindasnois.com"); myRequest.onData = function (d : String) { for (k in myRequest.responseHeaders.keys()) { Lib.println(k + " : " + myRequest.responseHeaders.get(k)); } }; myRequest.request(false); } } The following is what it displays: X-Cache : MISS from rack1.tumblr.com X-Cache-Lookup : MISS from rack1.tumblr.com:80 Via : 1.0 rack1.tumblr.com:80 (squid/2.6.STABLE6) P3P : CP="ALL ADM DEV PSAi COM OUR OTRo STP IND ONL" Set-Cookie : tmgioct=h6NSbuBBgVV2IH3qzPEPPQLg; expires=Thu, 02-Jul-2020 23:30:11 GMT; path=/; httponly ETag : f85901c583a154f897ba718048d779ef Link : <http://assets.tumblr.com/images/default_avatar_16.gif>; rel=icon Vary : Accept-Encoding Content-Type : text/html; charset=UTF-8 Content-Length : 30091 Server : Apache/2.2.3 (Red Hat) Date : Mon, 05 Jul 2010 23:31:10 GMT X-Tumblr-Usec : D=78076 X-Tumblr-User : pignoufou X-Cache-Auto : hit Connection : close Regular expressions and XML handling haXe offers a cross-platform API for regular expressions and XML that can be used on most targets' target. Regular expressions The regular expression API is implemented as the EReg class. You can use this class on any platform to match a RegExp, split a string according to a RegExp, or do some replacement. This class is available on all targets, but on Flash, it only starts from Flash 9. The following is an example of a simple function that returns true or false depending on if a RegExp matches a string given as parameter: public static function matchesHello(str : String) : Bool { var helloRegExp = ~/.*hello.*/; return helloRegExp.match(str); } One can also replace what is matched by the RegExp and return this value. This one simply replaces the word "hello" with "bye", so it's a bit of an overkill to use a RegExp to do that, and you will find some more useful ways to use this possibility when making some real programs. Now, at least you will know how to do it: public static function replaceHello(str : String) : String { var helloRegExp = ~/hello/; helloRegExp.match(str); return helloRegExp.replace(str, "bye"); } XML handling The XML class is available on all platforms. It allows you to parse and emit XML the same way on many targets. Unfortunately, it is implemented using RegExp on most platforms, and therefore can become quite slow on big files. Such problems have already been raised on the JS targets, particularly on some browsers, but you should keep in mind that different browsers perform completely differently. For example, on the Flash platform, this API is now using the internal Flash XML libraries, which results in some incompatibilities. The following is an example of how to create a simple XML document: <pages> <page id="page1"/> <page id="page2"/> </pages> Now, the haXe code to generate it: var xmlDoc : Xml; var xmlRoot : Xml; xmlDoc = Xml.createDocument(); //Create the document xmlRoot = Xml.createElement("pages"); //Create the root node xmlDoc.addChild(xmlRoot); //Add the root node to the document var page1 : Xml; page1 = Xml.createElement("page"); //create the first page node page1.set("id", "page1"); xmlRoot.addChild(page1); //Add it to the root node var page2 : Xml; page2 = Xml.createElement("page"); page2.set("id", "page2"); xmlRoot.addChild(page2); trace(xmlDoc.toString()); //Print the generated XML Input and output Input and output are certainly the most important parts of an application; indeed, without them, an application is almost useless. If you think about how the different targets supported by haXe work and how the user may interact with them, you will quickly come to the conclusion that they use different ways of interacting with the user, which are as follows: JavaScript in the browser uses the DOM Flash has its own API to draw on screen and handle events Neko uses the classic input/output streams (stdin, stdout, stderr) and so do PHP and C++ So, we have three different main interfaces: DOM, Flash, and classic streams. The DOM interface The implementation of the DOM interface is available in the js package. This interface is implemented through typedefs. Unfortunately, the API doesn't provide any way to abstract the differences between browsers and you will have to deal with them in most cases by yourself. This API is simply telling the compiler what objects exist in the DOM environment; so, if you know how to manipulate the DOM in JavaScript, you will be able to manipulate it in haXe. The thing that you should know is that the document object can be accessed through js.Lib.document. The js package is accessible only when compiling to JS. The Flash interface In a way that is similar to how the Flash is implemented in the flash and flash9 packages, the js package implements the DOM interface. When reading this sentence, you may wonder why there are two packages. The reason is pretty simple, the Flash APIs pre and post Flash 9 are different. You also have to pay attention to the fact that, when compiling to Flash 9, the flash9 package is accessible through the flashpath and not through flash9. Also, at the time of writing, the documentation for flash and flash9 packages on haxe. org is almost non-existent; but, if you need some documentation, you can refer to the official documentation. The standard input/output interface The standard input/output interface refers to the three basic streams that exist on most systems, which are as follows: stdin (most of the time the keyboard). stdout (the standard output which is most of the time the console, or, when running as a web-application, the stream sent to the client). stderr (the standard error output which is most of the time directed to the console or the log file). Neko, PHP and C++ all make use of this kind of interface. Now, there are two pieces news for you: one good and one bad. The bad one is that the API for each platform is located in a platform-specific package. So, for example, when targeting Neko, you will have to use the neko package, which is not available in PHP or C++. The good news is that there is a workaround. Well, indeed, there are three. You just have to continue reading through this article and I'll tell you how to handle that.  
Read more
  • 0
  • 0
  • 1359

article-image-mootools-extending-and-implementing-elements
Packt
25 Jul 2011
7 min read
Save for later

MooTools: Extending and Implementing Elements

Packt
25 Jul 2011
7 min read
  MooTools 1.3 Cookbook Over 100 highly effective recipes to turbo-charge the user interface of any web-enabled Internet application and web page The reader can benefit from the previous article on Extending MooTools. Extending elements—preventing multiple form submissions Imagine a scenario where click-happy visitors may undo normalcy by double-clicking the submit button, or perhaps an otherwise normal albeit impatient user might click it a second time. Submit buttons frequently need to be disabled or removed using client-side code for just such a reason. Users that double-click everything It is not entirely known where double-clicking users originated from. Some believe that single-clicking-users needed to be able to double-click to survive in the wild. They therefore began to grow gills and double-click links, buttons, and menu items. Others maintain that there was a sudden, large explosion in the vapors of nothingness that resulted in hordes of users that could not fathom the ability of a link, button, or menu item that could be opened with just a single click. Either way, they are out there, and they mostly use Internet Explorer and are quickly identifiable by how they type valid URLs into search bars and then swear the desired website is no longer on the Inter-nets. How to do it... Extending elements uses the same syntax as extending classes. Add a method that can be called when appropriate. Our example, the following code, could be used in a library that is associated with every page so that no submit button could ever again be clicked twice, at least, without first removing the attribute that has it disabled: Element.implement({ better_submit_buttons: function() { if ( this.get('tag')=='input' && this.getProperty('type')=='submit') { this.addEvent('click', function(e) { this.set({ 'disabled':'disabled', 'value':'Form Submitted!' }); }); } } }); window.addEvent('load',function() { $$('input[type=submit]').better_submit_buttons(); }); How it works... The MooTools class Element extends DOM elements referenced by the single-dollar selector, the double-dollars selector, and the document.id selector. In the onLoad event, $$('input[type=submit]').submit_only_once(); all INPUT elements that have a type equal to submit are extended with the Element class methods and properties. Of course, before that infusion of Moo-goodness takes place, we have already implemented a new method that prevents those elements from being clicked twice by adding the property that disables the element. There's more... In our example, we disable the submit button permanently and return false upon submission. The only way to get the submit button live again is to click the Try again button that calls the page again. Note that reloading the page via refresh in some browsers may not clear the disabled attribute; however, calling the page again from the URL or by clicking a link will. On pages that submit a form to a second page for processing, the semi-permanently disabled button is desirable outright. If our form is processed via Ajax, then we can use the Ajax status events to manually remove the disabled property and reset the value of the button. See also Read the document on the MooTools Request class that shows the various statuses that could be used in conjunction with this extended element: http://mootools.net/docs/core/Request/Request.   Extending elements-prompt for confirmation on submit Launching off the last extension, the forms on our site may also need to ask for confirmation. It is not unthinkable that a slip of the carriage return could accidentally submit a form before a user is ready. It certainly happens to all of us occasionally and perhaps to some of us regularly. How to do it... Mutate the HTML DOM FORM elements to act upon the onSubmit event and prompt whether to continue with the submission. Element.implement({ polite_forms: function() { if (this.get('tag')=='form') { this.addEvent('submit',function(e) { if(!confirm('Okay to submit form?')) { e.stop(); } }); } } }); How it works... The polite_forms() method is added to all HTML DOM elements, but the execution is restricted to elements whose tag is form, if (this.get('tag')=='form') {...}. The onSubmit event of the form is bound to a function that prompts users via the raw JavaScript confirm() dialogue that either returns true for a positive response or false otherwise. If false, then we prevent the event from continuing by calling the MooTools-implemented Event.stop(). There's more... In order to mix the submit button enhancement with the polite form enhancement only a few small changes to the syntax are necessary. To stop our submit button from showing in process... if the form submission is canceled by the polite form request, we create a proprietary reset event that can be called via Element.fireEvent() and chained to the collection of INPUT children that match our double-dollar selector. // extend all elements with the method polite forms Element.implement({ better_submit_buttons: function() { if (this.get('tag')=='input'&&this.getProperty('type')=='submit') { this.addEvents({ 'click':function(e) { this.set({'disabled':'disabled','value':'in process...'}); }, 'reset':function() { this.set({'disabled':false,'value':'Submit!'}); } }); } }, polite_forms: function() { if (this.get('tag')=='form') { this.addEvent('submit',function(e) { if(!confirm('Okay to submit form?')) { e.stop(); this.getChildren('input[type=submit]').fireEvent('reset'); } }); } } }); // enhance the forms window.addEvent('load',function() { $$('input[type=submit]').better_submit_buttons(); $$('form').polite_forms(); });   Extending typeOf, fixing undefined var testing We could not properly return the type of an undeclared variable. This oddity has its roots in the fact that undefined, undeclared variables cannot be dereferenced during a function call. In short, undeclared variables can not be used as arguments to a function. Getting ready Get ready to see how we can still extend MooTools' typeOf function by passing a missing variable using the global scope: // will throw a ReferenceError myfunction(oops_var); // will not throw a ReferenceError myfunction(window.oops_var); How to do it... Extend the typeOf function with a new method and call that rather than the parent method. // it is possible to extend functions with new methods typeOf.extend('defined',function(item) { if (typeof(item)=='undefined') return 'undefined'; else return typeOf(item); }); //var oops_var; // commented out "on purpose" function report_typeOf(ismoo) { if (ismoo==0) { document.write('oops_var1 is: '+typeof(oops_var)+'<br/>'); } else { // concat parent to avoid error from derefrencing an undeclared var document.write('oops_var2 is: '+typeOf.defined( window.oops_var)+'<br/>'); } } The output from calling typeof() and typeOf.defined() is identical for an undefined, undeclared variable passed via the global scope to avoid a reference error. <h2>without moo:</h2> <script type="text/javascript"> report_typeOf(0); </script> <h2><strong>with</strong> moo:</h2> <script type="text/javascript"> report_typeOf(1); </script> The output is: without moo: oops_var1 is: undefined with moo: oops_var2 is: undefined How it works... The prototype for the typeOf function object has been extended with a new method. The original method is still applied when the function is executed. However, we are now able to call the property defined, which is itself a function that can still reference and call the original function. There's more... For those that are not satisfied at the new turn of syntax, the proxy pattern should suffice to help keep us using a much similar syntax. // proxying in raw javascript is cleaner in this case var oldTypeOf = typeOf; var typeOf = function(item) { if (typeof(item)=='undefined') return 'undefined'; else return oldTypeOf(item); }; The old typeOf function has been renamed using the proxy pattern but is still available. Meanwhile, all calls to typeOf are now handled by the new version. See also The Proxy Pattern The proxy pattern is one of many JavaScript design patterns. Here is one good link to follow for more information: http://www.summasolutions.net/blogposts/design-patterns-javascript-part-1. Undeclared and Undefined Variables It can be quite daunting to have to deal with multiple layers of development. When we are unable to work alone and be sure all our variables are declared properly, testing every one can really cause code bloat. Certainly, the best practice is to always declare variables. Read more about it at http://javascriptweblog.wordpress.com/2010/08/16/understanding-undefined-and-preventing-referenceerrors/.  
Read more
  • 0
  • 0
  • 1070

article-image-extending-mootools
Packt
25 Jul 2011
8 min read
Save for later

Extending MooTools

Packt
25 Jul 2011
8 min read
  MooTools 1.3 Cookbook Over 100 highly effective recipes to turbo-charge the user interface of any web-enabled Internet application and web page         Read more about this book       (For more resources on this topic, see here.) The reader can benefit from the previous article on MooTools: Extending and Implementing Elements.   Making a Corvette out of a car-extending the base class The "base class" is a function, a method, that allows extension. Just what does extending a class entail? Buckle up and let us take a drive. Getting ready Just to show the output of our work, create a DIV that will be our canvas. <div id="mycanvas"></div> How to do it... Creating a class from the base class is as rudimentary as this: var Car = new Class();. That is not very instructive, so at the least, we add the constructor method to call at the time of instantiation: initialize. <script type="text/javascript"> var Car = new Class({ initialize: function(owner) { this.owner = owner; }}); The constructor method takes the form of a property named initialize and must be a function; however, it does not have to be the first property declared in the class. How it works... So far in our recipe, we have created an instance of the base class and assigned it to the variable Car. We like things to be sporty, of course. Let's mutate the Car into a Corvette using Extends and passing it the name of the Class to make a copy of and extend into a new class. var Corvette = new Class({ Extends: Car, mfg: 'Chevrolet', model: 'Corvette', setColor: function(color) { this.color = color; }}); Our Corvette is ready for purchase. An instantiation of the extended class will provide some new owner happiness for 5 years or 50,000 miles, whichever comes first. Make the author's red, please. var little_red = new Corvette('Jay Johnston'); little_red.setColor('red'); $('mycanvas').set('text',little_red.owner+"'s little "+little_red.color+' '+little_red.model+' made by '+little_red.mfg); </script> There's more... This entire example will work identically if Corvette Implements rather than Extends Car. Whether to Extend or to Implement Extending a class changes the prototype, creating a copy in which the this.parent property allows for the overridden parent class method to be referenced within the extended class's current method. To derive a mutation that takes class properties from multiple classes, we use Implements. Be sure to place the Extends or Implements property first before all other methods and properties. And if both extending and implementing, the Implements property follows the Extends property. See also See how Moo can muster so much class: http://mootools.net/docs/core/Class/Class#Class.   Giving a Corvette a supercharger-Implements versus Extends Be ready to watch for several things in this recipe. Firstly, note how the extended corvette methods can use this.parent. Secondly, note how the implemented corvette, the ZR1, can implement multiple classes. Getting ready Create a canvas to display some output. <h1>Speed Indexes:</h1><div id="mycanvas"></div> How to do it... Here we create a class to represent a car. This car does not have an engine until it goes through further steps of manufacturing, so if we ask what its speed is, the output is zero. Next, we create a class to represent a sporty engine, which has an arbitrary speed index of 10. // create two classes from the base Class var Car = new Class({ showSpeed: function() { return 0; } }); var SportyEngine = new Class({ speed: 10 }); Now we get to work. First, we begin by manufacturing corvettes, a process which is the extension of Car, they are faster than an empty chassis, of course, so we have them report their speed as an index rating one more than the parent class. // Extend one, Implement the other var Corvette = new Class({ Extends: Car, showSpeed: function() { // this.parent calls the overridden class return this.parent()+1; } }); Secondly, we implement both Car and SportyEngine simultaneously as ZR1. We cannot use this.parent so we return the speed if asked. Of course, the ZR1 would not have a speed if only a mutation of Car, but since it is also a mutation of SportyEngine it has the speed index of that class. var ZR1 = new Class({ // multiple classes may be implemented Implements: [Car, SportyEngine], // yep showSpeed: function() { // this.parent is not available //return this.parent()+1; // nope return this.speed; }}); How it works... When an instantiation of Corvette is created and its showSpeed() method called, it reports the speed of the parent class, Car, adding 1 to it. This is thanks to the magic Extends provides via this.parent(). var corvette = new Corvette(); var zr1 = new ZR1(); $('mycanvas').set('html', '<table>'+ '<tr><th>Corvette:</th>'+ '<td>'+corvette.showSpeed()+'</td></tr>'+ '<tr><th>ZR1:</th>'+ '<td>'+zr1.showSpeed()+'</td></tr>'+ '</table>'); And so, the output of this would be: Corvette: 1ZR1: 10 An instantiation of ZR1 has the properties of all classes passed to Implements. When showSpeed() is called, the value conjured by this.speed comes from the property defined within SportyEngine.   Upgrading some Corvettes—Extends versus Implements Now that we have reviewed some of the reasons to extend versus implement, we are ready to examine more closely how inheritance within Extends can be useful in our scripting. Getting ready Create a display area for the output of our manufacturing plant. <h1>Speeds Before</h1><div id="before"></div><h1>Speeds After</h1><div id="after"></div> How to do it... Create two classes, one that represents all car chassis with no engine and one that represents a fast engine that can be ordered as an upgrade. This section is identical to the last recipe; if necessary, review once more before continuing as the jist will be to alter our instantiations to display how inheritance patterns affect them. // create two classes from the base Class var Car = new Class({ showSpeed: function() { return 0; } }); var SportyEngine = new Class({ speed: 10 }); // Extend one, Implement the other var Corvette = new Class({ Extends: Car, speed: 1, showSpeed: function() { // this.parent calls the overridden class return this.parent()+1; } }); var ZR1 = new Class({ // multiple classes may be implemented Implements: [Car, SportyEngine], // yep showSpeed: function() { // this.parent is not available //return this.parent()+1; // nope return this.speed; } }); Note that the output before mutation is identical to the end of the previous recipe. var corvette = new Corvette(); var zr1 = new ZR1(); $('before').set('html', '<table>'+ '<tr><th>Corvette:</th>'+ '<td>'+corvette.showSpeed()+'</td></tr>'+ '<tr><th>ZR1</th>'+ '<td>'+zr1.showSpeed()+'</td></tr>'+ '</table>'); Here is what happens when the manufacturing plant decides to start putting engines in the base car chassis. That gives them a speed, where they did not have one previously. Mutate the base class by having it return an index of five rather than zero. // the mfg changes base Car speed to be +5 fasterCar = Car.implement({ showSpeed: function() { return 5; }});// but SportyEngine doesn't use the parent method$('after').set('html', '<table>'+ '<tr><th>New Corvette:</th>'+ '<td>'+corvette.showSpeed()+'</td></tr>'+ '<tr><th>New ZR1</th>'+ '<td>'+zr1.showSpeed()+'</td></tr>'+ '</table>'); How it works... The zr1 instantiation did not mutate. The corvette instantiation did. Since zr1 used implements, there is no inheritance that lets it call the parent method. In our example, this makes perfect sense. The base chassis comes with an engine rated with a speed of five. The ZR1 model, during manufacturing/instantiation is given a completely different engine/a completely different property, so any change/recall of the original chassis would not be applicable to that model. For the naysayer, the next recipe shows how to effect a manufacturer recall that will alter all Corvettes, even the ZR1s. There's more... There is an interesting syntax used to mutate the new version of Car, Class.implement(). That same syntax is not available to extend elements. See also Here is a link to the MooTool documentation for Class.implement(): http://mootools.net/docs/core/Class/Class#Class:implement.  
Read more
  • 0
  • 0
  • 855
Banner background image

article-image-haxe-2-using-templates
Packt
25 Jul 2011
10 min read
Save for later

haXe 2: Using Templates

Packt
25 Jul 2011
10 min read
  haXe 2 Beginner's Guide Develop exciting applications with this multi-platform programming language Introduction to the haxe.Template class As developers our job is to create programs that allow the manipulation of data. That's the basis of our job, but beyond this part of the job, we must also be able to present that data to the user. Programs that don't have a user interface exist, but since you are reading this article about haXe, there is a greater chance that you are mostly interested in web applications, and almost all web applications have a User Interface of some kind. However, these can also be used to create XML documents for example. The haXe library comes with the haxe.Template class. This class allows for basic, yet quite powerful, templating: as we will see, it is not only possible to pass some data to it, but also possible to call some code from a template. Templates are particularly useful when you have to present data—in fact, you can, for example, define a template to display data about a user and then iterate over a list of users displaying this template for each one. We will see how this is possible during this article and we will see what else you can do with templates. We will also see that it is possible to change what is displayed depending on the data and also that it is easy to do some quite common things such as having a different style for one row out of two in a table. The haxe.Template is really easy to use—you just have to create an instance of it passing it a String that contains your template's code as a parameter. Then it is as easy as calling the execute method and giving it some data to display. Let's see a simple example: class TestTemplate { public static function main(): Void { var myTemplate = new haxe.Template("Hi. ::user::"); neko.Lib.println(myTemplate.execute({user : "Benjamin"})); } } This simple code will output "Hi. Benjamin". This is because we have passed an anonymous object as a context with a "user" property that has "Benjamin" as value. Obviously, you can pass objects with several properties. Moreover, as we will see it is even possible to pass complex structures and use them. In addition, we certainly won't be hard coding our templates into our haXe code. Most of the time, you will want to load them from a resource compiled into your executable by calling haxe.Resource.getString or by directly loading them from the filesystem or from a database. Printing a value As we've seen in the preceding sample, we have to surround an expression with :: in order to print its value. Expressions can be of several forms:     Form Explanation ::variableName:: The value of the variable. ::(123):: The integer 123. Note that only integers are allowed. ::e1 operator e2:: Applies the operator to e1 and e2 and returns the resulting value. The syntax doesn't manage operator precedence, so you should wrap expressions inside parenthesis. ::e.field:: Accesses the field and returns the value. Be warned that this doesn't work with properties' getters and setters as these properties are a compile-time only feature. Branching The syntax offers the if, else, and elseif: class TestTemplate { public static function main(): Void { var templateCode = "::if (sex==0):: Male ::elseif (sex==1):: Female ::else:: Unknown ::end::"; var myTemplate = new haxe.Template(templateCode); neko.Lib.print(myTemplate.execute({user : "Benjamin", sex:0})); } } Here the output will be Male. But if the sex property of the context was set to 1 it would print Female, if it is something else, it will print "Unknown". Note that our keywords are surrounded by :: (so the interpreter won't think that it is just some raw-text to be printed). Also note that the "end" keyword has been introduced since we do not use braces. Using lists, arrays, and other iterables The template engine allows one to iterate over an iterable and repeat a part of the template for each object in the iterable. This is done using the ::foreach:: keyword. When iterating, the context will be modified and will become the object that is actually selected in the iterable. It is also possible to access this object (indeed, the context's value) by using the __current__ variable. Let's see an example: class Main { public static function main() { //Let's create two departments: var itDep = new Department("Information Technologies Dept."); var financeDep = new Department("Finance Dept."); //Create some users and add them to their department var it1 = new Person(); it1.lastName = "Par"; it1.firstName = "John"; it1.age = 22; var it2 = new Person(); it2.lastName = "Bear"; it2.firstName = "Caroline"; it2.age = 40; itDep.workers.add(it1); itDep.workers.add(it2); var fin1 = new Person(); fin1.lastName = "Ha"; fin1.firstName = "Trevis"; fin1.age = 43; var fin2 = new Person(); fin2.lastName = "Camille"; fin2.firstName = "Unprobable"; fin2.age = 70; financeDep.workers.add(fin1); financeDep.workers.add(fin2); //Put our departements inside a List: var depts = new List<Department>(); depts.add(itDep); depts.add(financeDep); //Load our template from Resource: var templateCode = haxe.Resource.getString("DeptsList"); //Execute it var template = new haxe.Template(templateCode); neko.Lib.print(template.execute({depts: depts})); } } class Person { public var lastName : String; public var firstName : String; public var age : Int; public function new() { } } class Department { public var name : String; public var workers : List<Person>; public function new(name : String) { workers = new List<Person>(); this.name = name; } } In this part of the code we are simply creating two departments, some persons, and adding those persons into those departments. Now, we want to display the list of departments and all of the employees that work in them. So, let's write a simple template (you can save this file as DeptsList.template): <html> <head> <title>Workers</title> </head> <body> ::foreach depts:: <h1>::name::</h1> <table> ::foreach workers:: <tr> <td>::firstName::</td> <td>::lastName::</td> <td>::if (age < 35)::Junior::elseif (58): :Senior::else::Retired::end::</td> </tr> ::end:: </table> ::end:: </body> </html> When compiling your code you should add the following directive: -resource DeptsList.template@DeptsList The following is the output you will get: <html> <head> <title>Workers</title> </head> <body> <h1>Information Technologies Dept.</h1> <table> <tr> <td>John</td> <td>Par</td> <td>Junior</td> </tr> <tr> <td>Caroline</td> <td>Bear</td> <td>F</td> </tr> </table> <h1>Finance Dept.</h1> <table> <tr> <td>Trevis</td> <td>Ha</td> <td>Senior</td> </tr> <tr> <td>Unprobable</td> <td>Camille</td> <td>Retired</td> </tr> </table> </body> </html> As you can see, this is indeed pretty simple once you have your data structure in place. Time for action – Executing code from a template Even though templates can't contain haXe code, they can make calls to so-called "template macros". Macros are defined by the developer and, just like data they are passed to the template.execute function. In fact, they are passed exactly in the same way, but as the second parameter. Calling them is quite easy, instead of surrounding them with :: we will simply prefix them with $$, we can also pass them as parameters inside parenthesis. So, let's take our preceding sample and add a macro to display the number of workers in a department. First, let's add the function to our Main class: public static function displayNumberOfWorkers(resolve : String->Dynamic, department : Department) { return department.workers.length + " workers"; } Note that the first argument that the macro will receive is a function that takes a String and returns a Dynamic. This function will allow you to retrieve the value of an expression in the context from which the macro has been called. Then, other parameters are simply the parameters that the template passes to the macro. So, let's add a call to our macro: <html> <head> </head> <body> ::foreach depts:: <h1>::name:: ($$displayNumberOfWorkers(::__current__::))</h1> <table> ::foreach workers:: <tr> <td>::firstName::</td> <td>::lastName::</td> <td>::if (sex==0)::M::elseif (sex==1)::F::else::?::end::</td> </tr> ::end:: </table> ::end:: </body> </html> As you can see, we will pass the current department to the macro when calling it to display the number of workers. So, here is what you get: <html> <head> </head> <body> <h1>Information Technologies Dept. (2 workers)</h1> <table> <tr> <td>John</td> <td>Par</td> <td>M</td> </tr> <tr> <td>Caroline</td> <td>Bear</td> <td>F</td> </tr> </table> <h1>Finance Dept. (2 workers)</h1> <table> <tr> <td>Trevis</td> <td>Ha</td> <td>M</td> </tr> <tr> <td>Unprobable</td> <td>Camille</td> <td>?</td> </tr> </table> </body> </html>   What just happened?   We have written the displayNumberOfWorkers macro and added a call to it in the template. As a result, we've been able to display the number of workers in a department. Integrating subtemplates Sub-templates do not exist as such in the templating system. The fact is that you can include sub-templates into a main template, which is not a rare process. Some frameworks, not only in haXe, have even made this standard behavior. So, there are two ways of doing this: Execute the sub-template, store its return value, and pass it as a property to the main template when executing it. Create a macro to execute the sub-template and return its value. This way you just have to call the macro whenever you want to include your sub-template in your main template. Creating a blog's front page In this section, we are going to create a front page for a blog by using the haxe.Template class. We will also use the SPOD system to retrieve posts from the database.
Read more
  • 0
  • 0
  • 1318

article-image-oracle-webcenter-11g-ps3-working-navigation-models-and-page-hierarchies
Packt
25 Jul 2011
3 min read
Save for later

Oracle WebCenter 11g PS3: Working with Navigation Models and Page Hierarchies

Packt
25 Jul 2011
3 min read
  Oracle WebCenter 11g PS3 Administration Cookbook Over 100 advanced recipes to secure, support, manage, and administer Oracle WebCenter 11g with this book and eBook         Read more about this book       (For more resources on this subject, see here.) Creating a navigation model at runtime Lots of administrators will not have access to JDeveloper, but they will need to manage navigation models. In WebCenter, you can easily create and manage navigation models at runtime. In this recipe, we will show how you can add navigation models at runtime. Getting ready For this recipe, you need a WebCenter Portal application. How to do it... Run your portal application. Log in as an administrator. Go to the administration page. Select Navigations from the Resource tab. Press the Create button. Specify a name, for example, hr. Specify a description, for example, Navigation model for HR users. Leave copy from empty. In this list, you can select an existing navigation model so the newly created model will copy the content from the selected model. Press the Create button: The navigation model is now created and you can add components to it. How it works... When you add a navigation model at runtime, an XML file will be generated in the background. The navigation model will be stored in the MDS. You can request the path to the actual xml file by selecting Edit properties from the Edit menu when you select a navigation model. In the properties window, you will find a field called Metadata file. This is the complete directory to the actual XML file. There's more... Even at runtime, you can modify the actual XML representation of the navigation model. This allows you to be completely flexible. Not everything is possible at runtime, but when you know what XML to add, you can do so by modifying the XML of the navigation model. This can be done by selecting Edit Source from the Edit menu. This way you will get the same XML representation of a navigation model as in JDevleoper. Adding a folder to a navigation model A folder is the simplest resource you can add to your navigation model. It does not link to a specific resource. A folder is only intended to organize your navigation model in a logical way. In this recipe, we will add a folder for the HR resources. Getting ready We will add the folder to the default navigation model so you only need the default WebCenter Portal application for this recipe. How to do it... Open default-navigation-mode.xml from Web Content/oracle/Webcenter/portalapp/navigations. Press the Add button and select Folder from the context menu. Specify an id for the folder. The id should be unique for each resource over the navigation model. Specify an expression language value for the Visible attribute. How it works... Adding a folder to a navigation model will add a folder tag to the XML with the metadata specified: <folder visible="#{true}" id="hr"> <attributes> <attribute isKey="false" value="folder" attributeId="Title"/> </attributes> <contents/> </folder> The folder tag has a contents tag as a child. This means that when you add a resource to a folder, these will be added as a child to the contents tag. There's more... You can also add a folder at runtime to a navigation model. This is done by selecting your navigation model and selecting Edit from the Edit menu. From the Add menu, you can select Folder. You are able to add the id, description, visible attribute and iconUrl.
Read more
  • 0
  • 0
  • 766

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
  • 4729
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 £15.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
  • 4130

article-image-customizing-wordpress-settings-seo
Packt
27 Apr 2011
12 min read
Save for later

Customizing WordPress Settings for SEO

Packt
27 Apr 2011
12 min read
  WordPress 3 Search Engine Optimization Optimize your website for popularity with search engines         Read more about this book       (For more resources on WordPress, see here.) We will begin by setting up the goals for your Internet presence and determining how best to leverage WordPress' flexibility and power for maximum benefit. We'll examine how to best determine and reach out to the specific audience for your goods or services. Different Internet models require different strategies. For example, if your goal is instant e-commerce sales, you strategize differently than if your goal is a broad-based branding campaign. We'll also examine how to determine how competitive the existing search market is, and how to develop a plan to penetrate that market. It's important to leverage WordPress' strengths. WordPress can effortlessly help you build large, broad-based sites. It can also improve the speed and ease with which you publish new content. It serves up simple, text-based navigation menus that search engines crawl and index easily. WordPress' tagging, pingback, and trackBack features help other blogs and websites find and connect with your content. For these reasons, and quite a few more, WordPress is search ready. In this article, we will look at what WordPress already does for your SEO. Of course, WordPress is designed as a blogging platform and a content management platform—not as a platform purely for ranking. We'll look at what WordPress doesn't accomplish innately and how to address that. Finally, we'll look at how WordPress communicates with search engines and blog update services. Following this article, we'll know how to plan out a new site or improve an existing one, how to gauge WordPress' innate strengths and supplant its weaknesses, and learn how WordPress sites get found by search engines and blog engines. Setting goals for your business and website and getting inspiration A dizzying variety of websites run on the WordPress platform, everything from The Wall Street Journal's blog to the photo sharing comedy site PeopleofWalMart. com . Not every reader will have purely commercial intent in creating his or her web presence. However, all webmasters want more traffic and more visibility for their sites. With that in mind, to increase the reach, visibility, and ranking of your website, you'll want to develop your website plan based on the type of audience you are trying to reach, the type of business you run, and what your business goals are. Analyzing your audience You will obviously want to analyze the nature of your audience. Your website's content, its design, its features, and even the pixel width of the viewable area will depend on your audience. Is your audience senior citizens? If so, your design will need to incorporate large fonts and you will want to keep your design to a pixel width of 800 or less. Senior citizens can have difficulty reading small text and many use older computers with 800 pixel monitors. And you can forget about the integrated Twitter and Facebook feeds; most seniors aren't as tuned into those technologies as young people. You might simply alienate your target users by including features that aren't a fit for your audience. Does your audience include purchasers of web design services? If so, be prepared to dazzle them with up-to-date design and features. Similarly, if you intend to rely on building up your user base by developing viral content, you will want to incorporate social media sharing into your design. Give some thought to the type of users you want to reach, and design your site for your audience. This exercise will go a long way in helping you build a successful site. Analyzing your visitors' screen sizes Have you ever wondered about the monitor sizes of the viewers of your own site? Google Analytics (www.google.com/analytics), the ubiquitous free analytics tool offered by Google, offers this capability. To use it, log on to your Google Analytics account (or sign up if you don't have one) and select the website whose statistics you wish to examine. On the left menu, select Visitors, and expand the Browser Capabilities menu entry. Then select Screen Resolutions. Google Analytics will offer up a table and chart of all the monitor resolutions used by your viewers. Determining the goal of your website The design, style, and features of your website should be dictated by your goal. If your site is to be a destination site for instant sales or sign-ups, you want a website design more in the style of a single-purpose landing page that focuses principally on conversions. A landing page is a special-purpose, conversion-focused page that appears when a potential customer clicks on an advertisement or enters through a search query. The page should display the sales copy that is a logical extension of the advertisement or link, and should employ a very shallow conversion funnel . A conversion funnel tracks the series of steps that a user must undertake to get from the entry point on a website to the satisfaction of a purchase or other conversion event. Shallow conversion funnels have fewer steps and deeper conversion funnels have more steps. When designing conversion-focused landing pages, consider if you want to eliminate navigation choices entirely on the landing page. Logically, if you are trying to get a user to make an immediate purchase, what benefit is served by giving the user easier choices to click onto the other pages? Individualized page-by-page navigation can get clunky with WordPress; you might want to ensure that your WordPress template can easily handle these demands. (Move the mouse over the image to enlarge it.) The previous screenshot shows the expert landing page for Netfiix's DVD rental service. Note the absence of navigational choices. There are other sophisticated conversion tools as well: clear explanation of benefits, free trial, arrows, and a color guide to the reader to the conversion event. If you sell a technical product or high-end consulting services, you rely heavily on the creation of content and the organization and presentation of that content, on your WordPress site. Creating a large amount of content covering broad topics in your niche will establish thought leadership that will help you draw in and maintain new customers. In sites with large amounts of educational content, you'll want to make absolutely sure that your content is well organized and has an easy-to-follow navigation. If you will be relying on social media and other forms of viral marketing to build up your user base, you'd want to integrate social media plug-ins and widgets into your site. Plug-ins and widgets are third-party software tools that you install on your WordPress site to contribute to a new functionality. A popular sports site integrates the TweetMeme and Facebook connect widgets. When users retweet or share the article, it means links, traffic, and sales. When compounded with a large amount of content, the effect can be very powerful. Following the leaders Once you have determined the essential framework and niche for your site, look for best-in-class websites for your inspiration. Trends in design and features are changing constantly. Aim for up-to-the-minute design and features: enlightened design sells more products and services, and sophisticated features will help you convert and engage your visitors more. Likewise, ease of functionality will keep visitors on your website longer and keep them coming back. For design inspiration, you can visit any one of the hundreds of website design gallery sites. These gallery sites showcase great designs in all website niches. The following design gallery sites feature the latest and greatest trends in web design and features (note that all of these sites run on WordPress): Urban Trash (www.urbantrash.net/cssgallery/): This gallery is truly one of the best and should be the first stop when seeking design inspiration. CSS Elite (www.csselite.com): Another of the truly high-end CSS galleries. Many fine sites are featured here. CSSDrive (www.cssdrive.com): CSS Drive is one of the elite classes of directories, and CSS Drive has many other design-related features as well. For general inspiration on everything from website design, to more specialized discussion of the best design for website elements such as sign-up boxes and footers, head to Smashing Magazine , especially its "inspiration" category (http://smashingmagazine.com/category/inspiration/). Ready-made WordPress designs by leading designers are available for purchase off-the-shelf at ThemeForest.net. These templates are resold to others, so they won't be exclusive to your site. A head's up: these top-end themes are full of advanced custom features. They might require a little effort to get them to display exactly as you want. For landing pages, get inspiration from retail monoliths in competitive search markets. DishNetwork and Netfiix have excellent landing pages. Sears' home improvement division serves up sophisticated landing pages for services such as vinyl siding and replacement windows. With thousands of hits per day, you can bet these retail giants are testing and retesting their landing pages periodically. You can save yourself the trouble and budget of your early-stage testing by employing the lessons that these giants have already put into practice. For navigation, usability, and site layout clues for large content-based sites, look for the blogging super-sites such as Blogs.wsj.com , POLITICO.com , Huffingtonpost. com , and Wikipedia.com Gauging competition in the search market Ideally, before you launch your site, you will want to gauge the competitive marketplace. On the Web, you have two spheres of competition: One sphere is traditional business competition: the competition for price, quality, and service in the consumer marketplace The other sphere of competition is search competition; competition for clicks, page views, conversions, user sign-ups, new visitors, returning visitors, search placement, and all the other metrics than help drive a web-based business The obvious way to get started gauging the search marketplace is to run some sample searches on the terms you believe your future customers might use when seeking out your products or services. The search leaders in your marketplace will be easy to spot; they will be in the first six positions in a Google search. While aiming for the first six positions, don't think in terms of the first page of a Google search. Studies show that the first five or six positions in a Google search yield 80 to 90 percent of the click-throughs. The first page of Google is a good milestone, but the highest positions on a search results page will yield significantly higher traffic than the bottom three positions on a search results page Once you've identified the five or six websites that are highly competitive and searches, you want to analyze what they're doing right and what you'll need to do to compete with them. Here's how to gauge the competition: Don't focus on the website in terms of the number one position for a given search. That may be too lofty a goal for the short term. Look at the sites in positions 4, 5, and 6. These positions will be your initial goal. You'll need to match or outdo these websites to earn those positions. First, you want to determine the Google PageRank of your competitor's sites. PageRank is a generalized, but helpful, indicator of the quality and number of inbound links that your competitors' websites have earned. Install a browser plug-in that shows the PageRank of any site to which you browse. For Firefox, try the SearchStatus plug-in (available at http://www.quirk.biz/searchstatus/). For Chrome, use SEO Site Tools (available through the Google Chrome Extensions gallery at https://chrome.google.com/extensions). Both of these tools are free, and they'll display a wide array of important SEO factors for any site you visit. How old are the domains of your competitors' websites? Older sites tend to outrank newer sites. If you are launching a new domain, you will most likely need to outpace your older competitors in other ways such as building more links or employing more advanced on-page optimization. Site age is a factor that can't be overcome with brains or hard work (although you can purchase an older, existing domain in the after market). Look at the size and scale of competing websites. You'll need to at least approach the size of the smallest of your competitors to place well. You will want to inspect your competitors' inbound links. Where are they getting their links from and how many links have they accumulated? To obtain a list of backlinks for any website, visit the Yahoo! Site Explorer at siteexplorer.search.yahoo.com. This free tool displays up to 1,000 links for any site. If you want to see more than 1,000 links, you'll need to purchase inbound link analysis software like SEO Spyglass from link-assistant.com. For most purposes, 1,000 links will give you a clear picture of where a site's links are coming from. Don't worry about high links counts because low-value links in large numbers are easy to overcome; high- value links like .edu links, links from article content, and links from high- PageRank sites will take more effort to surmount. You will want to examine the site's on-page optimization. Are the webmasters utilizing effective title tags and meta tags? Are they using heading tags and is their on-page text keyword-focused? If they aren't, you may be able to best beat your competitors through more effective on-page optimization. Don't forget to look at conversion. Is your competitor's site well-designed to convert his or her visitors into customers? If not, you might edge out your competition with better conversion techniques. When you analyze your competition, you are determining the standard you will need to meet or beat to earn competitive search placement. Don't be discouraged by well-placed competitors. 99 percent of all the websites are not well optimized. As you learn more, you'll be surprised how many webmasters are not employing effective optimization. Your goal as you develop or improve your website will be to do just a little bit more than your competition. Google and the other search engines will be happy to return your content in search results in favor of others if you meet a higher standard.
Read more
  • 0
  • 3
  • 2147

article-image-wordpress-avoiding-black-hat-techniques
Packt
26 Apr 2011
10 min read
Save for later

WordPress: Avoiding the Black Hat Techniques

Packt
26 Apr 2011
10 min read
  WordPress 3 Search Engine Optimization Optimize your website for popularity with search engines         Read more about this book       (For more resources on WordPress, see here.) Typical black hat techniques There is a wide range of black hat techniques fully available to all webmasters. Some techniques can improve rankings in short term, but generally not to the extent that legitimate web development would, if pursued with the same effort. The risk of black hat techniques is that they are routinely detected and punished. Black hat is never the way to go for a legitimate business, and pursuing black hat techniques can get your site (or sites) permanently banned and will also require you to build an entirely new website with an entirely new domain name. We will examine a few black hat techniques to help you avoid them. Hidden text on web pages Hidden text is the text that through either coding or coloring does not appear to users, but appears to search engines. Hidden text is a commonly-used technique, and would be better described as gray hat. It tends not to be severely punished when detected. One technique relies on the coloring of elements. When the color of a text element is set to the same color as the background (either through CSS or HTML coding), then the text disappears from human readers while still visible to search spiders. Unfortunately, for webmasters employing this technique, it's entirely detectible by Google. More easily detectible is the use of the CSS property display: none. In the language of CSS, this directs browsers to not display the text that is defined by that element. This technique is easily detectible by search engines. There is an obvious alternative to employing hidden text: Simply use your desired keywords in the text of your content and display the text to both users and search spiders. Spider detection, cloaking, redirection, and doorway pages Cloaking and spider detection are related techniques. Cloaking is a black hat SEO technique whereby the content presented to search engine spiders (via search spider detection) differs from the content presented to users. Who would employ such a technique? Cloaking is employed principally by sellers of products typically promoted by spam, such as pharmaceutics, adult sites, and gambling sites. Since legitimate search traffic is difficult to obtain in these niches, the purveyors of these products employ cloaking to gain visitors. Traditional cloaking relies upon spider detection. When a search spider visits a website, the headers accompanying a page view request identify the spider by names such as Goolgebot (Google's spider) or Slurp (Inktomi's spider). Conversely, an ordinary web browser (presumably with a human operator) will identify itself as Mozilla, Internet Explorer, or Safari, as the case may be. With simple JavaScript or with server configuration, it is quite easy to identify the requesting browser and deliver one version of a page to search spiders and another version of the page to human browsers. All you really need is to know the names of the spiders, which are publicly known. A variation of cloaking is a doorway page. A doorway page is a page through which human visitors are quickly redirected (through a meta refresh or JavaScript) to a destination page. Search spiders, however, index the doorway page, and not the destination page. Although the technique differs in execution, the effect is the same: Human visitors see one page, and the search engines see another. The potential harm from cloaking goes beyond search engine manipulation. More often than not, the true destination pages in a cloaking scheme are used for the transmission of malware, viruses, and Trojans. Because the search engines aren't necessarily reading the true destination pages, the malicious code isn't detected. Any type of cloaking, when reported or detected, is almost certain to result in a severe Google penalty, such as removal of a site from the search engine indexes. Linking to bad neighborhoods and link farms A bad neighborhood is a website or a network of websites that either earns inbound links through illegitimate means or employs other "black hat on-page" techniques such as cloaking, and redirects them. A link farm is a website that offers almost no content, but serves solely for the purpose of listing links. Link farms, in turn, offer links to other websites to increase the rankings of these sites. A wide range of black hat techniques can get a website labeled as a bad neighborhood. A quick test you can employ to determine if a site is a bad neighborhood is by entering the domain name as a part of the specialized Google search query, "site:the-website-domain.com" to see if Google displays any pages of that website in its index. If Google returns no results, the website is either brand new or has been removed from Google's index—a possible indicator that it has been labeled a bad neighborhood. Another quick test is to check the site's PageRank and compare the figure to the number of inbound links pointing to the site. If a site has a large number of backlinks but has a PageRank of zero, which would tend to indicate that its PageRank has been manually adjusted downwards due to a violation of Google's Webmaster Guidelines. If both of the previous tests are either positive or inconclusive, you would still be wise to give the site a "smell test". Here are some questions to ask when determining if a site might be deemed as a bad neighborhood: Does the site offer meaningful content? Did you detect any redirection while visiting the site? Did you get any virus warning while visiting the site? Is the site a little more than lists of links or text polluted with high numbers of links? Check the website's backlink profile. Are the links solely low-value inbound links? If it isn't a site you would engage with when visiting, don't link to it. Google Webmaster Guidelines Google Webmaster Guidelines are a set of written rules and prohibitions that outline recommended and forbidden website practices. You can find these webmaster guidelines at: http://www.google.com/support/webmasters/bin/ answer.py?hl=en&answer=35769, though you'll find it easier to search for "Google Webmaster Guidelines" and click on the top search result. You should read through the Google Webmaster Guidelines and refer to them occasionally. The guidelines are divided into design and content guidelines, technical guidelines, and quality guidelines. Google Webmaster Guidelines in a nutshell At their core, Google Webmaster Guidelines aim for quality in the technology underlying websites in their index, high-quality content, and also discourage manipulation of search results through deceptive techniques. All search engines have webmaster guidelines, but if you follow Google's dictates, you will not run afoul of any of the other search engines. Here, we'll discuss only the Google's rules. Google's design and content guidelines instruct that your site should have a clear navigational hierarchy with text links rather than image links. The guidelines specifically note that each page "should be reachable from at least one static text link". Because WordPress builds text-based, hierarchical navigation naturally, your site will also meet that rule naturally. The guidelines continue by instructing that your site should load quickly and display consistently among different browsers. The warnings come in Google's quality guidelines; in this section, you'll see how Google warns against a wide range of black hat techniques such as the following: Using hidden text or hidden links, elements that through coloring, font size, or CSS display properties to show to the search engines but do not show them to the users. The use of cloaking or "sneaky redirects". Cloaking means a script that detects search engine spiders and displays one version of a website to users and displays an alternate version to the search engines. The use of repetitive, automated queries to Google. Some unscrupulous software vendors (Google mentions one by name, WebPosition Gold, which is still in the market, luring unsuspecting webmasters) sell software and services that repeatedly query Google to determine website rankings. Google does allow such queries in some instances through their AJAX Search API Key—but you need to apply for one and abide by the terms of its use. The creation of multiple sites or pages that consist solely of duplicate content that appears on other web properties. The posting or installation of scripts that behave maliciously towards users, such as with viruses, trojans, browser interceptors, or other badware. Participation in link schemes. Google is quite public that it values inbound links as a measure of site quality, so it is ever vigilant to detect and punish illegitimate link programs. Linking to bad neighborhoods. A bad neighborhood means a website that uses illegitimate, forbidden techniques to earn inbound links or traffic. Stuffing keywords onto pages in order to fool search spiders. Keyword stuffing is "the oldest trick in the book". It's not only forbidden, but also highly ineffective at influencing search results and highly annoying to visitors. When Google detects violations of its guidelines Google, which is nearly an entirely automated system, is surprisingly capable of detecting violations of its guidelines. Google encourages user-reporting of spam websites, cloaked pages, and hidden text (through their page here: https://www. google.com/webmasters/tools/spamreport). They maintain an active antispam department that is fully engaged in an ongoing improvement in both, manual punishments for offending sites, and algorithmic improvements for detecting violations. When paid link abuses are detected, Google will nearly always punish the linking site, not necessarily the site receiving the link—even though the receiving site is the one earning a ranking benefit. At first glance, this may seem counter-intuitive, but there is a reason. If Google punished the site receiving a forbidden paid link, then any site owner could knock a competitor's website by buying a forbidden link, pointing to the competitor, and then reporting the link as spam. When an on-page black hat or gray hat element is detected, the penalty will be imposed upon the offending site. The penalties range from a ranking adjustment to an outright ban from search engine results. Generally, the penalty matches the crime; the more egregious penalties flow from more egregious violations. We need to draw a distinction, however, between a Google ban, penalty, and algorithmic filtering. Algorithmic filtering is simply an adjustment to the rankings or indexing of a site. If you publish content that is a duplicate of the other content on the Web, and Google doesn't rank or index that page, that's not a penalty, it's simply the search engine algorithm operating properly. If all of your pages are removed from the search index, that is most likely a ban. If the highest ranking you can achieve is position 40 for any search phrase, that could potentially be a penalty called a "-40 penalty". All search engines can impose discipline upon websites, but Google is the most strict and imposes far more penalties than the other search engines, so we will largely discuss Google here. Filtering is not a penalty; it is an adjustment that can be remedied by undoing the condition that led to the it. Filtering can occur for a variety of reasons but is often imposed following over optimization. For example, if your backlink profile comprises links of which 80% use the same anchor text, you might trigger a filter. The effect of a penalty or filter is the same: decreased rankings and traffic. In the following section, we'll look at a wide variety of known Google filters and penalties, and learn how to address them.
Read more
  • 0
  • 0
  • 1202

article-image-building-ext-js-theme-oracle-apex
Packt
15 Apr 2011
6 min read
Save for later

Building a Ext JS Theme into Oracle APEX

Packt
15 Apr 2011
6 min read
Oracle Application Express 4.0 with Ext JS Deliver rich desktop-styled Oracle APEX applications using the powerful Ext JS JavaScript library        Theme basics Out of the box, APEX comes with twenty themes, each theme comprising a collection of templates used to define the layout and appearance of an entire application. An application can have many themes, but only one theme is active at any time; switching themes is done at design time only. You can create custom themes, which may be published, either within a workspace by a Workspace Manager or for the whole APEX instance by an Internal Workspace Manager. Publishing a theme encourages consistency across applications. A theme comprises nine template types: breadcrumb, button, calendar, label, list, page, popup list of values, region, and report. A theme must have at least one of each of the nine template types. Within each template type are a set of predefined classes and eight custom classes. For example, the label template has the following classes: - Not Identified - No Label Optional Label Optional Label with Help Required Label Required Label with Help Custom 1... Custom 8 Programmers use these templates to construct the HTML pages that make up an application. Each page is declaratively defined using metadata to select templates to be used for the presentation. The APEX engine dynamically renders an HTML page using the metadata, assembling relevant templates and injecting dynamic data into placeholders within the templates. The HTML page is viewed when you request a page through a web browser. When you submit a page, the APEX engine performs page processing, once again using declaratively defined metadata to perform computations, validations, processes, and branching. This type of processing is a typical Model-View-Controller(MVC) pattern, where the view is the HTML generated using the application templates. The APEX engine is the controller and receives the GET or POST input and decides what to do with it, handing over to domain objects. The domain objects model is encapsulated in the page definition and contains the business rules and functionality to carry out specific tasks. Separation of concerns The MVC pattern also promotes another good design principle—separation of concerns. APEX has been designed so that the APEX engine, templates, and the application functionality can be optimized independently of each other. Clearly, the process of assembling and sequencing the steps necessary to render a page, and process a page are important to the overall solution. By separating this out and letting Oracle deal with the complexities of this through the APEX engine, it allows programmers to concentrate on providing business functionality. Equally, by separating presentation templates from the business logic, it allows each aspect to be maintained separately. This provides a number of advantages including ease of design change, allowing templates to be modified either by different people or at different times to enhance the interface without breaking the application. An excellent example of this is the standard themes provided in APEX, which have been designed to be completely interchangeable. Switching standard themes is simply a matter of loading a theme from the repository and then switching the active theme. APEX then remaps components to the new active theme using the template class identifiers. Standard themes We will be building our own custom theme rather than using one of the twenty pre-built ones. Nevertheless, it's worthwhile knowing what they provide, as we will build our custom theme by using one of them as a "starter". Looking at this image, we can see a preview of the standard APEX themes. Each theme provides a similar interface, so really each standard theme is just a visual variation on the others. The colors used are a little different, or the HTML layout is tweaked slightly, but in reality they are all much the same. Theme 4 is used by APEX as the "starter" theme and contains one template for each template class for all the template types—a total of 69 templates. Theme 19 is also worth noting as it's designed for mobile devices. Each of these themes are full of good HTML practices and show how and where to use the substitution strings. Creating a theme When creating a theme, you can choose to copy one from the repository, create one from scratch or from an export file. The repository and export file options copy the entire theme, and you start editing the template to suit. Creating a theme from scratch creates a theme without any templates. You then need to define templates for each different type before you can switch from the active theme. In my opinion, the easiest way to build a new theme is to take the approach that the application should always be in a working state, and the way to do this is to create a new empty TEMPLATE application using a standard theme and build from there. From this working base, you can progressively convert the templates to use Ext functionality, building simple test pages as you go to verify the templates. These test pages also form part of your template documentation, allowing team members to examine and understand specific functionality in isolation. Once a theme has templates for each of the nine template types, you can publish the theme into the workspace to be used by your business applications. The following screenshot shows a dialog named Create Workspace Theme from the APEX wizard. Notice that you can change the theme number when you publish a theme, providing a very simple mechanism for you to version control your themes. A published theme can't be edited directly once it has been created, but using a TEMPLATE application, you can republish it using a different theme number. Applications can have multiple themes, but only one active theme. By switching themes, applications can easily test a new version, safe in the knowledge that changing back to the earlier version is just a matter of switching back to the prior theme. So before we go any further, create a new TEMPLATE application based on Theme 4, and let's begin the process of creating our Ext JS theme. Building a Viewport Page template Several of the examples provided with Ext feature the Viewport utility container, including the RSS Feed Viewer shown in the screenshot below. The Viewport automatically renders to the document body, sizing itself to the browser viewport and dividing the page into up to five distinct regions; the center region is mandatory, with north, south, east, and west regions being optional. Viewport regions are configurable, and by setting a few simple attributes, you quickly find yourself with a very interactive page, with expanding/collapsing regions and splitters to resize regions by clicking and dragging with the mouse. We are going to build a basic viewport for our APEX page template including all five regions.
Read more
  • 0
  • 0
  • 1868
article-image-concrete5-mastering-auto-nav-advanced-navigation
Packt
12 Apr 2011
9 min read
Save for later

concrete5: Mastering Auto-Nav for Advanced Navigation

Packt
12 Apr 2011
9 min read
concrete5 Beginner's Guide Create and customize your own website with the Concrete5 Beginner's Guide         Autonav introduction Before we start customizing the autonav block, we're going to have a quick look at the different options and the output. It's very helpful to be familiar with all the block options as well as knowing the HTML output the block generates before you start extending the block. Preparation You may have the autonav block included in your theme, more precisely in header.php of your theme. Since we're going to play with navigation, we should undo this modification; changing the options in header.php would be a bit annoying otherwise. If you're done with this article, you might want to put the code back in place; it's mostly to make it easier to work with the custom templates we're going to build. Time for action – undoing autonav block integration Open header.php from your theme; it's located in the themes/c5book/elements directory (Code Download-ch:7). Since the following code snippet doesn't show the complete file, make sure you replace the correct lines. Everything is underneath the HTML tag with the ID header: <div id="wrapper"> <div id="page"> <div id="header_line_top"></div> <div id="header"> <?php $a = new Area('Header Nav'); $a->display($c); ?> </div> <div id="header_line_bottom"></div> Save header.php and go back to your page. Make sure the navigation is still there, if it isn't go back to edit the page and add a new autonav block in Header Nav. After you've added it, change the custom template to Header Menu. What just happened? We had to undo a modification done before this article. The code which printed the autonav block directly from the template would be fine if your navigation didn't change. However, since we're working on the autonav block for a whole article, we had to remove this code and replace it with the default code for an editable area. Autonav options The autonav block comes with a bunch of options you can use to create the correct hierarchical output of pages in your navigation. While you probably have to play around with it for a bit to get used to all the options, we're still going to look at a few possible configurations which we'll need later in this article. Autonav page structure The example configurations we're going to look at use the structure shown in the following screenshot. We won't need to tick the checkbox for system pages, which would show the dashboard and some built-in pages. We don't want to include them in our navigation anyway. It doesn't matter if your structure looks different at this point; the examples are easy to understand even if your result looks a bit different. Page order By default, the autonav block uses the sort order which you can see in the sitemap as well. This usually makes sense because it offers the biggest flexibility. Remember, you can arrange pages by dragging their icon to the place where you want the page to be. In all our examples you can choose whatever order you like; it doesn't have an effect on our templates. Example 1 - showing all pages The most basic configuration shows all pages, no matter where we are and no matter how many pages there are. This configuration is useful when you create a JavaScript-based navigation which displays subpages dynamically without reloading the page. The settings should be obvious and the result as well; it will show all pages shown in the preceding structure. When you create JavaScript drop-down navigation, you have to generate HTML code for all elements you want to show, but that doesn't necessarily mean that you want to print all elements. Assuming you've got hundreds of pages, would you like to see all of them in the drop-down menu? Probably not, and this is why you can manually specify the number of page levels you'd like to print. Use this for the drop-down navigation we're going to create later in this article. Example 2 – showing relevant subpages In the structure just shown, assume you're on About, which has two direct child pages. If we wanted to display the two subpages in the left sidebar of our page, we could use the following settings: Example 3 – showing relevant subpages starting from the top For a site where you only have a single navigation, probably on the left-hand side, you have to start at the top and include all the relevant subpages. The settings are similar, but this time we start at the top and include the level below the current subpage as well by using these settings: If you're on the About page again, you'd see all pages on the top, along with the About page and the two subpages of it. Autonav output The autonav controller produces an HTML output which is compatible with most jQuery libraries you can find. It uses an UL/LI structure to create a proper hierarchical representation of the pages we show in our navigation. Before we look at the actual output, here are some words about the process which generates the output. The autonav block controller uses all the settings you make when you add the block. It then creates an array of pages which doesn't have any children—it's a flat array. Unlike what some of you would expect, there's no real recursion in the structure which you have to process in the block template. How's an autonav block template supposed to print a hierarchical structure? That's not too difficult; there's a property called level for each element in the array. You simply have to check what happens to that level. Is the level of the current page element bigger than the one from the previous element? If yes, create a new child to the current page. Does it decrease? If yes, close the HTML tags for the child elements you created when the level increased. Does this sound a bit abstract? Let's look at a simplified, not working, but commented autonav template: <?php defined('C5_EXECUTE') or die(_("Access Denied.")); // get the list of all pages matching the selection $aBlocks = $controller->generateNav(); $nh = Loader::helper('navigation'); echo("<ul class="nav">"); // loop through all the pages foreach($aBlocks as $ni) { $_c = $ni->getCollectionObject(); // get the level of the current element. // This is necessary to create the proper indentation. $thisLevel = $ni->getLevel(); // the current page has a higher level than the previous // page which means that we have to print another UL // element to indent the next pages if ($thisLevel > $lastLevel) { echo("<ul>"); } // the current page has a lower level compared to // the previous page. We have to close all the open // LI and UL elements we've previously opened else if ($thisLevel < $lastLevel) { for ($j = $thisLevel; $j < $lastLevel; $j++) { if ($lastLevel - $j > 1) { echo("</li></ul>"); } else { echo("</li></ul></li>"); } } } // when adding a page, see "echo('<li>..." below // the tag isn't closed as nested UL elements // have to be within the LI element. We always close // them in an iteration later else if ($i > 0) { echo("</li>"); } // output the page information, name and link echo('<li><a href="' . $ni->getURL() . '">' . $ni->getName() . '</a>'); // We have to compare the current page level // to the level of the previous page, safe // it in $lastLevel $lastLevel = $thisLevel; $i++; } // When the last page has been printed, it // can happen that we're not in the top level // and therefore have to close all the child // level we haven't closed yet $thisLevel = 0; for ($i = $thisLevel; $i <= $lastLevel; $i++) { echo("</li></ul>"); } ?> The templates we're going to create don't change a lot from the default PHP template. We mostly use the HTML structure the default template generates and only add some CSS and JavaScript. Understanding every detail of the default autonav template isn't necessary, but still helps you to get the most out of the autonav block. What we must understand is the HTML structure shown as follows—it's what you'll have to work with when you create a custom navigation or layout: <ul class="nav"> <li class="nav-path-selected"> <a class="nav-path-selected" href="/">Home</a> </li> <li class="nav-selected nav-path-selected"> <a class="nav-selected nav-path-selected" href="/index.php/about/">About</a> <ul> <li> <a href="/index.php/about/press-room/">Press Room</a> </li> <li> <a href="/index.php/about/guestbook/">Guestbook</a> </li> </ul> </li> <li> <a href="/index.php/search/">Search</a> </li> <li> <a href="/index.php/news/">News</a> </li> </ul> Since you're supposed to have some HTML knowledge to read this book, it should be fairly easy to understand the preceding structure. Each new level added a new ul element which contains an li element for each page along with an a element to make it clickable. Child pages within a ul element belong to their parent, meaning that the li element of the parent is closed when all the children have been printed. The output uses the default template which adds some classes you can use to style the navigation: nav: The main ul tag contains this class. Use it to access all elements of the navigation. nav-selected: This class is assigned to the elements if they belong to the current page. nav-path-selected: This class can be found on pages which are above the current page. They belong to the path of the current page, and are thus called path-selected.
Read more
  • 0
  • 0
  • 2924

article-image-ibm-lotus-domino-adding-style-form-and-page-elements
Packt
29 Mar 2011
6 min read
Save for later

IBM Lotus Domino: Adding Style to Form and Page Elements

Packt
29 Mar 2011
6 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 Most of the CSS rules you write for an application relate to design elements on forms and pages. Suggestions and examples in this section just scratch the surface of CSS possibilities. Browse the Web for additional ideas. Here we focus on the mechanics of how elements are styled, rather than on specific recommendations about what looks good, which is largely a matter of taste. Use color effectively Use pleasing, complementary colors. If your organization requires a specific set of colors, then, of course, find out what that palette is and conform to it as much as possible. Color tastes change over the years, primary colors dominating at times and lighter pastels in vogue at others. Here are a few generalities to consider: Use white or very light colors for backgrounds Use stronger colors such as dark red to make important elements stand out Use no more than three or four colors on a form Use black or dark gray text on a light background for lengthy text passages If you have paid little attention to the matter of color in your applications, do some web work on the subject. Once you select a color scheme, provide some samples to your customers for their opinions and suggestions. Style text Typography is a complex topic with a rich history and strong opinions. For web application design purposes, consider using web-safe fonts which are likely to be available on most or all personal computers. If you use a font that is not available to a browser, then text is rendered with a default font. Fonts with serifs are usually considered easier to read on paper, and less so as web page text. Experiment with the following fonts: Bookman Old Style Cambria Garamond Georgia Times New Roman Common fonts without serifs (sans serif) are considered easier to read on the Web. Some examples include: Arial Calibri Helvetica MS Sans Serif Tahoma Trebuchet MS Verdana Mono-spaced fonts are useful when you want text to line up—columns of numbers in a table, perhaps: Courier New Courier Establish a common font style with CSS rules applied to the body type selector or to a main division using a type selector, a class selector, or an ID selector: body { color: #555555; font-family: Verdana; font-size: 8pt; } Style headings and labels If headings and labels are bracketed with HTML heading tags (for example, <h1> or <h2gt;), they can be styled with type selectors: h1 { color: Blue; font-family: Arial; font-size: 18pt; font-weight: bold; } If headings and labels are bracketed with <span> tags, use CSS classes: <span class="highlight1">October News</span> Underline links in text but not in menus When browsers and the Web first appeared in the early 1990's, hyperlinks were a novelty. To distinguish a link from normal text, the convention developed to underscore the text containing the link, and often the link text was colored blue. There is no magic associated with underscoring and making text blue—it was just the convention adopted at the time. Today links in text passages are usually distinguished from adjacent text with color, weight or underscoring. In a menu, however, each item is understood to be a hotspot link. Underscores and blue text are not required. So if you feel like underscoring a link, do so if the link appears within some text, but don't underscore links in menus. At the same time, refrain from highlighting important text with underscoring, which implies that that text is a hyperlink. Use another highlighting technique; italics, bold, or an alternate color work well for this purpose. Style fields Fields can be styled with CSS either with the Style attribute in Field Properties or with CSS rules. The key to understanding how CSS rules can be applied to fields is to understand that fields are translated to the Web using <input> tags. Here is how a simple text field translates into HTML: <input name="FirstName" value=""> Here is how a radio button field translates: <input name="%%Surrogate_Gender" type="hidden" value="1"> <label><input type="radio" name="Gender" value="M">M</label><br> <label><input type="radio" name="Gender" value="F">F</label><br> CSS rules can be defined for the <input> tag, an ID, or a class. For example, assume that a CSS class named requiredtext is defined. If that class name is entered in the Class attribute of Field Properties, the resulting HTML might look like this: <input name="FirstName" value="" class="requiredtext"> CSS style rules coded for the requiredtext class are applied to the field. Highlight required fields Required fields are validated, most likely with JavaScript code, so that complete and good data is saved into the database when a document is submitted. If entered values fail validation, the user is presented with a message of some sort that identifies the problem and requests correction. Web forms typically identify which fields are required. Any of several techniques can be used. Required field labels can be styled with a more prominent color or a special marker such as an asterisk or a checkmark can be positioned near the field. Required fields also can be co-located and set apart using the <fieldset> and <legend> tags. If a field value fails validation, it is common practice to provide an error message and then to set the focus into the field; the cursor is positioned in the field to facilitate an immediate correction. As the cursor can be difficult to spot on a busy form, it is also possible to change the background color of the incorrect field as a way of drawing the user's attention to the field. In this illustration, the background color of the field has been changed to yellow: Implementing this technique requires writing a small JavaScript function that changes the background color of the field, and then calling that function when field validation fails.
Read more
  • 0
  • 0
  • 3757

article-image-everything-package-concrete5
Packt
28 Mar 2011
10 min read
Save for later

Everything in a Package with concrete5

Packt
28 Mar 2011
10 min read
  concrete5 Beginner's Guide Create and customize your own website with the Concrete5 Beginner's Guide What's a package? Before we start creating our package, here are a few words about the functionality and purpose of packages: They can hold a single or several themes together You can include blocks which your theme needs You can check the requirements during the installation process in case your package depends on other blocks, configurations, and so on A package can be used to hook into events raised by concrete5 to execute custom code during different kind of actions You can create jobs, which run periodically to improve or check things in your website These are the most important things you can do with a package; some of it doesn't depend on packages, but is easier to handle if you use packages. It's up to you, but putting every extension in a package might even be useful if there's just a single element in it—why? You never have to worry where to extract the add-on. It always belongs in the packages directory An add-on wrapped in a package can be submitted to the concrete5 marketplace allowing you to earn money or make some people in the community happy by releasing your add-on for free Package structure We've already looked at different structures and you are probably already familiar with most of the directories in concrete5. Before we continue, here are a few words about the package structure, as it's essential that you understand its concept before we continue. A package is basically a complete concrete5 structure within one directory. All the directories are optional though. No need to create all of them, but you can create and use all of them within a single package. The directory concrete is a lot like a package as well; it's just located in its own directory and not within packages. Package controller Like the blocks we've created, the package has a controller as well. First of all, it is used to handle the installation process, but it's not limited to that. We can handle events and a few more things in the package controller; there's more about that later in this article. For now, we only need the controller to make sure the dashboard knows the package name and description. Time for action - creating the package controller Carry out the following steps: First, create a new directory named c5book in packages. Within that directory, create a file named controller.php and put the following content in it: <?php defined('C5_EXECUTE') or die(_("Access Denied.")); class c5bookPackage extends Package { protected $pkgHandle = 'c5book'; protected $appVersionRequired = '5.4.0'; protected $pkgVersion = '1.0'; public function getPackageDescription() { return t("Theme, Templates and Blocks from concrete5 for Beginner's"); } public function getPackageName() { return t("c5book"); } public function install() { $pkg = parent::install(); } } ?> You can create a file named icon.png 97 x 97 pixels with 4px rounded transparent corners. This is the official specification that you have to follow if you want to upload your add-on to the concrete5 marketplace. Once you've created the directory and the mandatory controller, you can go to your dashboard and click on Add Functionality. It looks a lot like a block but when you click on Install, the add-on is going to appear in the packages section. What just happened? The controller we created looks and works a lot like a block controller, which you should have seen and created already. However, let's go through all the elements of the package controller anyway, as it's important that you understand them: pkgHandle: A unique handle for your package. You'll need this when you access your package from code. appVersionRequired: The minimum version required to install the add-on. concrete5 will check that during the installation process. pkgVersion: The current version of the package. Make sure that you change the number when you release an update for a package; concrete5 has to know that it is installing an update and not a new version. getPackageDescription: Returns the description of your package. Use the t-function to keep it translatable. getPackageName: The same as above, just a bit shorter. install: You could remove this method in the controller above, since we're only calling its parent method and don't check anything else. It has no influence, but we'll need this method later when we put blocks in our package. It's just a skeleton for the next steps at the moment. Moving templates into package Remember the templates we've created? We placed them in the top level blocks directory. Worked like a charm but imagine what happens when you create a theme which also needs some block templates in order to make sure the blocks look like the theme? You'd have to copy files into the blocks directory as well as themes. This is exactly what we're trying to avoid with packages. It's rather easy with templates; they work almost anywhere. You just have to copy the folder slideshow from blocks to packages/c5book/blocks, as shown in the following screenshot: This step was even easier than most things we did before. We simply moved our templates into a different directory—nothing else. concrete5 looks for custom templates in different places like: concrete/blocks/<block-name>/templates blocks/<block-name>/templates packages/<package-name>/blocks/<block-name>/templates It doesn't matter where you put your templates, concrete5 will find them. Moving themes and blocks into the package Now that we've got our templates in the package, let's move the new blocks we've created into that package as well. The process is similar, but we have to call a method in the installer which installs our block. concrete5 does not automatically install blocks within packages. This means that we have to extend the empty install method shown earlier. Before we move the blocks into the package you should remove all blocks first. To do this, go to your dashboard, click on Add Functionality, click on the Edit button next to the block you want to move, and click on the Remove button in the next screen. We'll start with the jqzoom block. Please note; removing a block will of course, remove all the blocks you've added to your pages. Content will be lost if you move a block into a package after you've already used it. Time for action – moving jQZoom block into the package Carry out the following steps: As mentioned earlier, remove the jqzoom block from you website by using the Add Functionality section in your dashboard. Move the directory blocks/jqzoom to packages/c5book/blocks. Open the package controller we created a few pages earlier; you can find it at packages/c5book/controller.php. The following snippet shows only a part of the controller, the install method. The only thing you have to do is insert the highlighted line: public function install() { $pkg = parent::install(); // install blocks BlockType::installBlockTypeFromPackage('jqzoom', $pkg); } Save the file and go to your dashboard again. Select Add Functionality and locate the c5book package; click on Edit and then Uninstall Package and confirm the process on the next screen. Back on the Add Functionality screen, reinstall the package again, which will automatically install the block. What just happened? Besides moving files, we only had to add a single line of code to our existing package controller. This is necessary, because blocks within packages aren't automatically installed. When installing a package, only the install method of the controller is called, exactly the place where we hook into and install our block. The installBlockTypeFromPackage method takes two parameters: The block handle and the package object. However, this doesn't mean that packages behave like namespaces. What does this mean? A block is connected to a package. This is necessary in order to be able to uninstall the block when removing the package along with some other reasons. Even though there's a connection between the two objects, a block handle must be unique across all packages. You've seen that we had to remove and reinstall the package several times while we only moved a block. At this point, it probably looks a bit weird to do that, especially as you're going to lose some content on your website. However, when you're more familiar with the concrete5 framework, you'll usually know if you're going to need a package and make that decision before you start creating new blocks. If you're still in doubt, don't worry about it too much and create a package and not just a block. Using a package is usually the safest choice. Don't forget that all instances of a block will be removed from all pages when you uninstall the block from your website. Make sure your package structure doesn't change before you start adding content to your website. Time for action - moving the PDF block into the package Some blocks depend on helpers, files and libraries, which aren't in the block directory. The PDF generator block is such an example. It depends on a file found in the tools directory in the root of your concrete5 website. How do we include such a file in a package? Move the pdf directory from blocks to packages/c5book/blocks since we also want to include the block in the package. Locate the c5book directory within packages and create a new subdirectory named tools. Move generate_pdf.php from tools to packages/c5book/tools. Create another directory named libraries in packages/c5book. Move the mpdf50 from libraries to packages/c5book/libraries. As we've moved two objects, we have to make sure our code looks for them in the right place. Open packages/c5book/tools/generate.php and look for Loader::library at the beginning of the file. We have to add a second parameter to Loader::library, as shown here: <?php defined('C5_EXECUTE') or die(_("Access Denied.")); Loader::library('mpdf50/mpdf', 'c5book'); $fh = Loader::helper('file'); $header = <<<EOT <style type="text/css"> body { font-family: Helvetica, Arial; } h1 { border-bottom: 1px solid black; } </style> EOT; Next, open packages/c5book/blocks/pdf/view.php. We have to add the package handle as the second parameter to make sure the tool file is loaded from the package. <!--hidden_in_pdf_start--> <?php defined('C5_EXECUTE') or die(_('Access Denied.')); $nh = Loader::helper('navigation'); $url = Loader::helper('concrete/urls'); $toolsUrl = $url->getToolsURL('generate_pdf', 'c5book'); $toolsUrl .= '?p=' . rawurlencode($nh->getLinkToCollection($this- >c, true)); echo "<a href="{$toolsUrl}">PDF</a>"; ?> <!--hidden_in_pdf_end--> What just happened? In the preceding example, we put got a file in the tools directory and a PDF generator in the libraries directory, which we had to move as well. Even at the risk of saying the same thing several times: A package can contain any element of concrete5—libraries, tools, controllers, images, and so on. By putting all files in a single package directory, we can make sure that all files are installed at once, thus making sure all dependencies are met. Nothing has changed beside the small changes we've made to the commands, which access or load an element. A helper behaves like a helper, no matter where it's located. Have a go hero – move more add-ons We've moved two different blocks into our new package, along with the slideshow block templates. These aren't all blocks we've created so far. Try to move all add-ons we've created into our new package. If you need more information about that process, have a look at the following page: http://www.concrete5.org/documentation/developers/system/packages/
Read more
  • 0
  • 0
  • 1965
article-image-plug-ins-and-dynamic-actions-oracle-application-express-and-ext-js
Packt
22 Mar 2011
7 min read
Save for later

Plug-ins and Dynamic Actions with Oracle Application Express and Ext JS

Packt
22 Mar 2011
7 min read
Oracle Application Express 4.0 with Ext JS Deliver rich desktop-styled Oracle APEX applications using the powerful Ext JS JavaScript library Plug-ins and dynamic actions are the two most exciting new features for developers in APEX 4.0. Combining them with Ext JS components is a recipe for success. For the first time we now have the ability to add custom "widgets" directly into APEX that can be used declaratively in the same way as native APEX components. Plug-ins and dynamic actions are supported with back end integration, allowing developers to make use of APEX provided PL/SQL APIs to simplify component development. Plug-ins give developers a supported mechanism to enhance the existing built-in functionality by writing custom PL/SQL components for item types, regions, and processes. Dynamic actions provide developers with a way to define client-side behavior declaratively without needing to know JavaScript. Using a simple wizard, developers can select a page item and a condition, enter a value, and select an action (for example, Show, Hide, Enable, and Show Item Row). Most APEX developers come from a database development background. So, they are much more comfortable coding with PL/SQL than JavaScript. The sooner work is focused on PL/SQL development the more productive APEX developers become. The ability to create plug-ins that can be used declaratively means developers don't have to write page-specific JavaScript for items on a page, or use messy "hacks" to attach additional JavaScript functionality to standard APEX items. Ext JS provides a rich library of sophisticated JavaScript components just waiting to be integrated into APEX using plug-ins. A home for your plug-ins and dynamic actions APEX allows you to create plug-ins for item, region, dynamic action, and process types. Like templates and themes, plug-ins are designed to be shared, so they can be easily exported and imported from one workspace application to another. Plug-ins can also be subscribed, providing a way to easily share and update common attributes between plug-ins. Building a better Number Field APEX 4.0 introduced the Number Field as a new item type, allowing you to configure number-range checks by optionally specifying minimum and maximum value attributes. It also automatically checks that the entered value is a number, and performs NOT NULL validation as well. You can also specify a format mask for the number as well, presumably to enforce decimal places. This all sounds great, and it does work as described, but only after you have submitted the page for processing on the server. The following screenshot shows the APEX and Ext versions of the Number Field, both setup with a valid number range of 1 to 10,000. The APEX version allows you to enter any characters you want, including letters. The Ext version automatically filters the keys pressed to only accept numbers, conditionally the decimal separator, and the negative sign. It also highlights invalid values when you go outside the valid number range. We are going to build a better Number Field using APEX plug-ins to provide better functionality on the client side, and still maintain the same level of server-side validation. The Number Field is quite a simple example, allowing us to be introduced to how APEX plug-ins work without getting bogged down in the details. The process of building a plug-in requires the following: Creating a plug-in in your application workspace Creating a test page containing your plug-in and necessary extras to test it Running your application to test functionality Repeating the build/test cycle, progressively adding more features until satisfied with the result Creating a plug-in item For our Number Field, we will be creating an item plug-in. So, navigate to the plug-ins page in Application Builder, found under Application Builder | Application xxx | Shared Components | Plug-ins, and press Create to open the Plug-in Create/Edit page. Start filling in the following fields: Name: Ext.form.NumberField. Here, I'm using the Ext naming for the widget, but that's just for a convenience. Internal Name: Oracle's recommendation here is to use your organization's domain name as a prefix. So for example, a company domain of mycompany. com would prefix a plug-in named Slider, would result in an internal name of COM.MYCOMPANY.SLIDER. File Prefix: As we are referencing the Ext JavaScript libraries in our page template, we can skip this field completely. For specialized plug-ins that are only used on a handful of specific pages, you would attach a JavaScript file here. Source: For the PL/SQL source code required to implement our plug-in, you can either enter it as a PL/SQL anonymous block of code that contains functions for rendering, validating and AJAX callbacks, or refer to code in a PL/SQL package in the database. You get better performance using PL/SQL packages in the database, so that's the smart way to go. Simply include your package function names in the Callbacks section, as shown in the following screenshot, noting that no AJAX function name is specified as no AJAX functionality is required for this plug-in. The package doesn't need to exist at this time—the form will submit successfully anyway. Standard attributes: In addition to being able to create up to ten custom attributes, the APEX team has made the standard attributes available for plug-ins to use. This is really useful, because the standard attributes comprise elements that are useful for most components, such as width and height. They also have items such as List of Values (LOV), which have more complicated validation rules already built-in, checking SQL queries used for the LOV source are valid queries, and so on. For the Number Field, only a few attributes have been checked: IsVisible Widget: Indicating the element will be displayed Session State Changeable: So that APEX knows to store the value of the item in session state Has Read Only Attribute: So that conditional logic can be used to make the item read only Has Width Attributes: Allowing the width of the item to be set Notice that some of the attributes are disabled in the following screenshot. This is because the APEX Builder conditionally enables the checkboxes that are dependent on another attribute. So, in this screenshot the List of Values Required, Has LOV Display Null Attributes, and Has Cascading LOV Attributes checkboxes are disabled, because they are dependant on the Has List of Values checkbox. Once it is checked, the other checkboxes are enabled. Custom attributes: Defining the custom attributes for our Number Field is largely an exercise in reviewing the configuration options available in the documentation for Ext.form.NumberField, and deciding which options are most useful to be included. You need to also take into account that some configuration options are already included when you define an APEX item using your plug-in. For example, Item Label is included with an APEX item, but is rendered separately from the item, so don't need to be included. Likewise Value Required is a validation rule, and is also separate when rendering the APEX item. The following next screenshot shows some Ext.form.NumberField configuration options, overlaid with the custom attributes defined in APEX for the plug-in: I've chosen not to include the allowBlank config option as a custom attribute, simply because this can be determined by the APEX Value Required property. Other Configuration options, such as allowDecimals and allowNegative, are included as custom attributes as Yes/No types. The custom attributes created are listed in the following table: Custom events: Custom events are used to define JavaScript event that can be exposed to dynamic actions. For this simple plug-in, there is no need to define any custom events. At this point, we are done defining the Number Field in APEX; it's time to turn our attention to building the database package to execute the Callbacks to render and validate the plug-in.
Read more
  • 0
  • 0
  • 2060

article-image-modx-web-development-creating-lists
Packt
10 Mar 2011
7 min read
Save for later

MODx Web Development: Creating Lists

Packt
10 Mar 2011
7 min read
Menu details in document properties Every resource that can be shown in a menu must have the Shown in Menu option enabled in the resource's setting page. The Resource setting page also has two other options related to menus: Menu title—what to show in the menu. The resource title is used, if this value is left blank. Menu index—when a list of the resources that are to be listed in the menu is created, the menu index can be used to sort the resources in the required order. Menu index is a number, and when creating lists we can specify how we want to use the index. Authentication and authorization When creating the list of resources, WayFinder lists only those resources that are accessible by the user depending on the access permissions set for each resource, and the web user group to which the user belongs. Getting to know WayFinder WayFinder is a snippet that outputs the structure of the resources as reflected in the resource tree. It creates the lists of all the resources that can be accessed by the current user, from those that been marked as Shown in Menu in the resource properties. Let's try out an exercise to discover WayFinder. Create a new resource. Set the name as testing wayfinder. Choose the template as (blank). Place the following as the content: [[Wayfinder?startId=`0` ]] Save the document, and then preview it. You will see a screen like the one shown in the following screenshot: Notice that WayFinder has created a list of all of the resources, even the ones from the sample site. Each item is a link, so clicking on it leads you to the corresponding document. The generated HTML will look like the following example: <ul><li><a href="http://localhost/learningMODx/" title="Home" >Home</a></li><li><a href="/learningMODx/index.php?id=2" title="Blog" >Blog</a></li><li><a href="/learningMODx/index.php?id=15" title="MODx Features">Features</a><ul><li><a href="/learningMODx/index.php?id=16"title="Ajax" >Ajax</a></li><li><a href="/learningMODx/index.php?id=22" title="Menus and Lists">Menus and Lists</a></li><li><a href="/learningMODx/index.php?id=14" title="Content Management">Manage Content</a></li><li class="last"><a href="/learningMODx/index.php?id=24"title="Extendable by design" >Extendability</a></li></ul></li><li><a href="/learningMODx/index.php?id=33" title="Getting Help">Getting Help</a></li><li><a href="/learningMODx/index.php?id=32" title="Design" >Design</a></li><li><a href="/learningMODx/index.php?id=53" title="Signup Form">Signup Form</a></li><li><a href="/learningMODx/index.php?id=6" title="Contact Us" >Contactus</a></li><li><a href="/learningMODx/index.php?id=54" title="Getting to knowditto" >Getting to know ditto</a><ul><li><a href="/learningMODx/index.php?id=55" title="Sports RSS" >Sports RSS</a></li><li><a href="/learningMODx/index.php?id=56" title="Lifestyle RSS">Lifestyle RSS</a></li><li class="last"><a href="/learningMODx/index.php?id=57" title="ITRSS" >IT RSS</a></li></ul></li><li class="last active"><a href="/learningMODx/index.php?id=58"title="testing wayfinder" >testing wayfinder</a></li></ul> As seen in the preceding output, the generated list is just a set of <ul> and <li> tags. Let's go step-by-step, in understanding how the preceding output can be customized and themed, starting with menus of one level. Theming To be able to theme the list generated by WayFinder to appear as menus, we need to understand how WayFinder works in more detail. In this section, we will show you step-by-step how to create a simple menu without any sub-items, and then proceed to creating menus with sub-items. Creating a simple menu Since, for now, we only want a menu without any submenu items, we have to show resources only from the top level of the resource tree. By default, WayFinder will reflect the complete structure of the resource tree, including the resources within containers, as seen in the preceding screenshot. WayFinder lets you choose the depth of the list via the &level parameter. The parameter &level takes a value indicating the number of levels that WayFinder should include in the menu. For our example, because we only want a simple menu with no submenu items, &level is set to 1. Now, let us change the testing wayfinder resource, which we just created, to the following code: [[Wayfinder?startId=`0` &level=`1` ]] Preview the resource now, and you will see that the source code of the generated page in place of Wayfinder is: <ul><li><a href="http://localhost/learningMODx/" title="Home" >Home</a></li><li><a href="/learningMODx/index.php?id=2" title="Blog" >Blog</a></li><li><a href="/learningMODx/index.php?id=15" title="MODx Features">Features</a></li><li><a href="/learningMODx/index.php?id=33" title="Getting Help">Getting Help</a></li><li><a href="/learningMODx/index.php?id=32" title="Design" >Design</a></li><li><a href="/learningMODx/index.php?id=53" title="Signup Form">Signup Form</a></li><li><a href="/learningMODx/index.php?id=6" title="Contact Us" >Contactus</a></li><li><a href="/learningMODx/index.php?id=54" title="Getting to knowditto" >Getting to know ditto</a></li><li class="last active"><a href="/learningMODx/index.php?id=58"title="testing wayfinder" >testing wayfinder</a></li></ul> Now, if we can just give <ul> and <li> respective classes, we can style them to appear as a menu. We can do this by passing the class names to the parameter &rowClass. Change the contents of the preceding testing wayfinder to: <div id="menu">[!Wayfinder?startId=`0` &level=`1` &rowClass=`menu`!]</div> Now, open style.css from the root folder, and change the CSS to the following code. What we are doing is styling the preceding generated list to appear like a menu, by using CSS: * { padding:2; margin:0; border:1; }body { margin:0 20px; background:#8CEC81; }#banner { background: #2BB81B; border-top:5px solid #8CEC81; borderbottom:5px solid #8CEC81; }#banner h1 { padding:10px; }#wrapper { background: #8CEC81; }#container { width: 100%; background: #2BB81B; float: left; }#content { background: #ffffff; height:600px; padding:0 10px 10px10px; clear:both; }#footer { background: #2BB81B; border-top:5px solid #8CEC81; borderbottom:5px solid #8CEC81; }.clearing { clear:both; height:0; }#content #col-1 {float:left;width:500px; margin:0px;padding:0px;}#content #col-2 {float:right; width:300px; margin:0px; padding:30px 010px 25px; border-left:3px solid #99cc66; height:500px;}#content #col-2 div {padding-bottom:20px;}#menu {background:#ffffff;float: left;}#menu ul {list-style: none;margin: 0;padding: 0;width: 48em;float: left;}#menu ul li {display: inline;}#menu a, #menu h2 {font: bold 11px/16px arial, helvetica, sans-serif;display: inline;border-width: 1px;border-style: solid;border-color: #ccc #888 #555 #bbb;margin: 0;padding: 2px 3px;}#menu h2 {color: #fff;background: #000;text-transform: uppercase;}#menu a {color: #000;background: #2BB81B;text-decoration: none;}#menu a:hover {color: #2BB81B;background: #fff;} Also remember to change the template of the resource to the learning MODx default template. Now preview the page, and you will see something like the one shown in the following screenshot: The HTML code returned will be similar to the following: <ul><li class="menu"><a href="http://localhost/learningMODx/"title="Home" >Home</a></li><li class="menu"><a href="/learningMODx/index.php?id=2" title="Blog">Blog</a></li><li class="menu"><a href="/learningMODx/index.php?id=15" title="MODxFeatures" >Features</a></li><li class="menu"><a href="/learningMODx/index.php?id=33"title="Getting Help" >Getting Help</a></li><li class="menu"><a href="/learningMODx/index.php?id=32"title="Design" >Design</a></li><li class="menu"><a href="/learningMODx/index.php?id=53" title="SignupForm" >Signup Form</a></li><li class="menu"><a href="/learningMODx/index.php?id=6" title="ContactUs" >Contact us</a></li><li class="menu"><a href="/learningMODx/index.php?id=54"title="Getting to know ditto" >Getting to know ditto</a></li><li class="menu last active"><a href="/learningMODx/index.php?id=58"title="testing wayfinder" >testing wayfinder</a></li></ul> Notice that for each menu item, the class menu has been applied. Although we have not applied any custom style to the menu class, we have shown you that when you are building more fine-grained menu systems, you have the ability to have every item associated with a class.
Read more
  • 0
  • 0
  • 2189