2. Modifications and Additions
The two improvements are:
- The code that set the "user-agent" header was removed from the master_page.js script because neither Chrome nor Safari would accept it.
- A JSON menu source file was incorporated (implemented from code provided by a reader).
2.1. Using JSON to pass Parameters
In order to accomodate the use of JSON to define the contents of a menu, it was necessary to add a component to the build_page JSON parameter.
Therefore the revised recognized master page JSON name/value pairs are:
Name | Value | Type |
header_desired | Is a header desired? | Boolean |
header_contents_url | URL of the header text | URL |
logo_url | URL of the site logo | URL |
home_url | Target URL if logo is clicked | URL |
background_image_desired | Is a background image desired? | Boolean |
background_image_url | URL of the background image | URL |
heading | Heading text | String |
heading_color | Color of Heading text (i.e., one of the HTML Color Names [^]) | String |
subheading | Subheading text | String |
subheading_color | Color of Subheading text (i.e., one of the HTML Color Names [^]) | String |
dot_desired | Is a colored dot desired? | Boolean |
dot_target_url | Target URL if the dot is clicked | URL |
dot_title | Title displayed when mouse hovers over the dot | String |
dot_image_url | Image URL to be displayed as the dot | URL |
printing_desired | Is printing the page permitted? | Boolean |
text_sizing_desired | Is text sizing to be provided? | Boolean |
text_sizing_tags | HTML tags that will participate in text sizing (e.g., p, span, td, th, etc.) | String |
constant_contents_url | URL of the JavaScript constants | URL |
menu_desired | Is a menu to be created? | Boolean |
menu_contents_url | URL of the menu text | URL |
menu_data_is_json | if true, contents of the file specified by menu_contents_url is in JSON format; if omitted or set to false the contents of the file specified by menu_contents_url is not in JSON format | Boolean |
footer_desired | Is a footer desired? | Boolean |
footer_contents_url | URL of the footer text | URL |
left_footer_desired | Is a left footer desired? | Boolean |
left_footer_contents | Contents of the left footer | String |
center_footer_desired | Is a center footer desired? | Boolean |
privacy_policy_url | URL of the privacy policy | URL |
contact_webmaster_url | URL of the contact webmaster web page | URL |
right_footer_desired | Is a right footer desired? | Boolean |
right_footer_contents | Contents of the right footer | String |
debug_json | Is debug alert displaying JSON contents desired? | Boolean |
The menu_data_is_json component has been added to allow the menu_contents_url file to contain a JSON structure. This concept is more fully discussed below.
3. Creating a Master Page
3.1. MasterPages Template
As I have repeatedly suggested, creating new webpages can be more easily accomplished if a template is used. The following code is a template based upon the example website.
<!DOCTYPE html >
<html lang="en">
<head>
<title></title>
<meta http-equiv="Content-type"
content="text/html; charset=UTF-8" />
<meta name="viewport"
content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet"
href="https://www.w3schools.com/w3css/4/w3.css" />
<link rel="stylesheet"
href="./CSS/master_page.css" />
<!-- place additional scripts here (e.g., Google Analytics, etc.) -->
<script>
var PAGE_COMPONENTS =
{
"header_desired":true,
"header_contents_url":"URL_FOR_HEADER_CONTENTS",
"logo_url":"WEBSITE_LOGO_IMAGE",
"home_url":"WEBSITE_HOME_URL",
"background_image_desired":TRUE_OR_FALSE,
"background_image_url":"BACKGROUND_IMAGE",
"heading":"WEBSITE_NAME",
"heading_color":"HTML_COLOR_NAME",
"subheading":"WEBSITE_PAGE_NAME",
"subheading_color":"HTML_COLOR_NAME",
"dot_desired":TRUE_OR_FALSE,
"dot_image_url":"DOT_IMAGE_URL",
"dot_title":"DOT_TITLE",
"dot_target_url":"DOT_REDIRECT_URL",
"printing_desired":TRUE_OR_FALSE,
"text_sizing_desired":TRUE_OR_FALSE,
"text_sizing_tags":"HTML_TAGS_FOR_TEXT_RESIZING",
"constant_contents_url":"URL_FOR_JSON_CONSTANTS",
"menu_desired":TRUE_OR_FALSE,
"menu_contents_url":"URL_FOR_MENU_CONTENTS",
"menu_data_is_json":TRUE_OR_FALSE,
"footer_desired":TRUE_OR_FALSE,
"footer_contents_url":"URL_FOR_FOOTER_CONTENTS",
"left_footer_desired":TRUE_OR_FALSE,
"left_footer_contents":"",
"center_footer_desired":TRUE_OR_FALSE, ,
"privacy_policy_url":"URL_FOR_PRIVACY_CONTENTS",
"contact_webmaster_url":"URL_FOR_CONTACT_ME_CONTENTS",
"right_footer_desired":TRUE_OR_FALSE,
"right_footer_contents":"",
"debug_json":TRUE_OR_FALSE,
};
</script>
</head>
<body onload="MasterPage.build_page ( PAGE_COMPONENTS );">
<div id="header">
</div>
<div id="contents">
</div>
<div id="footer">
</div>
<script src="./Scripts/master_page.js"></script>
</body>
</html>
The capitalized text should be replaced by desired values.
Note that if, say, dot_desired is set false, none of the other PAGE_COMPONENTS dot-associated components (i.e., dot_image_url, dot_title, or dot_target_url) need be suplied. If dot_desired is set false, all of those components are ignored (whether present or not).
3.2. Header Menu
The header menu source file may be supplied in either text or JSON format.The text file format was discussed in the earlier version of this article. This errata will only address the JSON format.
3.2.1. JSON Menu Source File
The menu source file can be composed of a JSON object. For example:
{
"menus":
[
{
"label": "Home",
"href": "index.html",
"submenus": []
},
{
"label": "Link1",
"href": "link_1.html",
"submenus": []
},
{
"label": "Other Links",
"href": "",
"submenus":
[
{
"label": "Link2",
"href": "link_2.html"
},
{
"label": "Link3",
"href": "link_3.html"
},
{
"label": "Link4",
"href": "link_4.html"
}
]
}
]
}
To allow a JSON or a text file to be the source of the menu, the build_menu method required modification.
function build_menu ( components )
{
var file_name = components.menu_contents_url;
var menu_item_separator = ',';
var menu_line_height = 0.9;
var menu_metadata = null;
var start_menu_line_comment = '/';
if ( !file_name )
{
return ( null );
}
if ( components.constant_contents_url )
{
retrieve_menu_constants ( components,
menu_line_height,
start_menu_line_comment,
menu_item_separator );
}
menu_metadata = read_contents ( components.menu_contents_url );
if ( !menu_metadata )
{
return ( null );
}
if ( components.menu_data_is_json )
{
return ( build_menu_from_json ( menu_metadata,
menu_line_height,
start_menu_line_comment,
menu_item_separator ) );
}
else
{
return ( build_menu_from_text ( menu_metadata,
menu_line_height,
start_menu_line_comment,
menu_item_separator ) );
}
}
Converting this structure into a menu is the responsibility of the build_menu_from_json function.
function build_menu_from_json ( menu_metadata,
menu_line_height,
start_menu_line_comment,
menu_item_separator )
{
var i = 0;
var json_menu = null;
var menu_contents = null;
var menu_item = '';
var menus_list = null;
try
{
json_menu = JSON.parse ( menu_metadata );
}
catch ( error )
{
alert ( "In build_menu_from_json: " + error );
return ( null );
}
menus_list = json_menu.menus;
menu_contents =
" <div class='w3-bar'\n" +
" style='vertical-align:top; \n" +
" line-height:" + menu_line_height.toString ( ) +
";'>\n";
while ( i < menus_list.length )
{
var menu = menus_list [ i ];
if ( menu.submenus.length === 0 )
{
menu_item =
" <a href='" + menu.href + "' \n" +
" class='w3-bar-item w3-button'>" + menu.label + "</a>\n";
menu_contents += menu_item;
i++;
}
else
{
menu_item =
" <div class='w3-dropdown-hover'>\n" +
" <button class='w3-button'>" + menu.label +
"▼</button>\n" +
" <div class='w3-dropdown-content w3-bar-block w3-card-4'>\n";
menu_contents += menu_item;
for ( var j = 0; ( j < menu.submenus.length ); j++ )
{
var submenu = menu.submenus [ j ];
i++;
menu_item =
" <a href='" + submenu.href + "'\n" +
" class='w3-bar-item w3-button'>" + submenu.label +
"</a>\n";
menu_contents += menu_item;
}
menu_contents += " </div>\n";
i++;
}
}
menu_contents += " </div>";
return ( menu_contents );
}
I wish to acknowledge Walter Mariano Dávalos who provided the concept and this code.
4. Browser Compatibility
Safari does not appear to properly support the w3-display-right class. Output appears below the centerline of the w3-display-container.
The testing procedure is:
- Open the browser for which testing is to occur.
- Place the address of the Step 2 index.html file into the browser's address bar.
Using this procedure, each of the browsers, whose image is depicted above, was tested.
5. Acknowledgements
I would like to thank the following Code Project members for their corrections and suggestions:
Member | Corrections/Suggestions | Resolution |
Terry D. Woody | Reported that neither Chrome nor Safari would allow allow setting the "user-agent" header. | Removed the unnecessary setting of the "user-agent" header. |
Walter Mariano Dávalos | Suggested that the menu source file contents be JSON; provided the menu construction software that has been incorporated into master_page.js. | Incorporated the JSON menu source into the project. |
6. References
7. Conclusion
I hope that this errata has improved the method of developing master pages. Some significant improvements were made that I hope will make the process more useful.
8. Development Environment
MasterPages was developed in the following environment:
Microsoft Windows 7 Professional SP 1 |
Microsoft Visual Studio 2008 Professional SP1 |
Microsoft Visual C# 2008 |
Microsoft .Net Framework Version 3.5 SP1 |
Microsoft Office PowerPoint 2003 |
9. Download
The download contains:
- browser_compatibility.png
- master_page.js
- MasterPages.html
- MasterPages.TOC.html
- return_to_toc.png
Of these, only master_page.js is of particular interest.
10. History
06/28/2018 | Original article |
07/04/2018 | Revised formatting and typos |
07/04/2018 | Repaired error that caused Chrome and Safari to fail |
10/02/2019 | Added a JSON menu source file; removed jss to js file conversion |