Mercurial > wiki
view static-files/wiki.js @ 25:0aecc756ea18
The web app now commits to the server, though it doesn't handle any edge cases whatsoever and is therefore extremely fragile.
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Thu, 12 Feb 2009 20:06:17 -0800 |
parents | b094768c285b |
children | a42400d52a1e |
line wrap: on
line source
/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (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.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Ubiquity. * * The Initial Developer of the Original Code is Mozilla. * Portions created by the Initial Developer are Copyright (C) 2007 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Atul Varma <atul@mozilla.com> * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ var App = { PART_SEPARATOR: "\n\n", creole: null, editingElement: null, latestRemoteChangeset: null, localChanges: [], eventHandlers: {} }; App.eventHandlers.editPart = function editPart(aEvt) { if (!aEvt.shiftKey) return; aEvt.preventDefault(); App.enterEditMode([this], 1); }; App.getMarkup = function getMarkup(parts) { var partsMarkup = []; $(".creole-markup", parts).each( function(i) { partsMarkup.push($(this).text()); } ); return partsMarkup.join(App.PART_SEPARATOR); }; App.saveChanges = function saveChanges(isUserChange) { var markup = App.getMarkup($(window.document)); var changeset = {date: new Date(), content: markup, parentRemoteChangeset: App.latestRemoteChangeset}; App.localChanges.push(changeset); var changesetElem = $('<div class="changeset selected"></div>'); function setText() { changesetElem.text(jQuery.timeago(changeset.date)); } window.setInterval(setText, 60000); setText(); changesetElem.mousedown( function(aEvt) { aEvt.preventDefault(); if (aEvt.shiftKey) { $('#recent-changes').find('.changeset').removeClass('diffed'); var newerVersion = App.getMarkup($("#content")); var diff = $('<div class="diff"></div>'); var markupDiv = $('<div class="creole-markup"></div>'); markupDiv.text(newerVersion); diff.html(diffString(changeset.content, newerVersion)); $("#content").empty(); $("#content").append(diff); $("#content").append(markupDiv); $(this).addClass('diffed'); } else { $('#recent-changes').find('.changeset').removeClass('selected'); $('#recent-changes').find('.changeset').removeClass('diffed'); $(this).addClass('selected'); $("#content").empty(); $("#content").append(App.createParts(changeset.content)); } } ); $('#recent-changes').find('.changeset').removeClass('selected'); $('#recent-changes').find('.changeset').removeClass('diffed'); $('#recent-changes').find('h1').after(changesetElem); if (isUserChange) { $('#recent-changes').fadeIn(); var maybeNewChangeset = App.latestRemoteChangeset + 1; var jsonData = JSON.stringify({date: changeset.date.toString(), content: changeset.content}); jQuery.ajax({url: '/' + maybeNewChangeset, type: 'PUT', success: function() { // TODO: Because we're running asynchronously, // weird things can happen here, e.g. if the user // makes another edit while the XHR is being // processed. App.latestRemoteChangeset = maybeNewChangeset; }, error: function(xhr, textStatus, errorThrown) { // TODO: Do something here. }, dataType: 'text', processData: false, contentType: 'application/json', data: jsonData}); } }; App.enterEditMode = function enterEditMode(parts, level, cursorPos) { if (App.editingElement) { $(App.editingElement).blur(); App.editingElement = null; } var editablePart = $('<textarea class="wiki-edit"></textarea>').get(0); var originalMarkup = App.getMarkup(parts); $(editablePart).attr("value", originalMarkup); function setScrollHeight() { $(this).height(this.scrollHeight); } function exitEditMode() { var markup = $(this).attr("value"); $(this).replaceWith(App.createParts(markup)); if (markup != originalMarkup) { App.saveChanges(true); } } function editSiblings(aEvt) { if (!aEvt.shiftKey || level == 0) return; aEvt.preventDefault(); var prevMarkup = App.getMarkup($(this).prevAll()); var cursorPos = (prevMarkup.length + App.PART_SEPARATOR.length + this.selectionStart); var allSiblings = this.parentNode.childNodes; exitEditMode.apply(this); App.enterEditMode(allSiblings, level-1, cursorPos); } $(editablePart).blur(exitEditMode); $(editablePart).mousedown(editSiblings); $(editablePart).keyup(setScrollHeight); $(parts).filter(":not(:first)").remove(); $(parts).replaceWith(editablePart); setScrollHeight.apply(editablePart); if (typeof(cursorPos) != "undefined") { editablePart.selectionStart = cursorPos; editablePart.selectionEnd = cursorPos; } App.editingElement = editablePart; $(editablePart).focus(); }; App.createPart = function createPart(markup) { var partDiv = $('<div class="part"></div>'); var markupDiv = $('<div class="creole-markup"></div>'); markupDiv.text(markup); App.creole.parse(partDiv.get(0), markup); partDiv.mousedown(App.eventHandlers.editPart); partDiv.append(markupDiv); return partDiv.get(0); }; App.createParts = function createParts(text) { var parts = []; var partsMarkup = text.split(App.PART_SEPARATOR); jQuery.each( partsMarkup, function(i) { var partMarkup = this.toString(); if (partMarkup) parts.push(App.createPart(partMarkup)); } ); return parts; }; App.eventHandlers.onLoad = function onLoad() { App.creole = new Parse.Simple.Creole( {interwiki: { WikiCreole: 'http://www.wikicreole.org/wiki/', Wikipedia: 'http://en.wikipedia.org/wiki/' }, linkFormat: '' }); function onStatus(status) { App.latestRemoteChangeset = status.max_changeset; jQuery.get("/" + status.max_changeset, {}, function(obj) { var text = obj.content; $("#content").append(App.createParts(text)); App.saveChanges(false); }, "json"); } jQuery.get('/status', {}, onStatus, "json"); }; $(window).ready(App.eventHandlers.onLoad);