Building a CMS - Constructing the Main Heading Markup
(Page 5 of 5 )
this.tagBegin = "<div class=\"mainHead\">\n<h1>";
this.tagEnd = "</h1>\n</div>\n";
this.headText = txt;
this.headAssemble = headAssemble;
this.markup = "";
if(this.headText != "" || this.headText != " ")
this.markup = tagBegin + headText + tagEnd;
By constructing an Object to handle each document feature in this way, we can make an instance of it, fill it with values, use its assemble method to validate its data, and assemble the markup in a string to be put together with the other features at the end of the script. The method attached to this object "headAssemble()" will return false if the main heading field was left blank. You can then handle that error in whatever way you wish. If you construct a custom error object you could store the errors for each field within that object and then alert the user which errors had been found.
If there is an additional company description (About Company X) to be added to the standard company description, or if the standard description is to be altered for this particular release, then we will need to provide a mechanism for doing that. We have an "Add Description" button, a "Delete Description" button, a "Restore Default" button and a select menu that shows all the descriptions that are currently stored. The description sub head and text fields display the default company description as their default value. The default company description is also stored in a description object which is created if any descriptions are added. This way the default can be put in the document automatically if there are no changes to be made. The form markup for this section is below.
<input type="button" value="Add Company"
<input type="button" value="Delete Company"
<input type="button" value="Restore Default"
<option value="Company X">Company X</option>
<span class="title">Company Description Subheading</span><br>
<input type="text" name="cdsubhead" size="85" value="About Company X"><br>
<span class="title">Company Description Text</span><br>
<textarea name="dtext" rows="18" cols="65">
Company X is a multinational manufacturer of widgets for blah blah blah blah.......
First we will look at the description object. As with the main header object declare a global variable outside all functions. This will hold a description object when the user deletes or adds a new description. Setting it to null at first will allow you to check if editing has taken place. If not we just use the default values of the fields in the form.
var descriptionObj = null;
//our object constructor
//set a default heading and description
this.descHead = "About Company X";
this.descText = "Company X is a multinational manufacturer of " +
"widgets for blah blah blah blah.......";
//arrays to hold the defaults along with any additions
this.desc_Arr = new Array();
this.head_Arr = new Array();
this.head_Arr = descHead;
this.desc_Arr = descText;
//our object methods
this.addC = addC;
this.deleteC = deleteC;
this.restoreDefault = restoreDefault;
this.tagAssemble = tagAssemble;
When the user clicks the "Add Company" button we first check to see if we already have a description object. If so we simply call the addC method of that object passing it object references for our form controls and add what is currently in the form fields as a new description. If this is the first edit, then we create the object first and then call addC.
One thing to note about the way this script gets object references is that the Safari Web browser does not support the getElementByName() method of the document object. If you want this to work in Safari and you're used to using the "name" attribute for form controls, you have two options. You can use the technique I have shown here and pass objects to functions by using this.form.tagname, where tagname is the name attribute value of the form control you are trying to work with, or give the appropriate tags Id values as well and use getElementById() to get ahold of your tag object.
descriptionObj = new description();
if(head.value != "" && text.value != "")//if our values are not blank
var optobj = document.createElement("option");//create an option element;
optobj.value = sel.options.length;//set the proper attributes;
optobj.text = head.value;
sel.appendChild(optobj);//add it to the select menu;
//set the menu selection to the new company for feedback to the user
sel.selectedIndex = sel.options.length - 1; var hIndx = this.head_Arr.length;
var tIndx = this.desc_Arr.length;
//store our new company header and description for later retrieval
this.head_Arr[hIndx] = head.value;
this.desc_Arr[tIndx] = text.value;
this.markup = "";
else//Prompt the user to fill in all information
alert("Please Enter Both a Heading and Text description");
The "Delete Description" button will delete the description that is currently selected in the select menu. Again we first check to see if we have edited anything before and then proceed accordingly.
function deleteDesc(sel)//we only need a reference to our select menu this time
descriptionObj = new description();
//our deleteC method
var indx = sel.selectedIndex;//find out which option is selected
//erase our stored description data
this.head_Arr[indx] = "";
this.desc_Arr[indx] = "";
The "Restore Default" button will restore the default company description and delete all others. We check for an object as before and then call the method
//the restoreDefault method
function restoreDefault(sel)//again we only need a reference to our select menu
//remove all option elements from the menu to start over
for(var i = 0;i <= sel.options.length;i++)
var optobj = document.createElement("option");//create a new option element
optobj.value = 0;
optobj.text = this.descHead;//fill it with our default heading
sel.appendChild(optobj);//add it to our menu
//reset our arrays with the defaults
this.head_Arr.length = 1;
this.head_Arr = this.descHead;
this.desc_Arr.length = 1;
this.desc_Arr = this.descText;/**/
Our description object would also have a tag assemble method for constructing the final markup. If no editing took place then the object is created while the page markup is being assembled using the default values. Storing each object that represents a feature of our press release in a global variable outside any functions comes in handy when it is time to assemble the markup.
//Our globals that hold each object, for each feature of our press release
var mainHead = null;
var dateTime = null;
var subHead = null;
var descriptionObj = null;
var contactPerson = null;
var email = null;
var webAddr = null;
//If you already have a main heading object validate and re-assemble the tag.
//important to check if the user has closed a generated document and decided to
//edit some more without clearing everything.
else//If you don't already have a main heading object
//get the text field for the main heading
var mainHeadField = document.getElementById(mainHd);
//make a new main heading object and feed it the field value
mainHead = new headingMain(mainHeadField.value);
//validate your input and assemble the tag
//follow this with all your feature values and objects
//Then the code to put all the tags together into a document.
After each feature has been assembled, the page markup would be assembled and written into a new document. To do this you first assemble your markup in a variable, then use the window object's open() method to bring up a new window. This method takes three arguments. The first argument is a URL, which in this case is not needed so it should be set to a blank string (""). The second is the window name, which can be anything in this case. The third is a comma delimited list of window features.
var newWindow = window.open("","preview","resizeable,statusbar,width=500");
By storing the result of this method in a varaible, we can point to the window that was created and work with it. Once we have our markup we can fill what would be a blank document with that markup. For this we use the document's write() method and close() method. The close method is important in the same way that closing a stream to an open file once you are done with it is important in other languages.
//Store a string of the markup before the content
//You may add as much markup in here that user doesn't need to work with as is needed
var docStart = "<html>\n<head>\n<title>" + mainHead.headText + "</title>\n" +
"<link href=\"http://www.companyX.com/css/:press_release.css\" rel=\"stylesheet\"" + "type=\"text/css\">\n</head>\n<body>";
//Store a string of the markup after the content.
var docEnd = "</body></html>";
//Now assemble your the content from the markup property of each object, beginning and end
var documentString = docStart + mainHead.markup + dateTime.markup + subHead.markup +
companyDescription.markup + contactPerson.markup + email.markup + webAddr + docEnd;
//pheew! long string but we have our source lets open the window.
var newRelease = window.open("","release","resizeable");
//Now fill the document in newRelease
The new window will now display the new generated content for preview. Notice that we are not using a relative path for the stylesheet. The style sheet is needed if the user is going to be able to preview the document as it will look on the site. When the document is posted this path can be altered if needed. The user can then save the document as an HTML file and attach it to email or put it in a drop box directory for inclusion in the website.
A system like this can be expanded upon to include a way to generate links, bold text or other styling within the text areas on a form. The document could also be submitted to the server for further processing or posting. We could even skip most of the client side code all together and use server side code to generate an XML document of the form input that could later be transformed into HTML (or markup specially designed for a screen reader) by using XSLT. Other things that can be added are the ability to edit current documents (in-browser editing), access control and managing dynamic resources such as databases and printable reports of work done and email notification.
When a custom solution to fit the publishing environment is needed, be prepared to supply the client with the tools necessary to make their website a success.
| DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware. |