Complete dhtml windowing-system in 600 lines (24kb)*

Discussion in 'Javascript' started by darwinist, Aug 1, 2006.

  1. darwinist

    darwinist Guest

    1 Works in a browser as customisable web-interface or,
    2 Use with apache to make window-based, dhtml-apps
    3 Rename/retitle open windows
    4 Arbitrary virtual desktop size with easy navigation (default
    5 Free as in freedom, and free as in free-beer (beer not included).
    6 All in one html/js file at
    7 You can copy and paste this post into a new .html file and start your
    8 Tested on firefox 1.5 and ie 6
    9 Left and right window padding too fat on ie. Very hard. Please help.
    *(With comments, whitespace, and api reference)

    Please copy or contribute:

    <!-- dhtml windowing-system-->
    <title>Web Windows</title>

    <body style='font-family:arial;'>

    <!-- Scripts to control the desktop: -->
    var CurrentObject =""; // Which object is being dragged (moved)
    right now.
    var AreMoving = false; // Is an object being dragged.
    var AreSizing = false; // Are we sizing any objects right now
    var SizingType = ""; // Which kind of sizing
    var StartMouseX = 0; // Mouse x when dragging started
    var StartMouseY = 0; // Mouse y when dragging started
    var StartObjectX = 0; // element x when dragging started
    var StartObjectY = 0; // element y when dragging started
    var StartObjectHeight = 0; // element y when dragging started
    var StartObjectWidth = 0; // element y when dragging started
    var Windows = 0; // total windows created
    var WindowsNow = 0; // Number of windows currently open
    var TopZIndex = 0; // TopMostWindow

    // Show debug information (9 keystrokes shorter than window.alert
    debugon=true; // controllable with debugon flag)
    function msg(text){if (debugon) window.alert(text);}

    // Strip the "px" from the style values of gui objects, if it's
    there, and return as number.
    function pxVal(val) {
    return val.substring(val.length-2)=="px" ?
    val.substring(0, val.length-2) *1
    : val *1;

    // Create a new object and give it an id
    function $make(type, id) {el =
    document.createElement(type);;return el;}
    function $del(id){$(id).parentNode.removeChild($(id));} // remove an
    item from html document.
    function $text(text) { return document.createTextNode(text);} //
    Make a text node

    // Make an input with type, name and optional value and id (which is
    the same as name if not specified
    // or not used if set to false
    function $input(type, name, value, id)
    if (id == undefined) id = name; if (id == false) id = undefined;
    el = $make("input", id); name; el.type= type; el.value=
    return el;

    // return a default value if the desired parameter is undefined;
    otherwise the parameter.
    // Only works from inside functions
    function IfNo(targetvar, defaultval)
    {return targetvar == undefined ? defaultval : targetvar; }

    // Get an object by id (22 keystrokes shorter than
    function $(id){return document.getElementById(id);}

    // Get some values quicker; read-only.
    function Width(id){return pxVal($(id).style.width);}
    function Height(id){return pxVal($(id).style.height);}
    function Top(id){return pxVal($(id);}
    function Left(id){return pxVal($(id).style.left);}

    // Write these values more quickly:
    function WidthIs(id, newwidth){$(id).style.width=newwidth;}
    function HeightIs(id, newheight){$(id).style.height=newheight;}
    function TopIs(id, newtop){$(id);}
    function LeftIs(id, newleft){$(id).style.left=newleft;}
    XIs = LeftIs; YIs = TopIs; // Some aliases

    // Increase the height, width, top (y), or left (x) properties of
    function AddToHeight(id, pixels) {HeightIs(id,
    function AddToWidth(id, pixels) {WidthIs(id, (Width(id)+pixels));}
    function AddToX(id, pixels) {LeftIs(id, Left(id)+pixels);}
    function AddToY(id, pixels) {TopIs(id, Top(id)+pixels);}
    // X and Y are shorter than Left and Top, but you might forget
    AddToLeft = AddToX; AddToTop = AddToY; // aliases

    // Put an object in a a container object (at its end) both passed by
    reference, not id
    function PutIn(targetobject, newcontainer)

    // If we're meant to be moving a window, move it according to start
    and current positions
    function MoveIfMoving(e)
    if (AreMoving)
    NewX = StartObjectX + (e.clientX - StartMouseX);
    NewY = StartObjectY + (e.clientY - StartMouseY);
    if (NewX > 0) XIs(CurrentObject, NewX);
    if (NewY > 0) YIs(CurrentObject, NewY);

    ExtraWidth = Left(CurrentObject)+Width(CurrentObject) -
    ExtraHeight = Top(CurrentObject)+Height(CurrentObject) -
    if (ExtraWidth > 0) WidthIs("desktop", Width("desktop")+
    if (ExtraHeight > 0) HeightIs("desktop", Height("desktop")+
    $("desktopheight").value = Height("desktop");
    $("desktopwidth").value = Width("desktop");
    // Also we might be sizing instead
    else if (AreSizing) SizeObject(e);

    // executed for sizing buttons, not a low-level function.
    function SizeObject(e)
    xdiff = e.clientX - StartMouseX;
    ydiff = e.clientY - StartMouseY;

    if (SizingType == "out") // make window bigger, no matter what
    direction you move mouse.
    WinSize(CurrentObject, Math.abs(xdiff)+StartObjectWidth,
    if (xdiff < 0) XIs(CurrentObject, StartObjectX + xdiff);
    if (ydiff < 0) YIs(CurrentObject, StartObjectY + ydiff);
    else if (SizingType == "in")
    WinSize(CurrentObject, StartObjectWidth-Math.abs(xdiff),
    if (xdiff > 0) XIs(CurrentObject, StartObjectX + xdiff);
    if (ydiff > 0) YIs(CurrentObject, StartObjectY + ydiff);
    else if (SizingType == "se") // south east
    WinSize(CurrentObject, StartObjectWidth + xdiff, StartObjectHeight
    + ydiff);
    else if (SizingType == "nw") // north west
    XIs(CurrentObject, StartObjectX + xdiff);
    YIs(CurrentObject, StartObjectY + ydiff);
    WinSize(CurrentObject, StartObjectWidth - xdiff, StartObjectHeight
    - ydiff);

    // Start and stop moving objects around the screen when you press or
    unpress the mouse
    function StopMoving() {AreMoving=false;ShowObjectFrame(); }
    function StopSizing() {AreSizing=false; ShowObjectFrame();}
    function ShowObjectFrame(){if ($(CurrentObject+"_iframe"))
    function SetMouseMoving(e) {StartMouseX = e.clientX; StartMouseY =
    e.clientY; }
    function StartMoving(ObjectID)

    // Find out about what state an object was in at start of dragging
    or sizing.
    function CatchObjectState(ObjectID)
    CurrentObject = ObjectID;
    StartObjectX = Left(ObjectID); StartObjectY = Top(ObjectID);
    StartObjectHeight = Height(ObjectID); StartObjectWidth =
    if ($(ObjectID+"_iframe")) hide(ObjectID+"_iframe");

    function StartSizing(ObjectID, type)
    SizingType = type;

    function hide(id) {$(id).style.display='none';}
    function show(id)
    function toggle(id){if ($(id).style.display == "none") show(id);
    else hide(id);}
    function ToTop(id) {}//$(id).style.zIndex = -1;}

    function WinSize(id, x, y)
    if (x <1) x=1; if (y <1) y=1;
    HeightIs(id, y);WidthIs(id, x);
    HeightIs(id+"_div", y);WidthIs(id+"_div", x);
    HeightIs(id+"_iframe", y);WidthIs(id+"_iframe", x);

    function WinMove(id, x, y)
    if (x<1) x=1; if (y<1) y=1;
    // if position is further than desktop's size, increase desktop
    if (x+Width(id) > Width("desktop")) AddToWidth("desktop", ((x -
    Width("desktop")) + Width(id)));
    if (y+Height(id) > Height("desktop")) AddToHeight("desktop", ((y -
    Height("desktop")) + Height(id)));
    XIs(id, x); YIs(id, y);
    ShowDesktopSize(); // Update the size numbers on the navbox

    // The sizing buttons, as we need two per window of each.
    function sizeinbutton(id)
    var sizeinbutton = $make("button"); PutIn($text("> <"),
    sizeinbutton.onmousedown = function (){StartSizing(id, "in");} = "ew-resize";
    return sizeinbutton;

    function sizeoutbutton(id)
    // The size bigger button
    var sizeoutbutton = $make("button"); PutIn($text("< >"),
    sizeoutbutton.onmousedown = function (){StartSizing(id, "out");} = "ew-resize";
    return sizeoutbutton;

    // Size southeast
    function sizesebutton(id)
    var sizesebutton = $make("button"); PutIn($text("v>"),
    sizesebutton.onmousedown = function (){StartSizing(id, "se");} = "se-resize";
    return sizesebutton;

    // Size northwest
    function sizenwbutton(id)
    var sizenwbutton = $make("button"); PutIn($text("<^"),
    sizenwbutton.onmousedown = function (){StartSizing(id, "nw");} = "se-resize";
    return sizenwbutton;

    // For processing move forms, not to be confused with the lower
    level WinMove();
    function MoveWindow(id)
    x = $(id+"_x").value;
    y = $(id+"_y").value;
    WinMove(id, x, y);

    // Create a window for this windowing system, it's a table with a
    title bar and an iframe
    // and some borders
    function CreateWindow(src, id, title, height, width, top, left)
    var id = IfNo(id, "Window_"+Windows++);
    while ($(id)) id = "Window_"+Windows++;
    var nw = $make("table", id); = ++TopZIndex; // This is used to put windows on
    top = "absolute";
    nw.onclick = function(){if (TopZIndex ==0) TopZIndex = Windows; = ++TopZIndex;}//.position = "absolute"; = IfNo(height, 300); = IfNo(width, 400); = IfNo(top, 60); = IfNo(left, 90);"white";

    // the title bar, one cell;
    var tb = $make("td"); = "move";"100%"; tb.align="left";"ddddee";

    // now the control bar, another cell;
    var ctlb = $make("td"); ctlb.align="left"; ctlb.width="80px";"nowrap";

    // Sizing in and out buttons.
    var TopSizeIn = sizeinbutton(id);
    var BottomSizeIn = sizeinbutton(id);
    var TopSizeOut = sizeoutbutton(id);
    var BottomSizeOut = sizeoutbutton(id);

    // The close bar has just the close button
    var cb = $make("td"); cb.align = "right"; cb.width="1px";
    var closebutton = $make("button"); PutIn($text("x"), closebutton);
    closebutton.onclick = function (){$del(id);WindowsNow--} = "crosshair";
    PutIn(closebutton, cb);

    // Put the controls in the control box;
    PutIn(sizenwbutton(id), ctlb); PutIn(TopSizeOut, ctlb);
    PutIn(TopSizeIn, ctlb);
    titletext = $input("text", id+"_Title", (IfNo(title, "Title Bar
    "+id))); // Title bar text"100%"; // offset by the nowrap properties of
    other cells = "move";
    PutIn(titletext, tb);

    // The main application section, an iframe in a div in a cell
    var appframe = $make("iframe", id+"_iframe"); = IfNo(height, 300); = IfNo(width, 400);
    appframe.src = IfNo(src, "http://localhost");"none";//src = IfNo(src,

    if (src == "") appframe.src = "http://localhost";

    var appdiv = $make("div"); = id+"_div"; = IfNo(height, 300); = IfNo(width, 400);"solid";"black";

    var row1 = $make("tr"); var row2 = $make("tr");"top";row1.height="10";

    // Now the table cell to contain the div with the iframe.
    var appcell = $make("td");appcell.colSpan =3;

    // The third row
    var row3 = $make("tr");
    var row3cell = $make("td"); row3cell.colSpan=3;

    // The moving form:
    var mf = $make("form");"inline";
    mf.onsubmit = function() {MoveWindow(id); return false;}
    PutIn($text("x: "), mf);
    xmov = $input("text", id+"_x", 10000); xmov.size=5;
    ymov = $input("text", id+"_y", 10000); ymov.size=5;
    movbutn = $input("submit", id+"_mov", "<- Move");
    PutIn(xmov, mf);PutIn($text(", y: "), mf);PutIn(ymov, mf);
    PutIn(movbutn, mf); PutIn(mf, row3cell);

    // Sizing buttons for row 3.
    PutIn(BottomSizeIn, row3cell); PutIn(BottomSizeOut, row3cell);
    PutIn(sizesebutton(id), row3cell); PutIn(row3cell, row3);

    // Now make the moving events:
    tb.onmousedown = function(){StartMoving(id);}
    tb.onmouseup = function(){show(id+"_iframe");}

    // Put the frame in the cell
    PutIn(appframe, appdiv); PutIn(appdiv, appcell);
    // The appcell in the sceond row, the title bar in the first
    PutIn(appcell, row2);
    // control box, title box, close box
    PutIn(ctlb, row1);PutIn(tb, row1); PutIn(cb, row1);
    //the three rows into the table (window)
    tablebody = $make("tbody"); // ie is fussy about this
    PutIn(row1, tablebody); PutIn(row2, tablebody);PutIn(row3,
    // the window into the desktop
    PutIn(tablebody, nw); PutIn(nw, $("desktop"));

    <!-- The Desktop-Navigation box scripts-->
    function gotosection(section)
    if (section < 11) yoffset = 0;
    else if (section < 21) yoffset = 1;
    else if (section < 31) yoffset = 2;
    else if (section < 41) yoffset = 3;
    else if (section < 51) yoffset = 4;
    else if (section < 61) yoffset = 5;
    else if (section < 71) yoffset = 6;
    else if (section < 81) yoffset = 7;
    else if (section < 91) yoffset = 8;
    else yoffset = 9;

    x = (Width("desktop")/10)*((section-1)-yoffset*10);
    y = (Height("desktop")/10)*(yoffset);

    NavBoxX = 450; // Offset values to display the navbox after moving.
    NavBoxY = 60;

    // Move navbar to some visible area:
    if (x+Width("navbox")+NavBoxX < Width("desktop")) XIs("navbox",
    else {Overlap = (x+Width("navbox")) - Width("desktop");
    XIs("navbox", x-Overlap);}

    if (y+Height("navbox")+NavBoxY < Height("desktop")) YIs("navbox",
    else {Overlap = (y+Height("navbox")) - Height("desktop");
    YIs("navbox", y-Overlap);}

    window.scrollTo(x,y); // scroll the window to the start of the
    desired hundredth square.


    <!-- the desktop gui object -->
    <div id='desktop'
    onmousedown ='SetMouseMoving(event)'

    <!-- the navigation box -->
    <div id='navbox' onclick=';'
    <table border=1 width=100% height=100%>
    <tr style='vertical-align:top;'>
    <td colspan=2 style='cursor:move;'
    <table border=0 width="100%"> <tr><td>Desktop</td>
    <td align=right id='fetchbox'> <a
    onclick='MakeWindowList()'> Fetch Window: ...</a></td></tr>

    <!-- the navigation grid -->
    <td id='desktopgrid'>
    function MakeNavGrid()
    navtable = $make("table");
    tablebody = $make("tbody");
    for (rows=1;rows<11;rows++)
    var row = $make("tr");
    for (cols=1;cols<11;cols++)
    var cell = $make("td");
    Section = ((rows-1)*10) + cols;;"9";
    cell.onclick = function (){gotosection(;} ="pointer";
    PutIn($text(" "+Section+" "), cell);
    PutIn(cell, row);
    PutIn(row, tablebody);
    PutIn(tablebody, navtable);
    PutIn(navtable, $("desktopgrid"));

    MakeNavGrid(); // Make a nav grid, it knows where to put

    function FetchWindow(list, e) // Get a window according to a
    var winid = list[list.selectedIndex].value;
    WinMove(winid, Left("navbox"), Top("navbox"));//XIs(winid,
    Left("navbox")); YIs(winid, Top("navbox"));
    AddToHeight("navbox", -200);
    function MakeWindowList() // show all windows on navbox.
    // Delete it if it's already there.
    if ($("WindowList"))
    AddToHeight("navbox", -200);
    var WindowList= $make("select","WindowList");
    var tables = document.getElementsByTagName('table');
    for (table in tables)
    id = tables[table].id ;
    if (id != undefined)
    // if there's an iframe it's one of ours
    if ($(id+"_iframe"))
    option = $make("option");
    option.value = id;
    PutIn($text($(id+"_Title").value), option);
    PutIn(option, WindowList);

    WindowList.size = 10; = "block";
    WindowList.onclick = function(){FetchWindow(this,
    PutIn(WindowList, $("fetchbox"));
    AddToHeight("navbox", 200);

    function SizeDesktop() // resize the desktop according to the
    HeightIs("desktop", $("desktopheight").value);
    WidthIs("desktop", $("desktopwidth").value);
    return false;

    function ShowDesktopSize() // reset the navbox values according
    to the desktop
    $("desktopheight").value = Height("desktop");
    $("desktopwidth").value = Width("desktop");
    <td style='vertical-align:top;font-size:11;'>
    <form onsubmit='return SizeDesktop()' style='display:inline;'>
    <font style='font-weight:bold;'>Width</font><br><input
    type='text' value='10000' size=3 id='desktopwidth' /><br> pixels
    <font style='font-weight:bold;'>Height</font><br><input
    type='text'value='10000' size=3 id='desktopheight' />pixels
    <input type='submit' value='Set' />
    <td colspan=2>
    <font style='font-size:10;'>
    Go to a section, resize, or stretch the desktop by dragging
    any window past its edges

    <!-- desktop background controls -->
    <table border=0
    [<a style='cursor:pointer;color:blue;'
    onclick='toggle("helpbox");XIs("helpbox", 40);YIs("helpbox",
    [<a style='cursor:pointer;color:blue;' onclick='XIs("navbox",
    450);YIs("navbox", 60);show("navbox");'>Navbox</a>]
    <td align=right> Load URL:
    <form style='display:inline;' onsubmit='return LoadUrl();'>
    function LoadUrl() // grab the url from the form and load it in
    a new window.
    WindowsNow++;CreateWindow($("newurl").value, undefined,
    return false;
    <input type='text' style='font-size:10;' size=40 id='newurl'
    value='' />
    <input type='text' style='font-size:10;' id='newtitle'
    value='New Title' />
    <input type='submit' style='cursor:pointer;' value='<-Open' />
    <br>Execute Javascript [<a

    <div style="display:block;" id="codeboxes">
    <textarea id='code' ACCESSKEY='C' rows=4 cols=40
    <textarea id='codememory' rows=4 cols=40

    <!-- the help box -->
    <table onclick=';' id="helpbox"
    <td onmousedown="StartMoving('helpbox');" style='cursor:move;'>
    <font style='color:005500;font-weight:bold;'>Help</font></td>
    <ul style='overflow:auto;
    <li>Press tab in top textbox to execute its contents </li>
    <li>Alt+C to set focus to the code box</li>
    <li>L(+tab) to show last code</li>
    <li>Javascript will be copied to the second box regardless</li>
    <li>Commands provided by this system:
    <ul style='font-family:courier;'>
    <li>CreateWindow(url, id, title, height, width, top, left);
    <font style='color:green;'>// Like the "open" button. Only url
    is necessary.</font></li>
    <li>WinMove(id, x, y); <font style='color:green;'> // Move a
    window by id,
    resize desktop accordingly</font></li>
    <li>WinSize(id, x, y); <font style='color:green;'> // Doesn't
    resize the desktop</font></li>
    <li>msg(text); <font style='color:green;'>// shortcut to
    <li>$(id); <font style='color:green;'>//
    <li>$make(tagtype, id); <font style='color:green;'>// return a
    new html element</font></li>
    <li>$del(id); <font style='color:green;'>// remove element
    from document tree </font></li>
    <li>$text(text); <font style='color:green;'>// returns a text
    node with text in it </font></li>
    <li>$input(type, name, value, id); <font
    style='color:green;'>// returns a form input. Type and name are
    <li>AddToHeight(id, pixels); <font style='color:green;'>// Add
    to an elements height, must already have a pixel value</font></li>
    <li>AddToWidth(id, pixels);</li>
    <li>AddToTop(id, pixels); <font style='color:green;'>// Can
    also use AddToY();</font></li>
    <li>AddToLeft(id, pixels); <font style='color:green;'>// Can
    also use AddToX();</font></li>

    <!-- this will execute as the page finishes loading -->
    LastCommand=""; // The last code executed from the javascript box

    function ExecuteJavascript(CodeBox)
    var Code = CodeBox.value;
    if (Code.toUpperCase() == "L") // in a fraction of a second, show
    last command
    setTimeout("$('code').focus();$('code').value = LastCommand;",
    else if(Code.toUpperCase() != "")
    LastCommand = CodeBox.value;

    // Use to add the executed code to a buffer, (the second text box).
    function GetCode()
    var Code = $("code").value;
    if (Code.toUpperCase() != "L" && Code !="")

    $("code").focus(); // set focus to the javascript code box
    darwinist, Aug 1, 2006
    1. Advertisements

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. okaminer
    Feb 16, 2005
  2. Peter Swanson

    Re: Website width for 800 x 600 pixel

    Peter Swanson, Aug 8, 2003, in forum: HTML
    Peter Swanson
    Aug 8, 2003
  3. Peter Swanson

    Re: Website width for 800 x 600 pixel

    Peter Swanson, Aug 8, 2003, in forum: HTML
    Some One
    Aug 10, 2003
  4. darwinist
    Aug 1, 2006
  5. Steve
    Richard Cornford
    Apr 9, 2005

Share This Page