Visit Our Home Page
 Explored. Designed. DeliveredSM

 
Creativyst Docs 
Use JavaScript for Dynamic Content Syndication
Twitter follow Button
(@NetlabLoligo)

  J
S
M
s
g
 
JSMsg Information
º Icon: JSMsg Button
º JSMsg Basics
º Free! Display RSS Feeds
º JSMsg Scrollers
º JSMsg Feeds
º JSMsg Details
º Concept Test Page




 




















 
 

Conventions:

Creativyst® JSMsg Webpage Display Convention

Use JavaScript syndication to display dynamic content on static or dynamic pages





Author: Dominic (John) Repici


Why Use JSMsg?
  • Webmaster can access your content with only client-side scripting
    JSMsg is a JavaScript syndication convention that has the advantage of enabling dynamic content to be displayed on web pages without need for server-side scripting. If you provide your feeds in JSMSg, websites with no ability to run server-side scripts can still display them. Tens of millions of people have a small amount of webspace through their ISP accounts for use as personal pages. Typically they are restricted to using only client-side scripting. JSMsg gives these people easy access to your dynamic content.

  • JSMsg is flexible and powerful
    Webmasters who use JSMsg files to display dynamic content on their pages have complete control over how that content is displayed and presented. JSMsg is also designed to work with display scripts written by others. So adding a news scroller, for example, is easy...

    Interactively changing the content that displays on that scroller is a bit more advanced, but all done on the browser-side...

    JSMsg Feed:

  • JSMsg is "REST", standard, and cross-browser
    Webmasters who use JSMsg files need not be concerned with cross browser issues because it works on any browser with JavaScript enabled.

  • JSMsg does not rely on proprietary software
    Webmasters and content providers do not have to be concerned with whether a visitor has installed the proper plug-ins or DLLs in order to see their content.

  • JSMsg reduces site bandwidth usage
    Of special interest to busy sources, a JSMsg feed can be a regularly updated static JavaScript file residing on the web server, so it works with existing Web caching schemes. It will be cached by browsers and intermediate cache mechanisms based on 304's and other criteria. While it may also be dynamically generated, it operates completely within the existing HTTP framework.




[top]
Overview

This paper documents a recommendation for the "JSMsg" file format. The JSMsg convention is a JavaScript that allows dynamically changing content to be displayed on webpages directly, or to be shared with outside scripts. The JSMsg convention places no restrictions on how its content is formatted by the webmaster or JavaScript display program.

JavaSript programs that display content in interesting and creative ways are perfect candidates to have JSMsg client capabilities added to them.

Such scripts will be enhanced by JSMsg support because they will no longer need to ask their users to change the static information to be displayed. For example, an information display script, when told to use a JSMsg file from a news service, will display the news information as it changes automatically, without needing intervention from the webmaster. Just as importantly, such a script will work with dynamic OR static content from ANY JSMsg file, not just the news service.

This JSMsg recommendation is a specification for a JavaScript file, functions, and naming conventions which may be included by outside webmasters in their pages, allowing display of their provided content in whatever style and layout the outside webmaster chooses. The convention is also useful as an easy means of content display at the source website.

The JSMsg convention shall be used in many of Creativyst's custom and COTS web page content applications to permit simple dynamic content display on web pages, and promote sharing that content with others. We openly share this convention with all who wish to use it and contribute to it. Our licensing terms will be free to personal and commercial projects, and detailed in the permissions section.





[top]
Design Philosophy & Goals

The design of the JSMsg convention will enable publication of dynamic content for presentation on outside web pages and within outside JavaScripts without restrictions on the format, layout, and style in which the syndicated content may be displayed.

A primary motivation in developing this convention is to allow the millions of webmasters with client-side-only scripting capabilities to share and use dynamic content on their Web pages.

We are documenting this convention and granting permission to others to use it un-altered because interface consistency benefits everyone.

Another design goal for this specification is to allow separate outside JavaScript programs to easily display any dynamic content from any JSMsg file without prior knowledge of the JSMsg file or the application that produced it.

In a word, the design philosophy for this project is Simplicity. The specification defined here shall be easy to understand, easy to implement, and easy to use. It must also be concisely and unambiguously defined, flexible, and enabling of applications beyond those that can be envisioned at the time of initial definition.





[top]
The JSMsg File

The file may simply be named "JSMsg.js", though it does not have to be. One useful convention is to name the file the same as the namespace used (see below). A JSMsg file shall contain JavaScript that is v1.1 compliant or lower. It SHOULD support the lowest version of JavaScript possible.

File names MAY be sequentially enumerated in cases where multiple JSMsg.js files require sequential but separate storage in the same location. For example "JSMsg01.js, JSMsg02.js", or "JSMsgMon.js, JSMsgTue.js", etc.





[top]
Namespaces

Namespaces are simply a means of labeling a group of function and variable names so they do not conflict with identical names used by outside processes. JSMsg requires namespaces so that content in JSMsg files from diverse sources may be used together on a single web page.

JSMsg shall employ a single JavaScript class as a simple namespace mechanism. All function names, globally scoped (otherwise) variable names, and array names within a JSMsg file, WILL be wrapped in a single class named with the namespace. This class name SHALL serve as the namespace, and SHOULD be kept relatively short to preserve typing and bandwidth. The class constructor function name itself SHALL be preceded with the namespace. The namespace name, being the class name, MUST be comprised of letters, numbers, or underscores and must not begin with a number.

Applications that produce JSMsg files (servers) SHOULD give users the ability to change the namespace. This is REQUIRED for applications where a single outside webpage may want to include content from multiple outside sources that may all use the same application. Such sources could be blogs, or news and announcement services. In these cases, the application user (the source) may be instructed to pick their own namespace based on their URL or a legally protected trademark or service mark.

In any case, server applications should include a default name space if the user does not configure one, or configures one improperly.





[top]
Function Calls

The following seven functions MUST be provided by the JSMsg file and encapsulated in the namespace/class
(... is used here in place of the namespace)
  • ...Msg(msgPart) or ...Msg(msgPart, Offset)
    Display a specified part of a message from a short list of messages kept in the JavaScript file. Select which message is displayed from the list at random. Accept an optional Offset parameter which, if used will specify an message number OFFSET from the random number.
  • ...MsgN(msgPart, Number)
    Display a specified part of a message from a short list of messages kept in the JavaScript file. Select which message is displayed by providing its numerical position in the list (starting with message number 0).
  • ...MsgDay(msgPart)
    Display a specified part of a message from a short list of messages kept in the JavaScript file. Select which message is displayed from the list based on what day of the month it is.
  • ...Get(msgPart) or ...Get(msgPart, Offset)
    Return a string containing a specified part of a message from a short list of messages kept in the JavaScript file. Select which message is displayed from the list at random. Accept an optional Offset parameter which, if used will specify an message number OFFSET from the random number.
  • ...GetN(msgPart, Number)
    Return a string containing a specified part of a message from a short list of messages kept in the JavaScript file. Select which message is displayed by providing its numerical position in the list (starting with message number 0).
  • ...GetDay(msgPart)
    Return a string containing a specified part of a message from a short list of messages kept in the javascript file. Select which message is displayed from the list based on what day of the month it is.
  • ...MetaMsg(msgCmd)
    Return 1 (one) if the message part named in msgCmd is supported by this implementation of JSMsg.js, otherwise return 0 (zero). This also takes some special message parts of its own relating to the entire file, These return information such as the copyright notice, the number of messages contained in the JSMsg file, etc. A complete list of these are shown below, at the bottom of the Message Parts section.




[top]
Usage Examples

A particular JSMsg.js file is use by including it in the header with a script tag and then calling the functions within the remainder of your html file. Normally only the display functions are required to display information in the body of an HTML document. More advanced presentation can be accomplished using the GET functions.

The JSMsg.js file used in this example will be the one generated by Creativyst® Quote Catcher which has a name space of cqc.

 
Note about standards: To save space and show usage on older pages, these examples are presented without mime types (HTML 3.2). Older embedded browsers and all modern browsers will handle these examples correctly.
 

First, include the script in the header

 <SCRIPT LANGUAGE="JAVASCRIPT"
     SRC="https://creativyst.com/Site/quotes/JSMsg.js">
</script>


Use ...Msg() to display parts of a message that change randomly each time you reload the page. To try it click here and then use your browser's refresh or reload button.

 <hr>
 <font FACE="Arial, sans-serif" SIZE="2">
 <i>
 <script LANGUAGE="JAVASCRIPT">
     cqc.Msg("Body");
 </SCRIPT>
 </i><br>
 &nbsp; &nbsp; --
 <script LANGUAGE="JAVASCRIPT">
     cqc.Msg("Attrib");
 </SCRIPT>
 </font>


    --

This will display the message "Body" followed by a double dash and the message "Attrib" ("Attribute") for a randomly chosen message. Each time you reload the page, a new message will be selected at random and displayed.




Use ...MsgDay() to display parts of a message that change once a day.

 <hr>
 <font FACE="Arial, sans-serif" SIZE="2">
 <i>
 <script LANGUAGE="JAVASCRIPT">
     cqc.MsgDay("Body");
 </SCRIPT>
 </i><br>
 &nbsp; &nbsp; --
 <script LANGUAGE="JAVASCRIPT">
     cqc.MsgDay("Attrib");
 </SCRIPT>
 </font>


    --

Unlike the example above that changes every time you re-load the page, this one will only change once a day.




Use ...MsgN() to display a part of the Nth message in the current short list.

 <hr>
 <font FACE="Arial, sans-serif" SIZE="2">
 <i>
 <script LANGUAGE="JAVASCRIPT">
     cqc.MsgN("Body", 10);
 </SCRIPT>
 </i><br>
 &nbsp; &nbsp; --
 <script LANGUAGE="JAVASCRIPT">
     cqc.MsgN("Attrib", 10);
 </SCRIPT>
 </font>


    --

This will display a message that only changes when the current list changes. That is to say, when you run the application that re-builds the JSMsg.js file. If there are less than 10 messages in the current list in the above example, it will wrap around and start counting up from the beginning again.

The ...MsgN() and ...GetN() function is very useful for displaying a formatted list of the top N messages in the list, as you might do for example, in a list of recent news stories.





Use ...Get..() functions in your JavaScript code to retrieve message strings in identical fashion to how the ...Msg..() functions display them.

 <hr>
 <font FACE="Arial, sans-serif" SIZE="2">
 <i>
 <script LANGUAGE="JAVASCRIPT">

     var msg;
     msg = "<B>1: </B>";
     msg += cqc.GetN( "Body", 0 );
     msg += "<BR>&nbsp;--";
     msg += cqc.GetN( "Attrib", 0 );
     msg += "<hr WIDTH=\"35%\">";
     msg += "<B>2: </B>";
     msg += cqc.GetN( "Body", 1 );
     msg += "<BR>&nbsp;--";
     msg += cqc.GetN( "Attrib", 1 );
     msg += "<hr WIDTH=\"35%\">";
     msg += "<B>3: </B>";
     msg += cqc.GetN( "Body", 2 );
     msg += "<BR>&nbsp;--";
     msg += cqc.GetN( "Attrib", 2 );
     msg += "<hr WIDTH=\"35%\">";

     document.write(msg);

 </SCRIPT>
 </font>

You may use ...Get..() functions as well as ...Msg..() functions from within your JavaScript scripts for nearly unlimited flexibility when displaying message parts.

Had the application constructed a JSMsg file containing a list of news stories in most-recent-first order, the above JavaScript would have shown the three most recent ones. Note also, that the message numbers start at zero.





The random functions; ...Msg() and ...Get() may optionally take an extra offset parameter to add to the random number produced. To try it click here and then use your browser's refresh or reload button.

 <hr>
 <font FACE="Arial, sans-serif" SIZE="2">
 <i>
 <script LANGUAGE="JAVASCRIPT">

     var msg;
     msg = "<B>1: </B>";
     msg += cqc.Get( "Body", 0 );
     msg += "<BR>&nbsp;--";
     msg += cqc.Get( "Attrib", 0 );
     msg += "<hr WIDTH=\"35%\">";
     msg += "<B>2: </B>";
     msg += cqc.Get( "Body", 1 );
     msg += "<BR>&nbsp;--";
     msg += cqc.Get( "Attrib", 1 );
     msg += "<hr WIDTH=\"35%\">";
     msg += "<B>3: </B>";
     msg += cqc.Get( "Body", 2 );
     msg += "<BR>&nbsp;--";
     msg += cqc.Get( "Attrib", 2 );
     msg += "<hr WIDTH=\"35%\">";

     document.write(msg);

 </SCRIPT>
 </font>

We've used the ...Get() function above, but it would have worked just the same way had we used the ...Msg() function to display the messages directly.

Here, instead of a single message that changes every time the page reloads, there are three messages changing every time the page reloads. You can add as many as you'd like to such a list (they will simply wrap around to the beginning if there aren't enough messages in the JSMsg file).





[top]
Message Parts

Message parts are labels used to access various parts of a message, such as the Title, Body, Description, etc.

Message parts are all optional but at least one message part MUST be supported and provided in the JSMsg.js file.

Message parts provided MUST be well documented for users.

The message parts provided MUST be one or more of the following. Case should be ignored (i.e. Title, is the same as title, is the same as TiTlE).

  • Type
    A field to hold the type of the message. Such as "news story", "article", "quote", etc. This is optional, but may be useful, especially in instances where multiple JSMsg.js files are employed. Though, it may not provide any information which is not already inferred from the name space. If used it SHOULD be terse.
  • Title
    The title or headline of the message. News stories, article names, and other content will have a natural title. Some messages, like quotes and customer testimonials would not need to provide this message part.
  • Desc / SubHead / Description
    Meta-data about the message. A description. SHOULD also be used for the lead-in (sub-heading) in news stories.
  • Body / Content
    The body of the message. While many messages will include this part, others, such as news headlines wont.
  • Attrib / Source / Attribute
    The source or person or group who is thought to have first made the statement or originated the content. the is NOT the author per se, though in the case of a quote it might be thought of as such.
  • Author
    The person who is known to have authored the content. Use Attrib for quotes. If there is no Author field but there is an Attrib field, this part SHOULD return that.
  • Cat / Subject / Category
    A category or subject field associated with the message content.
  • Number / Numb
    The numeric position of the current message in the JSMsg file's list of messages. This is helpful for the functions such as ...Get() and ...Msg() that return part of a randomly selected message. Less obvious though, it is also helpful for the ...GetN/MsgN() functions since they wrap around and start counting from the begining when the JSMsg file runs out of messages. To get a count of total message in the JSMsg file, call ...MetaMsg("MetaCount");.

  • DayN, Day2N
    The day of the month (1 to 31) associated with the story/message. Usually just for news and announcements. Use Day2N to add a leading zero when the day number is only one digit.
  • MonthN, Month2N
    The month number (1 to 12) associated with the story/message. Usually just for news and announcements. Use Month2N to add a leading zero when the month is only one digit.
  • Year2N, Year4N
    The two or four digit year. Also, YearN SHOULD produce a 4 digit year. That is it should be the same as Year4N
  • Hour2N, Minute2N, Time
    The hour and minute (if any) stamp for the entry. The Time message will return the raw time field in hhmmss format.
  • TZ
    The Time Zone indicator (if any) stamp for the entry. NOT YET IMPLEMENTED

  • Link
    A URL or URI associated with the message. This is especially helpful for linking news headlines to stories, or anywhere you want to link a terse message to greater detail.
  • LinkTitle
    A complete HTML hypertext, consisting of the Title surrounded by an HTML anchor tag to the Link (<A HREF=Link...>Title</A>). This part must attempt to provide content even when one or the other of the two components are not provided, i.e.:
    • A Link with no Title
      Make an anchor to the link with the link itself as the hypertext.
    • A Title with no Link
      Return the title without surrounding it in an anchor tag.
    • No Title, no Link
      Return nothing ("")
  • Thumb
    A URL or URI to a graphic content associated with the message. This is useful for providing a picture to go with a headline. The graphic should be kept small for efficient bandwidth usage, but since it's a URI only, the user has the option of sizing it to taste within his own JavaScript (so don't make it too small).
  • Alt
    The Alt text that should go behind a graphic. This may be a terse description or just a copy of the description.

  • Some labels are only used by the ...MetaMsg() function, these are (optional unless otherwise specified):
    • MetaCount
      The total number of messages in the JSMsg file. [REQUIRED]
    • MetaUpdateDate
      The last update date for the JSMsg file in raw form (yyyymmddHHMMSS).
    • MetaCopyright
      Copyright notice for the content of entire JSMsg file (channel)
    • MetaTitle
      The title of the JSMsg file's content (channel).
    • MetaLink
      URL to the owner of the JSMsg channel.
    • MetaLinkTitle
      Just like LinkTitle but for the entire channel, not a message.
    • MetaThumb
      A URI to a graphic for the channel
    • MetaDesc
      A Terse description for the channel
    If you pass a regular message part label to the ...MetaMsg() function it SHALL return a 1 if the message part is supported, or a 0 if the message part is not carried.

    Implementers may add their own meta message labels as long as they don't conflict with existing message part, or meta-message labels.



[top]
Arrays

Arrays like all variables in the file, are wrapped in the class to encapsulate them in the namespace.

Don't use these arrays directly in your JavaScript. Use the access functions to get at the information within them. In the future the names will likely be shortened to just their first letter or two. If you use the access functions such as Get...(), your scripts will continue to work fine no matter how the array names change.

Each array holds the content of a single supported message part for all the messages in the JSMsg.js file (the shortlist) in parallel with other arrays holding other message parts.

A specific Array SHOULD only be provided if its respective message part is supported/provided by the implementation producing the JSMsg.js file.

Each array included in the JSMsg file, if used, MUST be named with specific names defined in this specification. Here are the specified array names for version 1.0a of this convention, with "..." substituted in place of the name spaces.

  • ...Type[]
  • ...Title[]
  • ...Desc[]
  • ...Body[]
  • ...Attrib[]
  • ...Author[]
  • ...Cat[]

  • ...DateN[] (yyyymmddHHMMtz..)

  • ...Link[]
  • ...Thumb[]
  • ...Alt[]


[top]
JSMsg Version Token
For webmasters using the content, JSM file is normally meant to be run as a JavaScript. But aggregators will likely read and parse JSMsg files as plain text in order to glean information from them. Because the array names are free to change and new array names may be added, some mechanism must be provided to tell the aggregator what names to look for when gleaning the information from them. The version token serves this purpose.

The token is "JSMsgVersion:" followed immediately by the version number of this JSMsg recommendation document. The current version number is version "1.0a" without the quotes.

The token should be placed somewhere in the file. Preferably near the top. It generally must be placed in a comment so it doesn't conflict with the running of the code.

/* 
 * The following version token is 
 * required by aggregators
 * -------
 * JSMsgVersion:1.0a
 * -------
*/

Note that the only part that's really required for aggregators in the above example is:

JSMsgVersion:1.0a





[top]
JSMsg Buttons
There are two buttons defined for JSMsg links. You may download these for use directly from your site. Do not link directly to them here at Creativyst.com (do not inline).
  • JSMsg Button
    Generally, this should be linked directly to the static JSMsg JavaScript file for the feed. Use the button below to send visitors to an instruction page explaining how to use the feed.

  • JSMsg Button
    If you use JSMsg as the basis for an easy-to-use pre-made scroller (or other easy-to-use application) link this button to a page, or pop-up that gives cut-and-paste code or instructions. Clicking on this one will give you a working example of how this button can be used (in this case, some cut and paste code to include a fader with Creativyst.com's site announcments in any HTML page).

    This button may also be linked to a simple instruction page showing how to link to the JSMsg file and how to use it directly.



[top]
Example JSMsg.js Code


JSMsg.js  
 

 /*
  * Creativyst(R) Quote Catcher (v1.0d)
  *
  * :ATTRIBUTION NOTICE BEGINS
  *
  * The following JSMsg functions are:
  * 
  *    (C) Copyright 2002 - 2005, Creativyst, Inc.
  *               ALL RIGHTS RESERVED
  * 
  * For more information go to:
  *           https://Creativyst.com
  * or email:
  *           Support@Creativyst.com
  * 
  * Licensed under the Open Software License version 1.1
  *
  * END ATTRIBUTION NOTICE:
  *
  * These functions are free software; you can redistribute 
  * them and/or modify them under the terms of the Open 
  * Software License (OSL) version 1.1 as published by
  * the Open Source Initiative;
  * 
  * This program is distributed in the hope that it will 
  * be useful, but WITHOUT ANY WARRANTY; without even the 
  * implied warranty of MERCHANTABILITY or FITNESS FOR A 
  * PARTICULAR PURPOSE. See the Open Software License
  * version 1.1 for more details.
  * 
  * For the complete details of the Open Software License
  * please visit the Open Source Initiative website.
  *
  * -------
  * JSMsgVersion:1.0a
  * -------
  *
  *
  * -------------------------------------------
  * Parts of this code were automatically
  * generated and may contain copyrighted
  * content from other sources as well.
  * Such content may not be used without
  * first obtaining explicit permissions
  * from its source.
  *
  *
 */



function cqc_JSMsg() {

 this.ListPosition = 0;

 this.Type = Array([this.ShortListSize]);
 this.Desc = Array([this.ShortListSize]);
 this.Body = Array([this.ShortListSize]);
 this.Attrib = Array([this.ShortListSize]);

 this.ShortListSize = 12;
 this.BeenLoaded = 0;
 this.dispNumb;

 this.Msg = function(msgPart, msgOffset)
 {
    document.write( this.Get(msgPart, msgOffset) );
 }

 this.MsgDay = function(msgPart)
 {
    document.write( this.GetDay(msgPart) );
 }

 this.MsgN = function(msgPart, msgNumber)
 {
    document.write( this.GetN(msgPart, msgNumber) );
 }


 this.Get = function(msgPart, msgOffset)
 {
    if(!msgOffset) {
        msgOffset = 0;
    }
    if(!this.BeenLoaded) {
        this.BeenLoaded = 1;
        dispNumb = 
           this.getRandInt(this.ShortListSize);
    }
    return( this.GetN(msgPart, (dispNumb + msgOffset)) );
 }

 this.GetDay = function(msgPart)
 {
    var d = new Date();
    var x = d.getDate();
    return( this.GetN(msgPart, x) );
 }


 this.GetN = function(msgPart, msgNumber)
 {
    var myTmp;

    if(!msgPart) {
        msgPart = "Body";
    }
    if(!msgNumber) {
        msgNumber = 0;
    }

    if(msgNumber >= this.ShortListSize) {
        msgNumber = msgNumber % this.ShortListSize;
    }

    if(  this.ok(msgPart,"Type") ) {
        return(this.Type[msgNumber]);
    }
    if(  this.ok(msgPart,"Title") ) {
        return(this.Title[msgNumber]);
    }
    if(  this.ok(msgPart, "Desc Description Content") ) {
        return(this.Desc[msgNumber]);
    }
    if(  this.ok(msgPart,"Body") ) {
        return(this.Body[msgNumber]);
    }
    if(  this.ok(msgPart, "Attrib Attribute Source") ) {
        return(this.Attrib[msgNumber]);
    }
    if(  this.ok(msgPart, "Author") ) {
        if(!this.Author[msgNumber]) {
            return(this.Attrib[msgNumber]);
        }
        return(this.Author[msgNumber]);
    }

    if(  this.ok(msgPart,"DayN Day2N Day") ) {
        myTmp = this.DateN[msgNumber];
        if(myTmp.length) { 
          myTmp = myTmp.substr(6,2);
          if(  this.ok(msgPart,"Day2N") ) {
            return(myTmp);
          }
          if(myTmp.charAt(0) == "0") {
            return(myTmp.substr(1,1))
          }
          return(myTmp);
        }
    }
    if(  this.ok(msgPart, "MonthN Month2N") ) {
        myTmp = this.DateN[msgNumber];
        if(myTmp.length) {
          myTmp = myTmp.substr(4,2)
          if(  this.ok(msgPart,"Month2N") ) {
            return(myTmp);
          }
          if(myTmp.charAt(0) == "0") {
            return(myTmp.substr(1,1))
          }
          return(myTmp);
        }
    }
    if(  this.ok(msgPart, "Year2N Year4N YearN Year") ) {
        if(this.DateN[msgNumber].length) {
          if(  this.ok(msgPart,"Year4N") ) {
            return(this.DateN[msgNumber].substr(0,4));
          }
          return(this.DateN[msgNumber].substr(0,4));
        }
    }

    if(  this.ok(msgPart,"Link") ) {
        return(this.Link[msgNumber]);
    }
    if( this.ok(msgPart,"LinkTitle") ) {
        if(this.MetaMsg(msgPart,"Link") && this.MetaMsg(msgPart,"Title") ) {
          if( !this.Link[msgNumber] ) {
              return(this.Title[msgNumber]);
          }

          if( !this.Title[msgNumber] ) {
            this.Title[msgNumber] =  this.Link[msgNumber];              
          }
          myTmp = '<A TARGET="_blank" \n'; 
          myTmp = myTmp + 'HREF="' + this.Link[msgNumber] + '">\n';
          myTmp = myTmp + this.Title[msgNumber] + '</A>\n';

          return(myTmp);

        }
        if( this.MetaMsg(msgPart,"Title") ) {
          return(this.Title[msgNumber]);
        }
        if( this.MetaMsg(msgPart,"Link") ) {
          if( this.Link[msgNumber] ) {
            myTmp = "<A TARGET=\"_blank\" \n"; 
            myTmp = myTmp + "HREF=\"" + this.Link[msgNumber] + "\">\n";
            myTmp = myTmp + this.Link[msgNumber] + "</A>\n";
            return(myTmp);
          }
        }
        return("");
    }
    if( this.ok(msgPart,"Cat Category Subject") ) {
        return(this.Cat[msgNumber]);
    }
    if( this.ok(msgPart,"Thumb") ) {
        return(this.Thumb[msgNumber]);
    }
    if( this.ok(msgPart,"Alt") ) {
        return(this.Alt[msgNumber]);
    }

    return("");
 }




 this.getRandInt = function(RandSz)
 {
    var t, t2, t3;

    t = 0;
    while(t < .000001) {
        t = Math.random();
        t = Math.abs(t);
    }
    t2 = t * 1000000;
    t2 = Math.round(t2);
    t3 = t2 % RandSz;
    return(t3);
 }



 this.ok = function(a, b)
 {
    var t, t2;

    if(!this.is(a,b)) {
        return(0);
    }
    return(this.MetaMsg(a));
 }

 this.is = function(a, b)
 {
    var t, t2;

    t = a + " ";
    t2 = b + " ";
    t2 = t2.toUpperCase();
    t = t.toUpperCase();

    if(t2.indexOf(t) == -1) {
        return(0);
    }
    return(1);
 }


 this.MetaMsg = function(msgCmd)
 {
    if( this.is(msgCmd, "Type Body Attribute Attrib Source ") ) {
         return(1);

    }
    else if( this.is(msgCmd, "MetaCount") ) {
        return(12);
    }
    else {
        return(0);
    }
 }

}




cqc = new cqc_JSMsg();

/* how slow is the with statement */

with( cqc ) {
 Type[0] = "Quote";
 Body[0] = "A first rate soup is more creative than a second-rate...";
 Attrib[0] = "Abraham Maslow";

 Type[1] = "Quote";
 Body[1] = "The one who can not forgive destroys the bridge over wh...";
 Attrib[1] = "Unknown";

 Type[2] = "Quote";
 Body[2] = "People's hobbies are more their measure than are their j...";
 Attrib[2] = "Robert Byrne";

 Type[3] = "Quote";
 Body[3] = "Our Creator did not promise a world without evil, only t...";
 Attrib[3] = "911 survivor";

 Type[4] = "Quote";
 Body[4] = "If you have integrity, nothing else matters. If you don...";
 Attrib[4] = "Al Simpson, former U.S. Senator";

 Type[5] = "Quote";
 Body[5] = "Lying makes a problem part of the future, truth makes a...";
 Attrib[5] = "Rick Pitino";

 Type[6] = "Quote";
 Body[6] = "All truths are easy to understand once they are discov...";
 Attrib[6] = "Galileo Galilei";

 Type[7] = "Quote";
 Body[7] = "Science has achieved some wonderful things of cours...";
 Attrib[7] = "HGTTG";

 Type[8] = "Quote";
 Body[8] = "He who asks is a fool for five minutes, but he wh...";
 Attrib[8] = "Old Chinese saying";

 Type[9] = "Quote";
 Body[9] = "If the learner has not learned, the teacher h...";
 Attrib[9] = "Ernest Smith";

 Type[10] = "Quote";
 Body[10] = "Never fry bacon in the nude";
 Attrib[10] = "L.B.";

 Type[11] = "Quote";
 Body[11] = "The first step on the road to truth is to...";
 Attrib[11] = "Ancient Chinese saying";

 }





 




[top]
JSMsg Servers

If you write a content management application that includes syndication formats, adding support for JSMsg will make it easy for webmasters of every stripe to incorporate your application's content into their pages.

Q. I already support RSS and other syndication formats. What are the advantages of adding yet another one?

1. Unlike RSS and other syndication formats, JSMsg is simple, and displays without plugins on any browser with JavaScript. Webmasters of all levels of expertise, from XHTML gurus, to AOL script runners will be able to easily incorporate content from your JSMsg file into their sites.

2. While JSMsg works fine as a stand-alone content format, it is also designed to make content available to display scripts. Any fancy display script that supports JSMsg will automatically be able to work with your application's content.

3. Webmasters will not have to insist their users run a single browser type. No data islands or DOM "extensions". Just simple, plain, well understood and supported JavaScript with a small set of consistent and openly shared access methods.

Coding support? This paper is just gearing up. I'm currently using the JSMsg Server Demo page to debug some Perl functions. Once they're decent (halfway stable) I'll make them available under one of the many public licenses. They are very deliberately written and so should be easy to port to PHP.

Applications that produce JSMsg files are called JSMsg Servers. If you've added JSMsg server support to your application, please let me know so I can list your application, a link to your site, and your application's default JSMsg namespace here.

  • Demo: RSS feed to JSMsg Converter (free) (demo)
    A free demonstration program that converts the XML of your favorite news feed (RSS) into a csvMsg file. The JSMsg file is returned in an output area that you can cut and paste. The page the conversion form is on also displays the content from your JSMsg file in a variety of formats.
  • Creativyst Quote Catcher (cqc)
    Produces a JSMsg file with a short list of quotes for random display on static and dynamic web pages. Will maintain a variety of different message types besides quotes, such as tip of the day, joke of the day, customer testimonials, etc.
  • Creativyst News entry Widget (cnw)
    [coming soon] - Creativyst's News Entry Widget will soon include a JSMsg server.
  • Creativyst CSV to JSMsg Converter (cvs)
    [coming soon] - Creativyst's general namespace will be used in a developer tool available to be used freely at creativyst.com. The converter will take comma separated value (CSV) files from a developer's spreadsheet, and convert them into JSMsg files for web page usage.
  • Your Application Here
    Help make content sharing and display easier by supporting the JSMsg format in your applications. let me know and I'll list it here along with a description and default namespace.




[top]
JSMsg Clients

A JSMsg Client is a JavaScript program that, given only a string with a namespace, can display the content from any JSMsg.js file listed above it.

JavaSript programs that display content in interesting and creative ways are perfect candidates to have JSMsg client capabilities added to them.

The following four functions may be pasted into display scripts directly to allow easy access to any JSMsg.js files included above them on the HTML page. These work just like the .Get() functions in JSMsg files but take an added namespace parameter so the calling script may specify which namespace's content to display.


/*
 * JSMsg Client Interface Code
 *
 * (C) Copyright 2003-2005 Creativyst, Inc.
 *             creatvisyt.com
 *          ALL RIGHTS RESERVED
 *
 * Developers may use these functions
 * freely in their code, modified or
 * unmodified as long as this entire
 * comment is included and intact.
 *
*/

/*
 * These work the same as their JSMsg Counterparts
 * except they take an extra namespace parameter
 * as their first parameter.
 *
 * They will return the message part just as if
 * the function of the same name was called
 * with the namespace prefixed.
 *
*/

function jsmGetN(ns,MsgPart,number)
{
    var rv, c, er;

    c = "rv = " + ns + ".GetN('" + MsgPart + "'," + number + ");";
    er = eval(c);

    return(rv);
}


function jsmGet(ns,MsgPart,offset)
{
    var rv, c, er;

    c = "rv = " + ns + ".Get('" + MsgPart + "'," + offset + ");";
    er = eval(c);

    return(rv);
}


function jsmGetDay(ns,MsgPart)
{
    var rv, c, er;

    c = "rv = " + ns + ".GetDay('" + MsgPart + "');";
    er = eval(c);

    return(rv);
}


function jsmMetaMsg(ns,MsgPart)
{
    var rv, c, er;

    c = "rv = " + ns + ".MetaMsg('" + MsgPart + "');";
    er = eval(c);

    return(rv);
}



For a simple working example of how these functions may be used within your JavaScript see example #5 in the concept test page.

The following function interfaces JSMsg files to a display script's message array. If your script uses structures or classes, you will only need to adjust this function a little to make it work.


/*
 * JSMsg Client Interface Code
 *
 * (C) Copyright 2003 - 2005 Creativyst, Inc.
 *            creatvisyt.com
 *         ALL RIGHTS RESERVED
 *
 * Developers may use the following
 * JSMsg client interface functions
 * freely in their code, modified or
 * unmodified as long as this entire
 * comment is included and intact.
 *
*/

/*
 * JSMsgIf() (Array Interface function):
 *
 *  This function takes an array of messages
 *  to display.  If there are no JSMsg
 *  namespaces defined it will return
 *  the array unchanged.  Otherwise
 *  it will append the entries from the
 *  JSMsg feeds on to whatever is already
 *  in the array.
 *
 *  msgAr   Message array to be appended
 *          with messages from the feeds
 *          (for use by the scroller app).
 *
 *  myNs    String containing namespaces for
 *          each JSMsg feed you want to display
 *          messages from.  Leave "" to simply
 *          return your array without additions.
 *
 *  mySeq   Messages from multiple JSMsg files
 *          are normally interleaved. Set this
 *          to 1 to present each JSMsg file
 *          end-to-end.
 *
 *  Example call:
 *
 *      JSMsgNs = "ciq cvs"; // namespaces setting var
 *      JSMsgSeq = 0;        // sequence setting var    
 *      myArray = JSMsgIf(myArray,JSMsgNs,JSMsgSeq);
 *
*/
function JSMsgIf(msgAr, myNs, mySeq)
{
    var TotNS,LongestNS;
    var NSAr = new Array();
    var i,j,k,o;

    if(!myNs) {
        myNs = "";
    }
    if(!mySeq) {
        mySeq = 0;
    }

    /* get the offset
    */
    o = msgAr.length;

    if(myNs) {
        NSAr = myNs.split(" ");
        TotNS = NSAr.length;

        /* Get longest length
        */
        LongestNS = 0;
        j = 0;
        for(i = 0;i < TotNS;i++) {
            j = jsmMetaMsg(NSAr[i], "MetaCount");
            if(j > LongestNS) {
                LongestNS = j;
            }
        }
        if(!j) {
            return(msgAr);
        }

        /* Interleave for now,
         * eventually do Seq
        */
        k = o; // offset
        if(mySeq) {
            for(j = 0;j < TotNS;j++) {
                for(i = 0;i < LongestNS;i++) {
                    if(jsmMetaMsg(NSAr[j],"MetaCount") <= i) {
                        continue;
                    }
                    msgAr[k] = jsmGetN(NSAr[j], "LinkTitle", i);
                    if(!msgAr[k]) { // no linktitle, use body
                        msgAr[k] = jsmGetN(NSAr[j], "Body", i);
                        msgAr[k] += "<br>   -";
                        t = jsmGetN(NSAr[j], "Attrib",i);
                        if(t.length > 17) {
                            t = t.substr(0,14);
                            t += "...";
                        }
                        msgAr[k] += t;
                    }
                    k++;
                }
            }
        }
        else {
            for(j = 0;j < LongestNS;j++) {
                for(i = 0;i < TotNS;i++) {
                    if(jsmMetaMsg(NSAr[i],"MetaCount") <= j) {
                        continue;
                    }
                    msgAr[k] = jsmGetN(NSAr[i], "LinkTitle", j);
                    if(!msgAr[k]) { // no linktitle, use body
                        msgAr[k] = jsmGetN(NSAr[i], "Body", j);
                        msgAr[k] += "<br>   -";
                        t = jsmGetN(NSAr[i], "Attrib",j);
                        if(t.length > 17) {
                            t = t.substr(0,14);
                            t += "...";
                        }
                        msgAr[k] += t;
                    }
                    k++;
                }
            }
        }
    }

    return(msgAr);
}



Content display scripts are enhanced by JSMsg support because they no longer have to ask users to configure them with static messages whenever fresh information display is desired. By supporting the JSMsg convention, these scripts can simply ask their users to place them under a JSMsg file containing the content they want the script to display, along with a namespace string (e.g. "cqc"). The author of the display script does not have to know anything about the content in the JSMsg file. If the JSMsg file is from an outside service like a news headline service, or a quote of the day service, the display script will display that content automatically, as it changes, without requiring the user to change the information in the display script.

This is a primary goal of the JSMsg specification; to allow separate JavaScript programs to display any JSMsg file's content, without prior knowledge of the application that produced that JSMsg file.

For those who write JavaScripts that display information in interesting ways, it would be helpful to have a simple set of functions that they can bolt on to their scripts so the information can come from a JSMsg file. I'll try and write such a set of functions and make them available from here when they're done.

If you've written interesting display JavaScripts for which you'd like to add JSMsg support please let me know. so I can list it and a link to your site here.





[top]
Aggregating JSMsg Files

The JSMsg specification allows for a simple script to be written to aggregate the content in other JSMsg.js files included on the page. For functions to help do this, see the section titled JSMsg Client Functions above.

Aggregating services will likely passively parse the content arrays directly. They should take care to discern between the array names specified here and future array names which will be one or two characters long to preserve WAN bandwidth [TBD].




[top]
Permissions

This recommendation is © Copyright, Creativyst, Inc. 2004-2007 ALL RIGHTS RESERVED.

Permission to use this unmodified convention as a component in the designs of commercial or personal products and software offerings is hereby granted.

Links to this paper are always welcome.

However, you may not copy, modify, or distribute this work without first obtaining express written permission from Creativyst, Inc. Those wishing to obtain permission to distribute this paper or derivatives in any form should contact Creativyst.

Permissions printed over code, DTD, and schema files are supported as our permission statement for those constructs.




Want to Contribute?

If you're interested in improving or promoting this convention please contact me. If used, your code and contributions will be attributed to you with a link to your site.
 



© Copyright 2003-2007 Creativyst, Inc.
ALL RIGHTS RESERVED

Written by Dominic Repici


With contributions by:
-