hosting/server/htdocs/page/index.html (1,034 lines of code) (raw):

<!DOCTYPE html> <!-- * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. --> <div id="bodydiv" class="body"> <div id="viewcontent" class="viewcontent"> <div id="pagecontainer"> <div id="pagediv" class="pagediv"> </div> <!-- <div class="guide" style="position: absolute; left: 0px; top: 0px; width: 320px; height: 460px;"></div> <div class="guide" style="position: absolute; left: 0px; top: 0px; width: 480px; height: 300px;"></div> <div class="guide" style="position: absolute; left: 0px; top: 0px; width: 768px; height: 911px;"></div> <div class="guide" style="position: absolute; left: 0px; top: 0px; width: 1024px; height: 655px;"></div> --> </div> <div id="playdiv" class="playdiv" style="display: none;"></div> </div> <div id="palettecontainer"> <div id="paletteview" style="display: none;"> <div id="palettecontent" class="palettecontent"> <table class="palettetable"> <tr><td class="palettetd"><span class="hd1" id="palette:h1"><span>Header 1</span></span></td></tr> <tr><td class="palettetd"><span class="hd2" id="palette:h2"><span>Header 2</span></span></td></tr> <tr><td class="palettetd"><span class="section" id="palette:section"><span>Section</span></span></td></tr> <tr><td class="palettetd"><span class="text" id="palette:text"><span>Some text</span></span></td></tr> <tr><td class="palettetd"><span class="link" id="palette:link"><a href="/"><span>Link</span></a></span></td></tr> <tr><td class="palettetd"><span class="button" id="palette:graybutton"><input type="button" value="Button" class="graybutton"/></span></td></tr> <tr><td class="palettetd"><span class="button" id="palette:redbutton"><input type="button" value="Button" class="redbutton"/></span></td></tr> <tr><td class="palettetd"><span class="button" id="palette:greenbutton"><input type="button" value="Button" class="greenbutton"/></span></td></tr> <tr><td class="palettetd"><span class="button" id="palette:bluebutton"><input type="button" value="Button" class="bluebutton"/></span></td></tr> <tr><td class="palettetd"><span class="entry" id="palette:entry"><input type="text" value="Entry Field" class="flatentry" size="10" autocapitalize="off" readonly="true" style="cursor: default;"/></span></td></tr> <tr><td class="palettetd"><span class="password" id="palette:password"><input type="password" value="Password" class="flatentry" size="10" readonly="true" style="cursor: default;"/></span></td></tr> <tr><td class="palettetd"><span class="checkbox" id="palette:checkbox"><input type="checkbox" value="Checkbox" class="flatcheckbox"/><span>Checkbox</span></span></td></tr> <!-- <tr><td class="palettetd"><span class="select" id="palette:select"><select disabled="true"><option value="select">Selection</option></select></span></td></tr> --> <tr><td class="palettetd"><span class="list" id="palette:list"> <table class="datatable"> <tr><td class="datatd"><span>List</span></td></tr> <tr><td class="datatd"><span>List</span></td></tr> <tr><td class="datatd"><span>List</span></td></tr> </table> </span></td></tr> <tr><td class="palettetd"><span class="table" id="palette:table"> <table class="datatable"> <tr><td class="datatdl"><span>Table</span></td><td class="datatdr"><span>Table</span></td></tr> <tr><td class="datatdl"><span>Table</span></td><td class="datatdr"><span>Table</span></td></tr> <tr><td class="datatdl"><span>Table</span></td><td class="datatdr"><span>Table</span></td></tr> </table> </span></td></tr> <tr><td class="palettetd"><span class="img" id="palette:img"><img id="imgimg"/></span></td></tr> </table> </div> </div> </div> <div id="xhtmlbuffer" style="display: none;"></div> <script type="text/javascript"> (function pagebody() { /** * Get the current app name. */ var appname = ui.fragmentParams(location)['app']; /** * Setup page layout. */ (function layout() { document.title = config.windowtitle() + ' - Page - ' + appname; $('viewhead').innerHTML = '<span id="appTitle" class="cmenu">' + appname + '</span>' + '<input type="button" id="deleteWidgetButton" title="Delete a widget" class="redbutton plusminus" style="position: absolute; top: 4px; left: 2px;" disabled="true" value="-"/>' + '<span style="position: absolute; top: 0px; left: 37px; right: 110px; padding: 0px; background: transparent;"><input id="widgetValue" type="text" value="" class="flatentry" title="Widget value" autocapitalize="off" placeholder="Value" style="position: absolute; left: 0px; top: 4px; width: 100%; display: none;" readonly="readonly"/></span>' + '<input type="button" id="playPageButton" title="View page" class="greenbutton plusminus" style="position: absolute; top: 4px; right: 72px;" value="&gt;"/>' + '<input type="button" id="copyWidgetButton" title="Copy a widget" class="bluebutton" style="position: absolute; top: 4px; right: 37px; font-size: 16px;" disabled="true" value="C"/>' + '<input type="button" id="addWidgetButton" title="Add a widget" class="bluebutton plusminus" style="position: absolute; top: 4px; right: 2px;" disabled="true" value="+"/>'; //'<input type="button" id="appInfoButton" title="View app info" class="bluebutton" style="position: absolute; top: 4px; right: 2px; font-size: 16px;" value="i"/>'; if (ui.isMobile()) { $('palettecontainer').className = 'palettecontainer3dm'; $('paletteview').className = 'paletteloaded3dm'; } else { $('viewcontent').className = 'viewcontent flatscrollbars'; $('palettecontainer').className = 'palettecontainer3d'; $('paletteview').className = 'paletteloaded3d'; $('palettecontent').className = 'palettecontent flatscrollbars'; } $('imgimg').src = ui.b64png(appcache.get('/public/img.b64')); })(); /** * Track the current page, author, and saved XHTML content. */ var author = ''; var editable = false; var savedxhtml = ''; /** * Initialize component references. */ var editorComp = sca.component('Editor'); var pages = sca.reference(editorComp, 'pages'); /** * Return the transform property of a widget. */ var msiefixupbounds = ui.isMSIE(); function widgettransform(e) { if (!isNull(e.xtranslate)) return [e.xtranslate, e.ytranslate]; var t = e.style.getPropertyValue('-webkit-transform') || e.style.getPropertyValue('-moz-transform') || e.style.getPropertyValue('-ms-transform') || e.style.getPropertyValue('-o-transform') || e.style.getPropertyValue('transform'); if (t) { var xy = t.split('(')[1].split(')')[0].split(','); return [ui.numpos(xy[0]), ui.numpos(xy[1])]; } if (e.id.substring(0, 8) == 'palette:') { // On Internet Explorer get the view bounding rect as the palette // doesn't return a correct bounding rect var pbr = msiefixupbounds? $('viewcontent').getBoundingClientRect() : $('palettecontent').getBoundingClientRect(); var br = e.getBoundingClientRect(); return [br.left - pbr.left, br.top - pbr.top]; } return [0, 0]; } /** * Return the x position of a widget. */ function widgetxpos(e) { var t = widgettransform(e)[0]; return ui.numpos(e.style.left) + (isNull(t)? 0 : t); } /** * Return the y position of a widget. */ function widgetypos(e) { var t = widgettransform(e)[1]; return ui.numpos(e.style.top) + (isNull(t)? 0 : t); } /** * Return the class of a widget. */ function widgetclass(e) { return e.className.split(' ')[0]; } /** * Initialize a widget. */ function fixupwidget(e) { // Add draggable class var wc = e.className; e.className = ui.isMobile()? (wc + ' draggable3dm') : (wc + ' draggable3d'); // Convert widget position to a CSS transform var x = ui.numpos(e.style.left); var y = ui.numpos(e.style.top); var t = 'translate(' + x + 'px,' + y + 'px)'; e.style.setProperty('-webkit-transform', t, null); e.style.setProperty('-moz-transform', t, null); e.style.setProperty('-o-transform', t, null); e.style.setProperty('-ms-transform', t, null); e.style.setProperty('transform', t, null); e.xtranslate = x; e.ytranslate = y; e.style.left = ui.pixpos(0); e.style.top = ui.pixpos(0); if (wc == 'entry' || wc == 'password') { var i = car(childElements(e)); i.readOnly = true; i.style.cursor = 'default'; return e; } if (wc == 'link') { var l = car(childElements(e)); l.onclick = function(e) { return false; }; return e; } return e; } /** * Cleanup a widget before saving it. */ function cleanupwidget(e) { //debug('cleanupwidget', e); // Adjust widget class var wc = widgetclass(e); e.className = wc; // Convert CSS transform to an absolute position e.style.left = ui.pixpos(widgetxpos(e)); e.style.top = ui.pixpos(widgetypos(e)); e.style.removeProperty('-webkit-transform'); e.style.removeProperty('-moz-transform'); e.style.removeProperty('-o-transform'); e.style.removeProperty('-ms-transform'); e.style.removeProperty('transform'); e.xtranslate = null; e.ytranslate = null; // Clear outline e.style.removeProperty('outline'); if (wc == 'entry' || wc == 'password') { var i = car(childElements(e)); i.readOnly = false; i.style.cursor = null; return e; } if (wc == 'link') { var l = car(childElements(e)); l.onclick = null; return e; } return e; } /** * Clone a widget. */ function clonewidget(e) { /** * Clone an element's HTML. */ function mkclone(e) { var ne = document.createElement('span'); // Skip the palette: prefix ne.id = 'page:' + e.id.substr(8); // Copy the class and HTML content ne.className = widgetclass(e); ne.innerHTML = e.innerHTML; // Fixup the widget fixupwidget(ne); return ne; } /** * Clone an element's position. */ function posclone(ne, e) { ne.style.position = 'absolute'; movewidget(ne, widgetxpos(e), widgetypos(e)); return ne; } return posclone(mkclone(e), e); } /** * Select a widget. */ function selectwidget(n, s) { //debug('selectwidget', n, s); if (isNull(n) || !s) { // Clear the widget value field $('widgetValue').value = ''; $('widgetValue').readOnly = true; $('widgetValue').style.display = 'none'; // Show the app title $('appTitle').style.display = 'block'; // Update the copy and delete buttons $('copyWidgetButton').disabled = true; $('deleteWidgetButton').disabled = true; // Clear the widget outline if (!isNull(n)) n.style.removeProperty('outline'); return true; } // Outline the widget n.style.outline = '2px solid #598edd'; // Update the widget value field $('widgetValue').value = widgettext(n); $('widgetValue').readOnly = false || !editable; $('widgetValue').style.display = 'block'; // Hide the app title $('appTitle').style.display = 'none'; // Update the copy and delete buttons $('copyWidgetButton').disabled = false || !editable; $('deleteWidgetButton').disabled = false || !editable; return true; } /** * Return the text of a widget. */ function widgettext(e) { function formula(e) { var f = e.id; if (f.substring(0, 5) != 'page:') return '=' + f; return ''; } function constant(e, f) { var wc = widgetclass(e); if (wc == 'hd1' || wc == 'hd2' || wc == 'text' || wc == 'section') { var t = car(childElements(e)).innerHTML; return t == f? '' : t; } if (wc == 'button' || wc == 'checkbox') { var t = car(childElements(e)).value; return t == f? '' : t; } if (wc == 'entry' || wc == 'password') { var t = car(childElements(e)).defaultValue; return t == f? '' : t; } if (wc == 'select') { var t = car(childElements(car(childElements(e)))).value; return t == f? '' : t; } if (wc == 'link') { var lhr = car(childElements(e)).href; var hr = lhr.substring(0, 5) == 'link:'? lhr.substring(5) : ''; var t = car(childElements(car(childElements(e)))).innerHTML; return t == f? hr : (t == hr? hr : (t == ''? hr : hr + ',' + t)); } if (wc == 'img') { var src = car(childElements(e)).src; return src == location.href? '' : src; } if (wc == 'list') return ''; if (wc == 'table') return ''; return ''; } var f = formula(e); var c = constant(e, f); return f == ''? c : (c == ''? f : f + ',' + c); } /** * Return true if a widget has editable text. */ function widgethastext(e) { var wc = widgetclass(e); if (wc == 'hd1' || wc == 'hd2' || wc == 'text' || wc == 'section') return true; if (wc == 'button' || wc == 'checkbox') return true; if (wc == 'entry' || wc == 'password') return true; if (wc == 'select') return false; if (wc == 'link') return true; if (wc == 'img') return true; if (wc == 'list') return false; if (wc == 'table') return false; return false; } /** * Set the text of a widget. */ function setwidgettext(e, t) { function formula(t) { if (t.length > 1 && t.substring(0, 1) == '=') return car(t.split(',')); return ''; } function constant(t) { return t.length > 1 && t.substring(0, 1) == '='? cdr(t.split(',')) : t.split(','); } var f = formula(t); var c = constant(t); var wc = widgetclass(e); e.id = f != ''? f.substring(1) : ('page:' + wc); if (wc == 'hd1' || wc == 'hd2' || wc == 'text' || wc == 'section') { car(childElements(e)).innerHTML = isNull(c)? f : car(c); return t; } if (wc == 'button') { car(childElements(e)).value = isNull(c)? f : car(c); return t; } if (wc == 'entry' || wc == 'password') { car(childElements(e)).defaultValue = isNull(c)? f : car(c); return t; } if (wc == 'checkbox') { car(childElements(e)).value = isNull(c)? f : car(c); map(function(n) { if (n.nodeName == "SPAN") n.innerHTML = isNull(c)? f : car(c); return n; }, nodeList(e.childNodes)); return t; } if (wc == 'select') { var ce = car(childElements(car(childElements(e)))); ce.value = isNull(c)? f : car(c); ce.innerHTML = isNull(c)? f : car(c); return t; } if (wc == 'list') { e.innerHTML = '<table class="datatable" style="width: 100%;;"><tr><td class="datatd">' + (isNull(c)? f : car(c)) + '</td></tr><tr><td class="datatd">...</td></tr></table>'; return t; } if (wc == 'table') { e.innerHTML = '<table class="datatable" style="width: 100%;"><tr><td class="datatdl">' + (isNull(c)? f : car(c)) + '</td><td class="datatdr">...</td></tr><tr><td class="datatdl">...</td><td class="datatdr">...</td></tr></table>'; return t; } if (wc == 'link') { var ce = car(childElements(e)); ce.href = isNull(c)? 'link:/index.html' : ('link:' + car(c)); car(childElements(ce)).innerHTML = isNull(c)? (f != ''? f : '/index.html') : isNull(cdr(c))? (f != ''? f : car(c)) : cadr(c); return t; } if (wc == 'img') { car(childElements(e)).src = isNull(c)? '/public/img.png' : car(c); return t; } return ''; } /** * Align a pos along a 9pixel grid. */ function snaptogrid(x) { return Math.round(x / 10) * 10; } /** * Bring a node to the top. */ function bringtotop(n) { n.parentNode.appendChild(n); } /** * Move a widget. */ var iefixuptransform = ui.isMSIE(); var fffixupoutline = ui.isFirefox() && (ui.firefoxVersion() > 4); function movewidget(e, x, y) { var t = 'translate(' + x + 'px,' + y + 'px)'; e.style.setProperty('-webkit-transform', t, null); e.style.setProperty('-moz-transform', t, null); e.style.setProperty('-o-transform', t, null); // On Internet Explorer set the property directly as setProperty // doesn't seem to apply if (iefixuptransform) e.style.msTransform = t; e.style.setProperty('transform', t, null); e.xtranslate = x; e.ytranslate = y; return e; } /** * Return a widget bounding rect. */ var fffixupbounds = ui.isFirefox() && (ui.firefoxVersion() < 12); function widgetbounds(e) { var br = e.getBoundingClientRect(); if (!fffixupbounds) return br; // On Firefox < 12, apply CSS transform translation to bounding rect manually //debug('fixup br', e, br.left, br.top, br.right, br.bottom, t[0], t[1]); function fixuptransform(e) { var t = widgettransform(e); if (!isNull(e.xtranslate)) return [e.xtranslate, e.ytranslate]; var t = e.style.getPropertyValue('-webkit-transform') || e.style.getPropertyValue('-moz-transform') || e.style.getPropertyValue('-ms-transform') || e.style.getPropertyValue('-o-transform') || e.style.getPropertyValue('transform'); if (t) { var xy = t.split('(')[1].split(')')[0].split(','); return [ui.numpos(xy[0]), ui.numpos(xy[1])]; } return [0, 0]; } var t = fixuptransform(e); var fbr = new Object(); fbr.left = br.left + t[0]; fbr.top = br.top + t[1]; fbr.right = fbr.left + e.offsetWidth; fbr.bottom = fbr.top + e.offsetHeight; return fbr; } /** * Find a draggable element in a list. */ function draggable(x, y, l) { //debug('draggable?', x, y, l); if (isNull(l)) return null; var n = car(l); if (isNull(n.id) || n.id == '') { var d = draggable(x, y, reverse(nodeList(n.childNodes))); if (!isNull(d)) return d; return draggable(x, y, cdr(l)); } var br = widgetbounds(n); //debug('element br', n, br.left, br.top, br.right, br.bottom); if (x >= br.left && x <= br.right && y >= br.top && y <= br.bottom) return n; return draggable(x, y, cdr(l)); } /** * Play page in a frame. */ function showplaying() { $('playPageButton').value = '<'; $('playdiv').style.display = 'block'; $('playdiv').visible = true; $('playdiv').innerHTML = ''; $('playdiv').innerHTML = '<iframe id="playappframe" style="position: relative; border: 0px;" scrolling="no" frameborder="0" src="/' + appname + '"></iframe>'; if ($('pagediv').visible) { $('pagediv').style.display = 'none' $('pagediv').visible = false; } hidepalette(); return true; } /** * Show the page editor. */ function showeditor() { $('playPageButton').value = '>'; $('pagediv').style.display = 'block' $('pagediv').visible = true; if ($('playdiv').visible) { $('playdiv').style.display = 'none'; $('playdiv').innerHTML = ''; $('playdiv').visible = false; } hidepalette(); return true; } /** * Palette animation. */ function palettetransitionend(e) { if ($('paletteview').className == 'paletteunloaded3dm') $('paletteview').style.display = 'none'; } $('paletteview').addEventListener('webkitTransitionEnd', palettetransitionend, false); $('paletteview').addEventListener('transitionend', palettetransitionend, false); /** * Show the palette. */ function showpalette() { if (ui.isMobile()) { $('paletteview').className = 'paletteloading3dm'; $('paletteview').style.display = 'block'; $('paletteview').visible = true; ui.delay(function transitionview() { $('paletteview').className = 'paletteloaded3dm'; }); } else { $('paletteview').className = 'paletteloaded3d'; $('paletteview').style.display = 'block'; $('paletteview').visible = true; } return true; } /** * Hide the palette. */ function hidepalette() { if (ui.isMobile()) { $('paletteview').className = 'paletteunloading3dm'; $('paletteview').visible = false; ui.delay(function transitionview() { $('paletteview').className = 'paletteunloaded3dm'; }); } else { $('paletteview').className = 'paletteunloaded3d'; $('paletteview').style.display = 'none'; $('paletteview').visible = false; } return true; } /** * Create page editor. */ function mkeditor() { // Initialize header elements $('widgetValue').readOnly = true; $('widgetValue').style.display = 'none'; $('appTitle').style.display = 'block'; $('copyWidgetButton').disabled = true; $('deleteWidgetButton').disabled = true; $('addWidgetButton').disabled = !editable; // Track widget dragging and selection var dragging = null; var selected = null; var moved = false; var mdown = false; var moveX = 0; var moveY = 0; var dragX = 0; var dragY = 0; /** * Handle a page change event */ function onpagechange(prop) { if (!editable) return false; var newxml = pagexhtml(); if (savedxhtml == newxml) return false; showstatus('Modified'); // Save property changes right away if (prop) return save(newxml); // Autosave other changes after 1 second ui.async(function autosave() { if (savedxhtml == newxml) { showstatus('Saved'); return false; } return save(newxml); }, 1000); return true; } /** * Handle a widget select event. */ function onselectwidget(w) { if (w == selected) return true; selected = w; return true; } /** * Render widget move animation. */ function onmoveanimation() { //debug('onmoveanimation'); // Stop animation if we're not dragging an element anymore if (dragging == null) return true; // Request the next animation frame ui.animation(onmoveanimation); // Nothing to do if the selected widget has not moved if (moveX == dragX && moveY == dragY) return true; // Compute position of dragged element var curX = widgetxpos(dragging); var curY = widgetypos(dragging); var newX = curX + (moveX - dragX); var newY = curY + (moveY - dragY); var okx = true; if (newX + dragging.clientWidth > 1024) { newX = 1024 - dragging.clientWidth; okx = false; } if (newX < 0) { newX = 0; okx = false; } if (okx) dragX = moveX; var oky = true; if (newY + dragging.clientHeight > 1024) { newY = 1024 - dragging.clientHeight; oky= false; } if (newY < 0) { newY = 0; oky = false; } if (oky) dragY = moveY; // On Firefox > 4, remove outline before moving widget as it's not // correctly painted if (fffixupoutline) dragging.style.removeProperty('outline'); // Move the dragged element movewidget(dragging, newX, newY); return true; } /** * Handle a mouse down event. */ function onmousedown(e) { // On mouse controlled devices, run component selection logic right away if (!ui.isMobile()) { //debug('onmousedown-click'); onclick(e); } // Find a draggable widget var d = draggable(moveX, moveY, reverse(nodeList($('pagediv').childNodes))); //debug('dragging', d, 'selected', selected); if (d == null || d != selected) return true; dragging = d; // Remember mouse position dragX = moveX; dragY = moveY; // Start move animation ui.animation(onmoveanimation); e.preventDefault(); return true; } if (!ui.isMobile()) { $('pagediv').onmousedown = function(e) { //debug('onmousedown', e.target); mdown = true; moveX = e.clientX; moveY = e.clientY; moved = false; return onmousedown(e); }; $('palettecontent').onmousedown = function(e) { //debug('onmousedown', e.target); mdown = true; moveX = e.clientX; moveY = e.clientY; moved = false; return onmousedown(e); }; } else { $('pagediv').ontouchstart = function(e) { //debug('ontouchstart'); mdown = true; moveX = e.touches[0].clientX; moveY = e.touches[0].clientY; moved = false; return onmousedown(e); }; $('palettecontent').ontouchstart = function(e) { //debug('ontouchstart'); mdown = true; moveX = e.touches[0].clientX; moveY = e.touches[0].clientY; moved = false; return onmousedown(e); }; } /** * Handle a mouse up event. */ function onmouseup(e) { // Simulate onclick event if (ui.isMobile() && !moved) { //debug('ontouchend-click'); return onclick(e); } if (dragging == null) return true; // Snap dragged widget to grid var newX = snaptogrid(widgetxpos(dragging)); var newY = snaptogrid(widgetypos(dragging)); movewidget(dragging, newX, newY); // Forget dragged element dragging = null; // Trigger page change event onpagechange(false); // On Firefox > 4, re-apply the outline after the widget has been repositioned if (fffixupoutline && !isNull(selected)) { ui.delay(function() { if (!isNull(selected)) selected.style.outline = '2px solid #598edd'; }, 32); } return true; } if (!ui.isMobile()) { window.onmouseup = function(e) { //debug('onmouseup'); if (!mdown) return true; return onmouseup(e); }; } else { window.ontouchend = function(e) { //debug('ontouchend'); if (!mdown) return true; return onmouseup(e); } } if (!ui.isMobile()) { window.onmousemove = function(e) { //debug('onmousemove'); // Record mouse position if (e.clientX != moveX) { moved = true; moveX = e.clientX; } if (e.clientY != moveY) { moved = true; moveY = e.clientY; } if (dragging == null) return true; return false; }; } else { window.ontouchmove = function(e) { //debug('ontouchmove'); // Record touch position var t = e.touches[0]; if (t.clientX != moveX) { moved = true; moveX = t.clientX; } if (t.clientY != moveY) { moved = true; moveY = t.clientY; } if (dragging == null) return true; return false; }; } /** * Handle a mouse click event. */ function onclick(e) { // Find selected element var palvis = $('paletteview').visible? true : false; var s = draggable(moveX, moveY, reverse(nodeList((palvis? $('palettecontent') : $('pagediv')).childNodes))); //debug('selected', s); if (s == null) { if (selected != null) { // Reset current selection selectwidget(selected, false); selected = null; // Trigger widget select event onselectwidget(null); } // Dismiss the palette if (palvis && isNull(draggable(moveX, moveY, mklist($('palettecontent'))))) hidepalette(); return true; } // Deselect the previously selected element selectwidget(selected, false); // Clone widget dragged from palette if (s.id.substring(0, 8) == 'palette:') { selected = clonewidget(s); // Add it to the page $('pagediv').appendChild(selected); movewidget(selected, widgetxpos(selected) + $('viewcontent').scrollLeft, widgetypos(selected) + $('viewcontent').scrollTop); // Hide the palette hidepalette(); // Trigger page change event onpagechange(true); // Select the element selectwidget(selected, true); // Trigger widget select event onselectwidget(selected); return true; } // Bring selected widget to the top selected = s; bringtotop(selected); // Select the widget selectwidget(selected, true); // Trigger widget select event onselectwidget(selected); return true; } /** * Handle field on change events. */ $('widgetValue').onchange = $('widgetValue').onblur = function() { if (selected == null) return false; setwidgettext(selected, $('widgetValue').value); // Trigger page change event onpagechange(true); return false; }; // Handle add widget event. ui.onclick($('addWidgetButton'), function(e) { // Show / hide the palette if ($('paletteview').visible) return hidepalette(); return showpalette(); }); // Handle delete event. ui.onclick($('deleteWidgetButton'), function(e) { if (selected == null) return false; // Reset current selection selectwidget(selected, false); // Remove selected widget selected.parentNode.removeChild(selected); selected = null; // Trigger widget select event onselectwidget(null); // Trigger page change event onpagechange(true); return false; }); // Handle copy event. ui.onclick($('copyWidgetButton'), function(e) { if (selected == null) return false; if (selected.id.substring(0, 8) == 'palette:') return false; // Reset current selection selectwidget(selected, false); // Clone selected widget selected = clonewidget(selected); // Add it to the page $('pagediv').appendChild(selected); // Move 10 pixels down right movewidget(selected, widgetxpos(selected) + 10, widgetypos(selected) + 10); // Bring it to the top bringtotop(selected); // Select the element selectwidget(selected, true); // Trigger widget select event onselectwidget(selected); // Trigger page change event onpagechange(true); return false; }); /** * Handle play page button event. */ ui.onclick($('playPageButton'), function(e) { // Show / hide the page play frame if ($('playdiv').visible) return showeditor(); return showplaying(); }); // Show the editor showeditor(); return true; }; /** * Get and display the requested app page. */ (function getpage() { if (isNull(appname)) return false; workingstatus(true); showstatus('Loading'); return pages.get(appname, function(doc) { // Stop now if we didn't get a page if (doc == null) { errorstatus('Couldn\'t get the app info'); workingstatus(false); return false; } // Get the page from the ATOM entry, convert it to XHTML and place it in a hidden buffer var pageentry = car(atom.readATOMEntry(mklist(doc))); var content = namedElementChild("'content", pageentry); var el = isNull(content)? mklist() : elementChildren(content); if (isNull(el)) $('xhtmlbuffer').innerHTML = '<div id="page"></div>'; else $('xhtmlbuffer').innerHTML = writeStrings(writeXML(el, false)); // Remove any existing page nodes from the editor div var fnodes = filter(function(e) { if (isNull(e.id) || e.id == '') return false; return true; }, nodeList($('pagediv').childNodes)); map(function(e) { $('pagediv').removeChild(e); }, fnodes); // Fixup widgets and append them to the editor map(function(e) { $('pagediv').appendChild(e); fixupwidget(e); return e; }, nodeList($('xhtmlbuffer').childNodes[0].childNodes)); savedxhtml = pagexhtml($('pagediv')); // Enable author to edit the page author = elementValue(namedElementChild("'author", pageentry)); editable = author == username; $('addWidgetButton').disabled = !editable; if (editable) onlinestatus(); else showstatus('Read only'); workingstatus(false); return true; }); })(); /** * Return the current page XHTML content. */ function pagexhtml() { // Copy page DOM to hidden buffer $('xhtmlbuffer').innerHTML = '<div id="page"></div>' var div = $('xhtmlbuffer').childNodes[0]; // Capture the nodes inside the page div div.innerHTML = $('pagediv').innerHTML; var nodes = nodeList(div.childNodes); map(function(e) { div.removeChild(e); return e; }, nodes); // Filter out palette and editor artifacts, which are not // part of the page, as well as nodes positioned out the // editing area var fnodes = filter(function(e) { if (isNull(e.id) || e.id == '') return false; return true; }, nodes); // Reposition and cleanup nodes map(function(e) { cleanupwidget(e); return e; }, fnodes); // Sort them by position var snodes = fnodes.sort(function(a, b) { var ay = widgetypos(a); var by = widgetypos(b); if (ay < by) return -1; if (ay > by) return 1; var ax = widgetxpos(a); var bx = widgetxpos(b); if (ax < bx) return -1; if (ax > bx) return 1; return 0; }); // Append the sorted nodes back to the div in order map(function(e) { div.appendChild(e); return e; }, snodes); // Convert the page to XHTML var lxhtml = readXHTMLElement(div); var xhtml = writeStrings(writeXML(lxhtml, false)); return xhtml; } /** * Save the current page. */ function save(newxml) { workingstatus(true); showstatus('Saving'); // Get the current page XHTML content savedxhtml = newxml; // Update the page ATOM entry var entry = '<?xml version="1.0" encoding="UTF-8"?>\n' + '<entry xmlns="http://www.w3.org/2005/Atom">' + '<title type="text">' + appname + '</title><id>' + appname + '</id><author><email>' + author + '</email></author>' + '<content type="application/xml">' + newxml + '</content></entry>'; pages.put(appname, entry, function(e) { if (e) { showstatus('Local copy'); workingstatus(false); return false; } showstatus('Saved'); workingstatus(false); return false; }); return true; }; /** * Handle app info button event. */ /* Disabled for now. ui.onclick($('appInfoButton'), function(e) { return ui.navigate('/#view=info&app=' + appname, '_view'); }); */ /** * Initialize the page editor. */ mkeditor(); })(); </script> </div>