Open Designer Tutorial

If you fine this page helpful, then lets promote each other.
Exchange links with me, Click hereThanks, Ray

Developer Documents by Ray Yates
Important Developer Documentation -- Add these links to your favorites. You will need them.
Tutorials
Open Designer user written tutorial. -- Concepts, examples and debugging tips.
Open Designer Advanced Technique -- Understanding merchant screens forms
Adding the W3C DOCTYPE to Miva Merchant output.
Miva Merchants Nested Tables Diagram -- Understanding Merchant/OpenUI layout
Cross Reference Listings
Open Designer Object Dependents -- Cross Reference list of object relationships.
OpenUI Token Shortcuts -- A list of most token shortcuts available in OUI.
OpenUI Module -- Open Designer Cross Reference -- Hookpoints, Module, Function, Screen Code, Object.


Created 12/19/2003
Last updated 11/18/2004
 

What's new?

October/November 2004. Open Designer Interface change.

Open Designer is currently undergoing it most significant update since it's introduction. Once complete it will sport a new interface, exciting new features, and the new OpenUITurbo token parcing engine and more, all designed to increase your productivity and speed your Merchant store. When finished, you will see a complete update of the tutorial. To those of you struggling to learn OD now, I'm sorry that the graphics are out of date but the functionality is still there. It has just been re-arranged. As soon as the current beta is released, I'll update this document.

11/18/2004 Theme Selection updated
10/05/2004 Corrections
07/09/2004 Jump Start guide with images and Tutorial update.
07/08/2004 Updated the preface OpenUI tokens.
05/07/2004 Example 6 updated. Fixed a bug in detecting inactive categories.
04/12/2004 Example 6 updated. The object will now restore category pointers to the state before the call to the object.
03/29/2004 Preface: OpenUI Tokens Discussion of token basics; skills needed to read and write OpenDesigner objects.
03/17/2004 OpenDesigner Quick-Start Overview by Eric Randall.

Forward: I offer this tutorial, learned through trial, error and help from the forum, to help the Merchant / OpenUI Community and especially OpenDesigner users. I'm no expert and don't work for OpenUI or Darren Ehlers so don't flame me if I don't get some details wrong. <grin>  I can’t tell you what to do if you have crashed your system. OD contains complete power to really screw up your screens. If you have managed to destroy some of the objects you can reset them by selecting Your Store | Utility | OpenIU OpenObjects™ (v#.x) and resetting the objects and sets back to the original. IMPORTANT NOTE: In my opinion, every time you download updates, you should reset the original objects. Why? Because downloading the objects does not "replace" them in the database. Why Not? Because OD lets you alter those objects and resetting them will also remove your changes. Also keep seperate offline text copies of all of your objects. I write more on this topic below.

Contents

Preface: OpenUI Tokens

Part 1: Tutorial Topics

Part 2: Working with Tokens and Objects -- Code Examples

Preface: OpenUI Tokens

OpenDesigner is a powerful extension and user interface for OpenUI tokens exposing the inner working of Miva Merchant. It will allow you to completely change the look and feel of your Miva Merchant store. Knowledge of OUI Tokens and Token-Shortcuts is essential to make more that simple html changes to your store with OpenDesigner. The most basic job of tokens, is to output html to the screen. Where html creates static pages, tokes let you present your users with dynamic pages customized just for them. Unlike JavaScript, it does it's job on the server.

To begin, you should look over each token available to you in the OpenUI™ Token & Object Usage Guide. The 30 or so "basic" tokens provide the foundation of a server side scripting language. Along with all the variations on those basic tokens are expanded syntax versions increasing the number to around 80 plus the tokens shortcuts available in the drop down boxes on header and footer screens within Admin. In all, tokens provides a rich feature set which can be overwhelming at first. Start your exploration with the basic tokens. Read about each one even if you don't full understand. I promise, at some point you are going to think, "I remember something about that." You will usually have that thought right before having an epiphany. When you are looking at OD objects, keep the token reference open and available.

You will see and use these tokens constantly. %VAR()%, %SET()%, %ASSIGN()%, %EXPR()%, %IF()% %ELSE% and %IFEND%. Understand them and you will begin to grasp many of the other tokens. I will compare them to JavaScript so you can get an overview of the syntax.

Variables are the heart of token script. You will normally use two classes of variables, global and database fields. Global variables all have the form g.variable_name. The current screen code then is stored in the variable g.screen. View source for the login screen and find the <form>tag. In the form you will see <input type="hidden" name="screen" value ="LOGN">. when the form is submitted, screen becomes the variable g.screen with the string value "LOGN". The same applies to every <input> tag on the screen The name becomes g.variable_name. There are also built in system variables, for accessing system date, time, CGI, HTTP and others.

Database variables all have the form database_alias.d.fieldname,  For the Products database the name of the product is stored in Products.d.name. There are thousands of these all with the same format. Bookmark this page. Miva Merchant 4x Database Reference Manual so you can look them up when needed.

Tokens that evaluate expressions will let you directly add MivaScript operators and functions to your headers and objects. You will see these frequently use in the objects provided by OpenDesigner. Operators include the arithmetical, comparison, logical, text string, and bitwise operators. Functions include the time and date, text string, numeric, file system, language, system, and encryption. The MivaScript tags are the core of the MivaScript language and are the basis of OpenUI tokens. For example; where MivaScript offers <MvASSIGN>, OpenUI tokens offers %ASSIGN()% which operates in a similar way. You will want to examine and bookmark the Miva Script Guide and the Miva Script Reference Manual. There will be times when the OpenUI documentation just does not provide enough detail.

The %VAR()% token will simply output a variables literal contents but will not normally evaluate expressions unless formatting options are used.Unlike JavaScript document.write() however, It can output its contents in some unexpected and powerful ways. Be sure an look over all the formatting options available with %VAR()%. There are a lot of them and there uses may not be immediately apparent.

Examples:
%VAR(g.sessionurl)% will output the URL of the storefront.
%VAR(g.sessionurl)%Screen=LOGN&Order=0 will output the URL of the login page
%VAR(g.secure_sessionurl)%Screen=LOGN&Order=0 will output the secure (https://) URL of the login page.
%VAR(g.myzipcode)% is similar to JavaScript's document.write(myzipcode)

The %SET()% token and %ASSIGN()% seem similar at first, but SET will only allow you to set a variables literal contents. I does not evaluate, or parce the values you set so you can not use it directly with an expression or use it to directly assign a variables value to another variable.

Examples:
%SET(g.myzip|40222)% is equivalent to JavaScript myzip = "40222".
Correct: %SET(g.myname|Ray Yates)%
Wrong: %SET(g.myname|Customer.d.shipFname)%
Correct but: %SET(g.myname|%VAR(Customer.d.ship_fname)%)%
Better:  %ASSIGN(g.myname|Customer.d.ship_fname)%

Note: With SET you do not use quotations marks around string literals, unless you want to include quotations marks, as part of the stored string.

%EXPR()%. and %ASSIGN()% tokens are use with more complex expressions that require evaluation. You can also imbed tokens inside other tokens and sometimes the syntax requires that you do so. Many tokens will evaluate expressions and variables, while some require literals. Unfortunately, it will not always be obvious. as with array indexes.

Examples:
%EXPR(g.myzip5 $ '-' $ g.myzip4)%.
%ASSIGN(g.myfullzip|g.myzip4 $ '-' $ g.myzip4)%
%ASSIGN(g.count|g.count + 1)%

With ASSIGN use single quotes to enclose string literals and $ to add them together as in this example

%ASSIGN(g.wholename|'Mr.' $ customers.d.ship_fname $ ' ' $ 'customers.d.ship_lname)%

Array indexes can not be a variable but must use the %VAR()% token to parse the variable.

Examples:
Correct: %ASSIGN(g.MY_names[1]|Categories.d.name)%
Wrong: %ASSIGN(g.MY_names[g.count]|Categories.d.name)%
Correct: %ASSIGN(g.MY_names[%VAR(g.count)%]|Categories.d.name)%

Flow control: The %IF(expression)%,  %ELSE%, %IFEND%, %WHILE(expression)%, and %WHILEEND% tokens are like other language constructs and are the fundamental way that you control the flow of your programs. Flow control expressions can take many forms and can be used with these logic operators

Logic Operators Meaning
GT Greater Than
LT Less Than
EQ Equal
NE Not Equal
GE Greater than or Equal
LE Less than or Equal
NOT Logical Not
AND Logical And
OR Logical Or
Arithmetical Operators (+, -, *, /, MOD, POW, ROUND)
String Operators ($ , IN, CIN, EIN, ECIN, CRYPT).
Conditional Expression Examples:
%IF(g.screen EQ 'SFNT')%
%IF((A + B) GE (C * D))%
%IF((Categories.d.name EQ 'Shirts') AND (Products.d.name EQ 'Jersey'))%
%IF(NOT (g.OUI_ok EQ 1))%
%IF('300' IN '100200300400500')%
%IF(g.screen CIN 'SFNT,OSEL
%WHILE(g.count LT 100)%
    %ASSIGN(g.count|g.count + 1)%
    %VAR(g.count)%<br>
%WHILEEND%

 

Part 1 OpenDesigner Tutorial:

Required Knowledge:

A good knowledge of html essential because you will be coding html by hand. A fair knowledge of programming concepts (if, then else, while etc) is also required so you can make some sense out of the object code. Knowledge of OUI Tokens and Token-Shortcuts is essential to do anything more advanced than tweaking html. But if you just want to change the look of your Merchant pages, html modifications may be all you need. If you’ve never used a token, get some skill with using them in your store header and footer screens before taking on OD. Tokens are a way to execute server side MivaScript, the language Merchant is written in. Knowledge of MivaScript is not required to get started, but can be useful because you can directly execute Miva Merchant commands and call Merchants database, module and MivaScript functions directly. For some tokens like the %DB()% database tokens, you must use the MivaScript guides. This opens the door to direct database access and much more. Skill with client side JavaScript or VbScript as well as Cascading Style Sheets (CSS) is not necessary but useful and will let you do things like mouse over effects, special processing and much more. I highly recommend learning CSS.

Keep documents listed here bookmarked. You will need these.

Basics Concepts:

Navigate to the OD screen and lets review some concepts named Themes, Theme Selection, Sets, and Objects.

Objects are server side programs, constructed from primarily from OUI tokens and HTML, but which may include JavaScript and anything else that you might see in a web page.  These programs output the source code for the screens we see in Merchant and more. Sets are collections of Objects. An Object may be a member of many Sets or just one. A Set must belong to a Theme to become active. By Design, you can only assign a Set to one Theme, but a Theme may contain many Sets of Objects.

If all that is confusing think of it this way. A house (Set) may contain many items (Objects) but the house has only one Master (Theme). But, the Master (Theme) may own many houses (Sets) containing many objects. Too much metaphor you say? Let’s get practical then.

The Active Theme -> has a Default Set -> containing many Objects.

When you first start Open Designer, none of these objects are active. Once you enable the object it is still not active. What is active is the original built-in, OpenUI MivaScript versions of all these objects. These objects, written in TokenScript, are designed to be replacements for the built in code. To see them in action, you must assign them to the default set of the active theme.

A detailed explaination of how all this works is below, but lets just do it and come back to the details later.

Jump Start:

     Ten steps to your first modification.

1. Keep in mind, this gets easier once you get past creating your first themes and sets. Go to the Themes tab. You will see the DEFAULT_OPENUI theme and three sets named OPENUI_DEFAULT, OpenUI v1.x API, OpenUI v2.x API. My advice is to leave them alone. If you ever need to go back to a "pure non-OD store" these could come in handy.

2. Create two new Themes. (Why two? Trust me. <grin>) Click on the yellow "New Theme" button, add a code and name. I call mine FH_DEFAULT / Flying Hands Default and FH_ALTERNATE / Flying Hands 2. Call yours what ever is appropriate for your store. The "code" is the important part here you will use it later. Click Update

3. At first there the Default Set is {none}, so let's create them. Click on the Sets tab then click the Theme Filter dropdown box and select the new theme you just created. Click the yellow New Set button. I call mine FH_SET as shown below. Again, call yours whatever is appropriate. Click Update. Repeat the process for your ALTERNATE theme.
 

4. Return to the theme tab. You will now see the set assigned to your new theme but still the themes default set says {none}. At the end of the themes row click the edit here button, the new theme will be selected as the default so just click Update. Again, repeat the process for your ALTERNATE theme. The results should look something like this.

5. At this point you have two new themes and sets, however, neither is active. Remember the exact name and case sensitive spelling of your theme then select the Theme Selection tab. Paste the code below into the Theme Selection box. Edit this script adding your login (You do have a customer login name for your store right?) and the codes of your default and alternate themes. Click Update.

Theme Selection


 

What this does is enable your default theme for the world to see and provides you with a way to test new objects without showing them to the world. When you login, you will see the alternate theme and can test and debug your objects online before presenting them to your customers or clients.

6. The default theme is now active, but the objects are not so your store should look exactly the way it did before. Return to the Theme window, and click the link for your active default set. This takes you to the Object Set: screen. There is no tab for this screen, because there could be an unlimited number of sets. You can get here from the themes tab or the sets tab, but you will find this more convenient.

The Object Set screen is the traffic cop for your objects. Initially you will see a long list of Codes (sometimes called virtual codes) a filter box and most importantly a drop down box that says disabled. The list of codes is a list of internal objects that OpenUI calls when it needs to perform a task. For example; When OpenUI needs to display Merchants Error screen it looks for the ERROR code. If it finds it set to disabled, it calls the built-in program to display the code, if it finds the code has been set to an object like OUI2_ERROR, It call OUI2_ERROR instead.

The beauty of OpenDesigner, is this ability to "re-wire" your store at a fundamental level and even add your own Codes to create new screens, sub-routines, and completely new features like my link exchange program. Click here

7. Before you can assign any object to your set, you have to have something to assign. Let's customize an object. Merchants error screen provides no navigation, it just dies, so add some. Click the Objects tab. In the Object Set Filter, select OpenUI v2.x API. Scroll down and select OUI2_ERROR. Clone and rename the object

Your new object should now be active, but it is still not assigned to your store. We will make a minor change, assign the object to our active set and view the results.

The first line of the object starts with %OUI%. This is mandatory for any object containing tokens. Paste the following piece of code over the opening %OUI%. Change nothing else and click Update.
 

8. Return to your default Object Set screen. Find the ERROR code and assign your new object. Click Update. The only thing left is to see the results. Browse to your storefront. In the address bar where you see Screen=SFNT change it to Screen=xxx. You should now see the error screen with your global header and navigation bar. Below in the tutorial you will find a detail explanation of the OUI2_ERROR object and a better way to do this. On the OD Forum, you can find a much better version of the error object.

9. When you first start testing your new objects, I'm pretty sure you will notice some weird things going on in your store. Read about Object Dependencies below to understand why and see and bookmark my OpenUI v2.x API Library Object Dependents document to see which other object you need to enable and add to your set. You should use the OUIv2 objects unless you have a module conflict, which I won't go into here.

10. Also, enable both CATTREE_OUILOOKUP and PRODUCT_OUILOOKUP. There is no exact OpenUI match for these objects and no virtual codes. They are both low level subroutines called by many other objects. Finally, hang in there. As I said, it gets easier once you get past creating your first themes and sets.

Objects:

These are the building blocks of your store. Most directly relate to what you see on the screen. Select the Object tab and you will see Object Set Filter. In the list below it, you will see the names of lots and lots of objects. There are two classes of predefined objects OUI1 and OUI2. The first is defined for compatibility with third party modules. Many modules hook into Merchant by using OpenUI hook points. If you have a module that directly affects a screens output then you will likely have to make use of some OUI1 class objects for those to continue to work. If not then use the OUI2 objects. They’re simpler to understand and are coded more efficiently. Don’t worry you can mix and match them in your store. You can also add just the needed hookpoints back into OUIv2 objects. Search the forum for more information.

Select the first object OUI1_AFFADEDIT. To the right the object code will appear. Find %HOOK(56|2)% in the code. This represents a hook point where module might alter code. 56 is the screen number and 2 is the hook point on that screen. For a mostly complete list of screen numbers and there meaning click here.  (I couldn’t find this documented on the OpenUI site)

Changing an Object: OD will let you directly edit and change standard objects. Don’t Do It! As many users, including myself, later realized, resetting an object does NOT restore the original code. It reloads the last saved code. Clone the object and work on the copy. If you need to restore altered v1 or v2 objects  to the original state, select your stores utility link and you will see tabs for OpenUI OpenObjects™ (v1.x) Configuration  and OpenUI OpenObjects™ (v2.x) Configuration. Select them and you will see reset checkboxes that are used to restore the original objects.

Example 1: Replacing the ugly Error Screen: I chose this as my first example because the object code is short and this is easy to implement. If you've gone through the quick start above you are already familiar with this process. In the Object Set Filter:, select OUI2_ERROR. It will appear along with as dropdown box with two options; "Rename Object" and "Clone Object" Select Clone Object, type MY_ERROR as the name and check Enabled. Don’t check User Objects or Enable Hook Points. We'll talk about them later. Click Update to create a new object called "MY_ERROR. now you have a copy that you can alter.

Select <All Objects in the filter and return to MY_ERROR and scroll down till you find

%DOFUNC(g.OUIX_ok|g.Module_Library_Utilities|Screen_Error())%

This one line of code causes the object to output an entire web page. It uses no headers or footers so there is no place to interrupt the output inside the Admin interface admin.mvc. It must be replaced. Comment out the code like this and the error screen will be effectively turned off.

%COMMENT%
%DOFUNC(g.OUIX_ok|g.Module_Library_Utilities|Screen_Error())%
%COMMENTEND%

Now you must create your own replacement page. At the top of the object enter the following:

%OUI%
<html><head>
<!—MY_ERROR Custom object -->

At of bottom of the object enter the following and click update.

<title>Error: %VAR(g.OUIX_message)%</title>
</head><body>

<p>Miva Merchant has encountered an error and is unable to continue.<br>
The following information may assist you in determining the cause of the
error:</p>
<p>Error Code: %VAR(g.OUIX_code)% -- Description: %VAR(g.OUIX_message)%</p>
</body></html>

Here is the complete modified code you can cut and paste:

----------------------------------------------------------------------------------cut here-
%OUI%
<html><head>
<!-- MY_ERROR Custom object -->
%IF(len(g.OUIX_message) EQ 0)%
%SET(g.OUIX_code|UNKNOWN)%
%SET(g.OUIX_message|<B>Unknown Error</B><BR><BR> Action = %VAR(g.Action)%<BR> Screen = %VAR(g.Screen)%)%
%IFEND%

%DOFUNC(g.OUIX_ok|g.Module_Library_Utilities|Error(g.OUIX_code, g.OUIX_message))%

%COMMENT%
%DOFUNC(g.OUIX_ok|g.Module_Library_Utilities|Screen_Error())%
%COMMENTEND%

%SET(g.Screen|)%
%SET(g.Action|)%
%SET(g.OUIX_FatalError|1)%
<!-- End Merchant Error Screen -->

<title>Error: %VAR(g.OUIX_message)%</title>
</head><body>
Miva Merchant has encountered an error and is unable to continue.
The following information may assist you in determining the cause of the error:

<b>Error Code:</b> %VAR(g.OUIX_code)% - <b>Description:</b> %VAR(g.OUIX_message)%
</body></html>
----------------------------------------------------------------------------------cut here-

Commenting out Code: Notice the <!-- --> comment tag. You can add comments to any object and then display the screen and view the source to confirm the object is enabled. You can also comment out entire sections of code that normally generate html. The html will be generated inside a set of comment tags and wont display on the screen. You can also use the token %COMMENT%  %COMMENTEND% to suppress all output and token operations. To more completely suppress code without deleting, you can use the following.

<!-- Client side comment. Suppress code on the client side
%COMMENT% 
     Server side comment. Suppressed code on the server side.
%COMMENTEND%
-->

Testing testing is this thing on? Congratulations. If you've followed these steps, you have created your first object. However, just creating an object is not enough. You must assign the object to your active theme and default set. here's how.

Return to the Themes tab.  In the Sets column, select the default “OpenUI v1.x API" link. On the next screen, scroll down till you see the keyword ERROR. The box next to it should say “<disabled>”. This indicates that the error screen is directed to use Merchants internal error handler. With objects disable, OD does not process the screen but rather passes control to Merchant for processing. Open the box and scroll to select the MY_ERROR object. Click update.

Assuming the default settings have not been changed, it should now work. Create an error by altering the address bar URL pointing to your storefront by entering a bogus screen like

http://www.yourwebsite.com/Merchant2/merchant.mvc?Screen=xxxx

If that fails, check the following:

  1. 1. Themes should contain OPENUI_DEFAULT with a default set of OpenUI v1.x API

  2. 2. On the link  “OpenUI v1.x API", the “ERROR" object should be mapped to MY_ERROR.

  3. 3. The Theme Selection tab should contain OPENUI_DEFAULT

If successful, you can now customize “MY_EROR” further by adding headers, navigation, and footers from your websites html. To see the custom error message on my site, click here.

Example 2: If you prefer, you can also redirect the user to another screen using a little JavaScript. You can test the error code and use that to decide where to send the user.

<script language="JavaScript">
//redirect the user if certain error occurs.
var ecode=”%VAR(g.OUIX_code)%”;
var testcode=”OUI-00001”; //Unknown Screen – change this code as needed.
var url=”http://www.yourwebsite.com/Merchant2/merchant.mvc?Screen=SFNT”;
if (ecode= testcode)
{
 location.href=url;
}
</script>

Themes and Sets:

Make sure you read this section.  Let’s create a theme. Click the Themes tab and click on the yellow icon. If you hold the mouse over it for a few seconds it will say “New Theme”. Enter a code like MY_THEME and a name like My Default  Theme and a description or instructions and click update.

Click the Sets tab. And select MY_THEME in then Theme Filter: box. It’s important that you select the theme in the filter box otherwise the set will be added to the OPENUI_DEFAULT Theme. Click on the yellow icon for “New Set”. Enter a Set Code like My_Custom_Set and any notes or instructions. Click update.

Click back on the Themes tab and click the edit button next to MY_ THEME. You can now select a default set and click update.

You should now see a new tab added to the screen that says MY_ THEME My_Custom_Set. Click it and you will see the now familiar list all assigned to <Disabled> Find ERROR and select the object you created earlier “MY_ERROR”.

NOTE: At this point the Theme is still not active. There is one more step to make this active.

Theme Selection Select this tab and you should see OPENUI_DEFAULT in the text area. Change this to MY_THEME and click update to activate your theme. Since your theme has only one object, MY_ERROR, this is the only change that is active. You can add new objects and mix them with OUI1 or OUI2 objects or leave them disabled and OD will default to Merchants own processing.

Notice the Theme Selection Tab has token shortcuts dropdown boxes on them. Why you ask? Good question. So you can do things like this.

Example 3

%OUI%
%IF(Customers.d.login NE 'your_login_name')%
   FH_DEFAULT_THEME
%ELSE%
   FH_ALT_THEME
%IFEND%

This is a variation on code Darren posted. It lets you set up a theme that only displays when YOU are logged in. All other users see the normal theme. This is how you can develop and test your code while running a live store.

Object Dependencies -- Using objects within objects within objects...

This can get a little complicated so get yourself some coffee then jump in. Many many objects in Open Designer are dependent upon other objects to function correctly. If you've spent any time programming in other languages you are probably familiar with functions or subroutines. Objects act very much like a subroutine in the older interpreted version of the programming language BASIC. Each Object is a way of compartmentalizing code into separate functional blocks that do a specific task.

For example the OUI2_SFNT object, displays your stores entry page. If you enable this object and assign SFNT = OUI2_SFNT in your themes set, you will may find that your main page no longer displays. That is because the OUI2_SFNT uses seven other objects that are common to many of the other objects as listed below. Each of these objects may have to be enable and assigned to your set as well.

 OUI2_SFNT
    OUI2_BEGINSCREEN
        OUI2_GREYMENU
            OUI2_CATTREE
                CATTREE_OUILOOKUP
        OUI2_MAINTENANCE
        OUI2_NAVBAR
    OUI2_ENDSCREEN

I have  indented this list to illustrate that objects can have objects within objects.. OUI2_SFNT calls the BEGINSCREEN object and the ENDSCREEN object. The BEGINSCREEN object in turn uses GREYMENU which uses CATTREE which uses CATTREE _OUILOOKUP.

There are three tokens used to call and execute objects. They are %OBJ()% , %OUIOBJ()%, and %OUIOBJOUT()%. See the OpenUI™ Token & Object Usage Guide for details. You will see in all of the objects that I have included in this tutorial that I use the %OBJ()% token. If you look at the latest version of the OUIxx Objects you will see that they have all been converted in February of 2004 to use the %OUIOBJOUT()% token. The reason for the change is to avoid some of the problems with these dependencies.

Look at your current Set for the virtual code BEGINSCREEN. What ever you have assigned to the virtual code, is the object that will be used when you use the token %OBJ(BEGINSCREEN)%. If nothing is assigned, then nothing will be displayed.  If there is no virtual code, then the token looks for an object named BEGINSCREEN and executes that instead. If it can't find an object with that name, again nothing will be displayed. To use the %OBJ(BEGINSCREEN)% token, you must assign an object like OUI2_BEGINSCREEN or your own custom object like MY_BEGINSCREEN and you must enable the dependent objects and assign them to the appropriate virtual code. BUT WAIT! There is a better way so read on.

I've compiled a complete list of these dependencies and you can view them here Open Designer OUIv2 Object Dependents

A better way. The day after I completed this list, Darren issued a completely new set of objects the eliminate or reduce this problem. all of the %OBJ()% tokens were replaces with the more complicated %OUIOBJOUT()% token. These tokens have the advantage to falling back on the hard-coded OpenIU interface objects if the Object Code called is not assigned and thereby reducing the need to enable and assign dependent objects. All of the code in this tutorial was written prior to that change and still uses the %OBJ()% token.

OK! If you've made it this far there is one more important and as of this writing undocumented feature of the %OBJ()% token. I have quite a few objects that I have written for which there is no virtual code. For instance the FH_CATTABLE object shown in Example 6. If I use the syntax %OBJ(FH_CATTABLE)% the token will look for a virtual object code by that name first in the set (which will fail) then look for an object with that name which will succeed. If I use this alternate syntax %OBJ({FH_CATTABLE})% the token will skip the first check and go straight to the object for display. This is the form that you will see in all of my examples from now on, where I call a custom written object. If you prefer to use the %OUIOBJOUT()% token for calling the supplied OUIxx objects, just copy the syntax from another object that is making the same call. This will eliminate the dependency problem form your objects.

Tutorial Summary

Open Designer gives you the power to make your Miva Merchant Screens work the way you want. It also gives you the power to trash your live store and must be used with some caution. If your uncomfortable working down in the low level details with a beta program, wait for the final version. Here's what we learned.

1. Copy the objects to new objects, don’t edit the originals.
2. You can use comments to suppress code.
3. You can use CSS, JavaScript and VbScript as well as Html, OUITokens and MivaScript.
4. Using Themes in five steps

5. Test your code privately by logging in.
6. Be aware of dependent objects and the implications for using them. Check the dependency list. 

Sorry about the length but there was a lot to cover. I hope I haven’t pointed anybody in the wrong direction . Happy programming.


Part 2 Working with Tokens and Objects -- Code Examples

These code examples are intended to be used as Objects in Open Designer. Many of the techniques can also be used directly in your store with some modifications in a header or footer.

Merchant Objects:

Adding New Screens. For this example, lets add a brand new "Contact Information" screen to our store. Here, you will learn several techniques in one lesson. We will create a "User" object and a template screen that we can use as the foundation for creating any screen we want to add to our store and we will learn a useful debugging tip.

As well as the rich list built in objects, OD is extensible with "User" objects and Merchant Objects called "Special Objects" in the OpenDesigner™ Installation & Usage Guide. The Merchant Objects are different in that they call built in functions of Merchant and allow you to do many things that would otherwise require a module written in MivaScript.

Part 1. Lets begin by creating a new "User" object. User objects show up on the Edit Store screen where they can be edited and saved. They operate exactly like any other object except that they can be altered by regular users and store owners. They are a great place to add user specific data. Select the Objects tab. Select "All Objects in the filter. Select <Add New Object> and type in an object name MY_AddressStreet. (TIP: Adopt a naming convention and use it consistently with all your objects. I begin all of mine with FH so that they sort together in the Object listing. I use mixed case for user objects and lower case for template objects) Also select "Enabled" and "User Object". Finally copy and paste the following code making changes appropriate to your store.

Example 4:

<p><b>Physical Address</b><br>
1234 My Street<br>
City, State Zipcode<br>
Country<br></p>

Finally click the Update button. By creating an address object, you can use it anyplace in your store you need to display your address. If your address changes you only have one object to update. To use the object simply add %OBJ(MY_AddressStreet)% at the point where you want to insert the address. What is a user Object? In the admin, go to your stores Edit Store screen and you will see a new tab called User Objects. Check it out.

Part 2. Create a template object that you can use over and over for adding new screens to your store. Select <Add New Object> and type in an object name like MY_screen_template. Select enabled copy and paste the code below and click Update. I'll explain a this code later, for now just save it.

Example 5:

%OUI%
%SET(g.MyDebug|1)%
%IF(g.MyDebug)%<!-- MY_OBJECTNAME 2/10/2004 -->%IFEND%
%SET(g.OUIX_title|'%VAR(Stores.d.name)% -- Contact us: e-mail, address and phone numbers.')%
%SET(g.OUIX_greymenu|1)%
%SET(g.OUIX_catid|0)%

%IF(g.MyDebug)%<!-- Note: requires BEGINSCREEN + dependents be enabled -->%IFEND%
%OUIOBJOUT(BEGINSCREEN|g.OUIX_ok|OPENUI|OUI_Begin_Screen(g.OUIX_title,g.OUIX_greymenu,g.OUIX_catid))%
%IF(g.OUIX_ok)%
<BR>
<BLOCKQUOTE>
<FONT FACE="%VAR(OUI_Store.d.body_font|EE)%"SIZE="%VAR(OUI_Store.d.body_fsize|EE)%">
%IF(g.MyDebug)%<!-- Start Screen -->%IFEND%


My html and text token code goes here.


%IF(g.MyDebug)%<!-- End Screen -->%IFEND%
</BLOCKQUOTE>
%IF(g.MyDebug)%<!-- Note: requires ENDSCREEN + dependents be enabled -->%IFEND%
%OUIOBJOUT(ENDSCREEN|g.OUIX_ok|OPENUI|OUI_End_Screen())%
%IFEND%

Now lets clone this template to create our Contact screen. In the drop down box, select "Clone Object" and type a name like MY_SCREEN_CONTACT. And click Update. In the area between "Start Screen" and "End Screen" add some simple text for your screen and then add the following using the object name you used before.

%OBJ({MY_AddressStreet})%

Part3. Click Update. Now lets turn this screen on. Select the Set for the active Theme and so that you will be able to see your changes. Scroll to the bottom and you will see a blank textbox where you can add your own object codes. Enter SCREEN_CONTACT in the code box and then select MY_SCREEN_CONTACT in the object dropdown box and click Update.

Browse to your storefront and change the url so that Screen=SFNT becomes Screen=CONTACT and press enter. The screen should display your address. Now you can go back and change the screen to add any information and formatting you wish. To add the new screen to your store you will have to create a link to it. The link url might be something like the following:

http://www.yoursitename.com/Merchant2/merchant.mvc?Screen=contact
or you could use OpenUI tokens like %VAR(g.sessionurl)%Screen=contact

Part 4. Template Description -- The object template above requires some explanation. First what is this line with MyDebug? Glad you asked. I have started adding this line %SET(g.MyDebug|1)% to all my objects so that I can embed comments and debugging information in my object code by bracketing my html comment with %IF(g.MyDebug)% and %IFEND%. When the object is complete I can strip all comments and debugging information from the output by simply changing the line to %SET(g.MyDebug|0)% This makes the code much easier to maintain when I revisit it months or years later.

You see several tokens to call other objects like %OBJ(BEGINSCREEN)% to see what these do simple comment the line out and refresh the screen in your store. The changes will be immediate and obvious. Many of the "higher" level objects make use of the "lower" level or more primitive objects. You can and should use them as well.

Working with Categories and Products:

There are MANY times that you may want to retrieve and display category information outside the category tree. To that end, I offer several routines that may serve as a starting point for your own objects. Remember these code examples DO NOT have to be use in Open Designer Objects. but, as shown they are intended to be used as Objects. 

To use as an Object, copy all of the code from %OUI% to the final %IFENF% to a new object called FH_CATTABLE and update. Then copy just the portion between the %COMMENT% and %COMMENTEND% to your categories header or footer remembering to add %OUI% to the first line. That's it, View your category tree and select the appropriate category.

Remember, This will display the sub-categories to the current category. If there are no sub categories, then an error message will display instead.

Displaying Sub-Categories in a Table

Example 6

This object is intended to be called from a category header of footer.

%OUI%
%COMMENT%
<!-- Object name = FH_CATTABLE
Display the sub categories of any selected or the current category in a table
First Set four variables prior to calling the object -->
%OUI%
%SET(g.FH_Catcode|%catcode%)% <!-- current category code or any category code you choose -->
%SET(g.FH_ColCount|4)% <!-- number of columns -->
%SET(g.FH_TbWidth|90)% <!-- table width in percent -->
%SET(g.FH_lineheight|1.7)% <!-- uses CSS to control vertical spacing -->
%OBJ({FH_CATTABLE})% <!-- This line calls the object that you created -->
%COMMENTEND%

%SET(g.count|0)%
%SET(g.FH_names|)%
%SET(g.FH_codes|)%
%COMMENT%<!-- Save the current category -->%COMMENTEND%
%ASSIGN(g.FHcurrentcat|Categories.d.id)%

%COMMENT%<!-- Get the category Names and Codes into arrays -->%COMMENTEND%
%FUNC(Category_Find_Code(g.FH_Catcode))%
%IF(g.OUIX_FuncReturn)%
%ASSIGN(g.FHCat|Categories.d.id)%
%FUNC(Category_FindFirst_Parent(g.FHCat))%
%WHILE(g.OUIX_FuncReturn)%
%IF(Categories.d.active)%
%ASSIGN(g.count|g.count + 1)%
%ASSIGN(g.FH_names[%VAR(g.count)%]|Categories.d.name)%
%ASSIGN(g.FH_codes[%VAR(g.count)%]|Categories.d.code)%
%IFEND%
%FUNC(Category_FindNext_Parent(g.FHCat))%
%WHILEEND%
%IFEND%
%ASSIGN(g.MyRowCount|%EXPR(g.count / g.FH_ColCount)% ROUND 0)%

%COMMENT%<!-- Display results -->%COMMENTEND%
%SET(g.c|0)%
%SET(g.idx|0)%
%IF(g.count)%
<hr>
<table cellSpacing="0" cellPadding="3" width="%VAR(g.FH_TbWidth)%%" border="0">
<tr>
%WHILE(g.c LT g.FH_ColCount)%
%SET(g.r|1)%
<td "nowrap width="%EXPR(%EXPR(100 / g.MyColCount)% ROUND 0)%%">
<p style='line-height: %VAR(g.FH_lineheight)%'>
%WHILE(g.r LE g.MyRowCount)%
%ASSIGN(g.idx|g.idx + 1)%
%IF(g.idx LE g.count)%
<a href='%VAR(g.sessionurl)%Screen=CTGY&Category_Code=%VAR(g.FH_codes[%VAR(g.idx)%])%'>
%VAR(g.FH_names[%VAR(g.idx)%])%</a><br>
%IFEND%
%ASSIGN(g.r|g.r + 1)%
%WHILEEND%
</p></td>
%ASSIGN(g.c|g.c + 1)%
%WHILEEND%
</tr>
</table>
<hr>
%ELSE%
Sub Categories for %VAR(g.FH_Catcode)% not found.<BR>
%IFEND%

%COMMENT%<!-- Restore category table pointers -->%COMMENTEND%
%IF(g.FHcurrentcat)%
%DOFUNC(g.OUIX_ok|g.Module_Library_DB|Customer_Category_Find_ID(BasketList.d.cust_id,g.FHcurrentcat))%
%DB(FIND|OUI_Categories|%VAR(g.FHcurrentcat)%|EXACT)%
%DB(FIND|OUI_Categories2|%VAR(g.FHcurrentcat)%|EXACT)%
%IFEND%

Displaying Parent Categories and all Products

Once again,  used as an Object, copy all of the code from %OUI% to the final <hr> to a new object called FH_CAT_PRODUCTS and update. Then copy just the portion between the %COMMENT% and %COMMENTEND% to the screen header or footer where you want to display this information remembering to add %OUI% to the first line. That's it, just view the appropriate page.

Example 7

%COMMENT%
<!-- Object name = FH_CAT_PRODUCTS
Display selected TOP LEVEL Parent categories and all of their products in table -->

%OBJ({FH_CAT_PRODUCTS})%
%COMMENTEND%

%SET(g.count|0)%
%SET(g.FH_names|)%
%SET(g.FH_codes|)%
%SET(g.FH_id|)%

<!-- Retreive parent categories -->
%FUNC(Category_FindFirst_Parent(0))%
%WHILE(g.OUIX_FuncReturn)%
  %IF(Categories.d.code IN '100200300400500600700800900')% <!-- only get specific categories 100, 200, 300: use your own list -->
    %ASSIGN(g.count|g.count + 1)%
    %ASSIGN(g.FH_names[%VAR(g.count)%]|Categories.d.name)%
    %ASSIGN(g.FH_codes[%VAR(g.count)%]|Categories.d.code)%
    %ASSIGN(g.FH_id[%VAR(g.count)%]|Categories.d.id)%
  %IFEND%
  %FUNC(Category_FindNext_Parent(0))%
%WHILEEND%

%SET(g.idx|)%
<div align="center">
<table border="0" width="250" cellpadding="0" bgcolor="#FFFFFF">
 <tr><td>
 %WHILE(g.idx LE g.count)%
  %ASSIGN(g.idx|g.idx + 1)%
  <b>%VAR(g.FH_names[%VAR(g.idx)%])%</b><br>
  %FUNC(Customer_Product_FindOffset_Category(BasketList.d.cust_id,0,g.FH_id[%VAR(g.idx)%]))%
  %WHILE(g.OUIX_FuncReturn)%
    &nbsp;&nbsp;%VAR(Products.d.code)% -- %VAR(Products.d.name)%<br>
    %FUNC(Customer_Product_FindNext_Category(BasketList.d.cust_id,0,g.FH_id[%VAR(g.idx)%]))%
  %WHILEEND%
 %WHILEEND%
 </td></tr>
</table>

 

Example 8

Display all products in a single category and count them.

%OUI%
%COMMENT%
<!-- Part 1 -- Copy the 2 lines below to call the object.
     Set g.FH_CatCod prior to calling the object.
     You can use current category token as shown or
     hardcode a category like SET(g.FH_CatCode|Shoes)
     on return, g.FH_Return = number of products found     
-->
%SET(g.FH_CatCode|%catcode%)%
%OBJ({FH_CATPRODUCTS})%
%COMMENTEND%


%COMMENT%
<!-- Part 2 -- Display the products in the category that is
     in the same availability Group as the customer.
     Save this as Object Name = FH_CATPRODUCTS
     on exit, g.FH_Return = number of products found
-->       
%COMMENTEND%

%SET(g.FH_Return|)%
%ASSIGN(g.MyCatCode|g.FH_CatCode)%
%FUNC(Category_Find_Code('%VAR(g.MyCatcode)%'))%
%IF(g.OUIX_FuncReturn)%
  <b>%VAR(Categories.d.name)%</b><br>
  %FUNC(Customer_Product_FindOffset_Category(BasketList.d.cust_id,0,Categories.d.id))%
  %WHILE(g.OUIX_FuncReturn)%    
   %ASSIGN(g.FH_Return|g.FH_Return + 1)%
     <!-- display all products -->   
     ProductsId = %VAR(Products.d.id)%, Code=%VAR(Products.d.code)%, Name=%VAR(Products.d.name)%, Link=%prodnameL%<br>
     %FUNC(Customer_Product_FindNext_Category(BasketList.d.cust_id,0,Categories.d.id))%
  %WHILEEND%
%ELSE%
  No products found in %VAR(g.FH_CatCode)%.<br>
%IFEND%


Hit Counter