fixed merge confilcts in pad.html

This commit is contained in:
John McLear 2011-08-01 13:20:05 +01:00
commit 9911fb95b9
54 changed files with 612 additions and 263 deletions

View File

@ -34,9 +34,8 @@ The Node.js version of your Linux repository might be too old/new. Please compil
2. Install npm `curl http://npmjs.org/install.sh | sh` 2. Install npm `curl http://npmjs.org/install.sh | sh`
3. Ensure you have installed the sqlite develob libraries, gzip and git `apt-get install libsqlite3-dev gzip git-core` 3. Ensure you have installed the sqlite develob libraries, gzip and git `apt-get install libsqlite3-dev gzip git-core`
4. Clone the git repository `git clone 'git://github.com/Pita/etherpad-lite.git'` 4. Clone the git repository `git clone 'git://github.com/Pita/etherpad-lite.git'`
5. Install the dependencies `cd etherpad-lite && npm install` 5. Start it with `bin/run.sh` (the first run will install all dependencies)
6. Start it with `bin/run.sh` 6. Open your web browser and visit <http://localhost:9001>
7. Open your web browser and visit <http://localhost:9001>
# Next Steps # Next Steps
You can modify the settings in the file settings.json You can modify the settings in the file settings.json

30
bin/debugRun.sh Executable file
View File

@ -0,0 +1,30 @@
#!/bin/sh
#Move to the folder where ep-lite is installed
FOLDER=$(dirname $(readlink -f $0))
cd $FOLDER
#Was this script started in the bin folder? if yes move out
if [ -d "../bin" ]; then
cd "../"
fi
#prepare the enviroment
bin/installDeps.sh || exit 1
hash node-inspector > /dev/null 2>&1 || {
echo "You need to install node-inspector to run the tests!" >&2
echo "You can install it with npm" >&2
echo "Run: npm install -g node-inspector" >&2
exit 1
}
node-inspector &
echo "If you new to node-inspector, take a look at this video: http://youtu.be/AOnK3NVnxL8"
cd "node"
node --debug server.js
#kill node-inspector before ending
kill $!

View File

@ -1,15 +1,20 @@
#!/bin/bash #!/bin/sh
#Move to the folder where ep-lite is installed
FOLDER=$(dirname $(readlink -f $0))
cd $FOLDER
#Was this script started in the bin folder? if yes move out
if [ -d "../bin" ]; then if [ -d "../bin" ]; then
cd "../" cd "../"
fi fi
type -P node &>/dev/null || { hash node > /dev/null 2>&1 || {
echo "You need to install node!" >&2 echo "You need to install node!" >&2
exit 1 exit 1
} }
type -P doc.md &>/dev/null || { hash doc.md > /dev/null 2>&1 || {
echo "You need to install doc.md! npm install -g doc.md" >&2 echo "You need to install doc.md! npm install -g doc.md" >&2
exit 1 exit 1
} }

71
bin/installDeps.sh Executable file
View File

@ -0,0 +1,71 @@
#!/bin/sh
#Move to the folder where ep-lite is installed
FOLDER=$(dirname $(readlink -f $0))
cd $FOLDER
#Was this script started in the bin folder? if yes move out
if [ -d "../bin" ]; then
cd "../"
fi
#Is wget installed?
hash wget > /dev/null 2>&1 || {
echo "Please install wget" >&2
exit 1
}
#Is node installed?
hash node > /dev/null 2>&1 || {
echo "Please install node.js ( http://nodesjs.org )" >&2
exit 1
}
#Is npm installed?
hash npm > /dev/null 2>&1 || {
echo "Please install npm ( http://npmjs.org )" >&2
exit 1
}
#Does a settings.json exist? if no copy the template
if [ ! -f "settings.json" ]; then
echo "Copy the settings template to settings.json..."
cp -v settings.json.template settings.json || exit 1
fi
echo "Ensure that all dependencies are up to date..."
npm install || exit 1
echo "Ensure jQuery is downloaded and up to date..."
DOWNLOAD_JQUERY="true"
NEEDED_VERSION="1.6.2"
if [ -f "static/js/jquery.min.js" ]; then
VERSION=$(cat static/js/jquery.min.js | head -n 2 | tail -n 1 | grep -o "v[0-9]*\.[0-9]*\.[0-9]*");
if [ ${VERSION#v} = $NEEDED_VERSION ]; then
DOWNLOAD_JQUERY="false"
fi
fi
if [ $DOWNLOAD_JQUERY = "true" ]; then
wget -O static/js/jquery.min.js http://code.jquery.com/jquery-$NEEDED_VERSION.min.js || exit 1
fi
#Remove all minified data to force node creating it new
echo "Clear minfified cache..."
rm -f var/minified*
echo "ensure custom css/js files are created..."
for f in "index" "pad" "timeslider"
do
if [ ! -f "static/custom/$f.js" ]; then
cp -v "static/custom/js.template" "static/custom/$f.js" || exit 1
fi
if [ ! -f "static/custom/$f.css" ]; then
cp -v "static/custom/css.template" "static/custom/$f.css" || exit 1
fi
done
exit 0

View File

@ -1,4 +1,4 @@
#!/bin/bash #!/bin/sh
#Move to the folder where ep-lite is installed #Move to the folder where ep-lite is installed
FOLDER=$(dirname $(readlink -f $0)) FOLDER=$(dirname $(readlink -f $0))
@ -10,51 +10,14 @@ if [ -d "../bin" ]; then
fi fi
#Stop the script if its started as root #Stop the script if its started as root
if [[ $EUID -eq 0 ]]; then if [ "$(id -u)" -eq 0 ]; then
echo "You shouldn't start Etherpad-Lite as root!" 1>&2 echo "You shouldn't start Etherpad-Lite as root!" 1>&2
echo "Use authbind if you want to use a port lower than 1024 -> http://en.wikipedia.org/wiki/Authbind" 1>&2 echo "Use authbind if you want to use a port lower than 1024 -> http://en.wikipedia.org/wiki/Authbind" 1>&2
exit 1 exit 1
fi fi
#Is node installed? #prepare the enviroment
type -P node &>/dev/null || { bin/installDeps.sh || exit 1
echo "You need to install node to run Etherpad-Lite!" >&2
exit 1
}
#Is npm installed?
type -P npm &>/dev/null || {
echo "You need to install npm to run Etherpad-Lite!" >&2
exit 1
}
#Does a settings.json exist? if no copy the template
if [ ! -f "settings.json" ]; then
echo "Copy the settings template to settings.json..."
cp -v settings.json.template settings.json
fi
echo "Ensure that all dependencies are up to date..."
npm install
echo "Ensure jQuery is downloaded and up to date..."
DOWNLOAD_JQUERY="true"
NEEDED_VERSION="1.6.2"
if [ -f "static/js/jquery.min.js" ]; then
VERSION=$(cat static/js/jquery.min.js | head -n 2 | tail -n 1 | grep -o "v[0-9]*\.[0-9]*\.[0-9]*");
if [[ ${VERSION:1} = $NEEDED_VERSION ]]; then
DOWNLOAD_JQUERY="false"
fi
fi
if [[ $DOWNLOAD_JQUERY = "true" ]]; then
wget -O static/js/jquery.min.js http://code.jquery.com/jquery-$NEEDED_VERSION.min.js
fi
#Remove all minified data to force node creating it new
echo "Clear minfified cache..."
rm var/minified* 2> /dev/null
#Move to the node folder and start #Move to the node folder and start
echo "start..." echo "start..."

View File

@ -1,19 +0,0 @@
#!/bin/bash
type -P node-inspector &>/dev/null || {
echo "You need to install node-inspector to run the tests!" >&2
echo "You can install it with npm" >&2
echo "Run: npm install node-inspector" >&2
exit 1
}
node-inspector &
echo "If you new to node-inspector, take a look at this video: http://youtu.be/AOnK3NVnxL8"
if [ -d "../bin" ]; then
cd "../"
fi
cd "node"
node --debug server.js

View File

@ -1,14 +0,0 @@
#!/bin/bash
type -P nodeunit &>/dev/null || {
echo "You need to install Nodeunit to run the tests!" >&2
echo "You can install it with npm" >&2
echo "Run: npm install nodeunit" >&2
exit 1
}
if [ -d "../bin" ]; then
cd "../"
fi
nodeunit tests

View File

@ -1,4 +1,4 @@
#!/bin/bash #!/bin/sh
#This script ensures that ep-lite is automatically restarting after an error happens #This script ensures that ep-lite is automatically restarting after an error happens
@ -49,12 +49,12 @@ do
bin/run.sh >>$1 2>>$1 bin/run.sh >>$1 2>>$1
#Send email #Send email
if [ $ERROR_HANDLING == 1 ]; then if [ $ERROR_HANDLING = 1 ]; then
TIME_NOW=$(date +%s) TIME_NOW=$(date +%s)
TIME_SINCE_LAST_SEND=$(($TIME_NOW - $LAST_EMAIL_SEND)) TIME_SINCE_LAST_SEND=$(($TIME_NOW - $LAST_EMAIL_SEND))
if [ $TIME_SINCE_LAST_SEND -gt $TIME_BETWEEN_EMAILS ]; then if [ $TIME_SINCE_LAST_SEND -gt $TIME_BETWEEN_EMAILS ]; then
echo -e "Server was restared at: $(date)\nThe last 50 lines of the log before the error happens:\n $(tail -n 50 $1)" | mail -s "Pad Server was restarted" $EMAIL_ADDRESS printf "Server was restared at: $(date)\nThe last 50 lines of the log before the error happens:\n $(tail -n 50 $1)" | mail -s "Pad Server was restarted" $EMAIL_ADDRESS
LAST_EMAIL_SEND=$TIME_NOW LAST_EMAIL_SEND=$TIME_NOW
fi fi

View File

@ -1,10 +1,17 @@
# AuthorManager # db/AuthorMana
`require("./AuthorManager");` `require("./db/AuthorManager");`
The AuthorManager controlls all information about the Pad authors The AuthorManager controlls all information about the Pad authors
## Functions ## Functions
- - -
### getAuthor (author, callback)
Internal function that creates the database entry for an author
* **author** *(String)* The id of the author
* **callback** *(Function)* callback(err, authorObj)
- - - - - -
### getAuthor4Token (token, callback) ### getAuthor4Token (token, callback)
Returns the Author Id for a token. If the token is unkown, Returns the Author Id for a token. If the token is unkown,

View File

@ -1,5 +1,5 @@
# db # db
`require("./db");` `require("./db/DB");`
The DB Module provides a database initalized with the settings The DB Module provides a database initalized with the settings
provided by the settings module provided by the settings module

View File

@ -1,5 +1,5 @@
# Mod # db/
`require("./Models/Pad");` `require("./db/Pad");`
The pad object, defined with joose The pad object, defined with joose

View File

@ -1,5 +1,5 @@
# PadManager # db/PadMana
`require("./PadManager");` `require("./db/PadManager");`
The Pad Manager is a Factory for pad Objects The Pad Manager is a Factory for pad Objects

View File

@ -0,0 +1,21 @@
# db/ReadOnlyMana
`require("./db/ReadOnlyManager");`
The ReadOnlyManager manages the database and rendering releated to read only pads
## Functions
- - -
### getPadId (readOnlyId, callback)
returns a the padId for a read only id
* **readOnlyId** *(String)* read only id
* **callback** *No description*
- - -
### getReadOnlyId (padId, callback)
returns a read only id for a pad
* **padId** *(String)* the id of the pad
* **callback** *No description*

View File

@ -0,0 +1,16 @@
# handler/Expor
`require("./handler/ExportHandler");`
Handles the export requests
## Functions
- - -
### doExport (req, res, padId, type)
do a requested export
* **req** *No description*
* **res** *No description*
* **padId** *No description*
* **type** *No description*

View File

@ -0,0 +1,15 @@
# handler/Impor
`require("./handler/ImportHandler");`
Handles the import requests
## Functions
- - -
### doImport (req, res, padId)
do a requested import
* **req** *No description*
* **res** *No description*
* **padId** *No description*

View File

@ -0,0 +1,38 @@
# handler/PadMessag
`require("./handler/PadMessageHandler");`
The MessageHandler handles all Messages that comes from Socket.IO and controls the sessions
## Functions
- - -
### handleConnect (client)
Handles the connection of a new user
* **client** the new client
- - -
### handleDisconnect (client)
Handles the disconnection of a user
* **client** the client that leaves
- - -
### handleMessage (client, message)
Handles a message from a user
* **client** the client that send this message
* **message** the message from the client
- - -
### setSocketIO (socket_io)
A associative array that translates a session to a pad
* **socket_io** The Socket
- - -
### updatePadClients (pad, callback)
* **pad** *No description*
* **callback** *No description*

View File

@ -0,0 +1,23 @@
# handler/Socket
`require("./handler/SocketIORouter");`
This is the Socket.IO Router. It routes the Messages between the
components of the Server. The components are at the moment: pad and timeslider
## Functions
- - -
### addComponent (moduleName, module)
Saves all components
key is the component name
value is the component module
* **moduleName** *No description*
* **module** *No description*
- - -
### setSocketIO (_socket)
sets the socket.io and adds event functions for routing
* **_socket** *No description*

View File

@ -1,5 +1,5 @@
# MessageHandler # handler/TimesliderMessag
`require("./MessageHandler");` `require("./handler/TimesliderMessageHandler");`
The MessageHandler handles all Messages that comes from Socket.IO and controls the sessions The MessageHandler handles all Messages that comes from Socket.IO and controls the sessions
@ -26,7 +26,7 @@ Handles a message from a user
- - - - - -
### setSocketIO (socket_io) ### setSocketIO (socket_io)
A associative array that translates a session to a pad Saves the Socket class we need to send and recieve data from the client
* **socket_io** The Socket * **socket_io** The Socket

View File

@ -0,0 +1,15 @@
# utils/A
`require("./utils/Abiword");`
Controls the communication with the Abiword application
## Functions
- - -
### convertFile (srcFile, destFile, type, callback)
* **srcFile** *No description*
* **destFile** *No description*
* **type** *No description*
* **callback** *No description*

View File

@ -1,5 +1,5 @@
# AttributePoolFactory # utils/AttributePoolF
`require("./AttributePoolFactory");` `require("./utils/AttributePoolFactory");`
This code represents the Attribute Pool Object of the original Etherpad. This code represents the Attribute Pool Object of the original Etherpad.
90% of the code is still like in the original Etherpad 90% of the code is still like in the original Etherpad

View File

@ -1,5 +1,5 @@
# Changeset # utils/Cha
`require("./Changeset");` `require("./utils/Changeset");`
## Functions ## Functions

View File

@ -0,0 +1,24 @@
# utils/Expo
`require("./utils/ExportHtml");`
Copyright 2009 Google Inc.
* Licensed 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.
## Functions
- - -
### getPadHTMLDocument (padId, revNum, noDocType, callback)
* **padId** *No description*
* **revNum** *No description*
* **noDocType** *No description*
* **callback** *No description*

View File

@ -1,5 +1,5 @@
# minify # utils/
`require("./minify");` `require("./utils/Minify");`
This Module manages all /minified/* requests. It controls the This Module manages all /minified/* requests. It controls the
minification && compression of Javascript and CSS. minification && compression of Javascript and CSS.
@ -7,9 +7,10 @@ minification && compression of Javascript and CSS.
## Functions ## Functions
- - - - - -
### padJS (req, res) ### minifyJS (req, res, jsFilename)
Answers a http request for the pad javascript creates the minifed javascript for the given minified name
* **req** the Express request * **req** the Express request
* **res** the Express response * **res** the Express response
* **jsFilename** *No description*

View File

@ -1,11 +1,15 @@
# settings # utils/Se
`require("./settings");` `require("./utils/Settings");`
The Settings Modul reads the settings out of settings.json and provides The Settings Modul reads the settings out of settings.json and provides
this information to the other modules this information to the other modules
##Variables ##Variables
- - -
### abiword
The path of the abiword executable
- - - - - -
### dbSettings ### dbSettings
This setting is passed with dbType to ueberDB to set up the database This setting is passed with dbType to ueberDB to set up the database
@ -18,6 +22,10 @@ This setting is passed with dbType to ueberDB to set up the database
### defaultPadText ### defaultPadText
The default Text of a new pad The default Text of a new pad
- - -
### ip
The IP ep-lite should listen to
- - - - - -
### logHTTP ### logHTTP
A flag that shows if http requests should be loged to stdout A flag that shows if http requests should be loged to stdout

13
node/README.md Normal file
View File

@ -0,0 +1,13 @@
# About the folder structure
* **db** - all modules that are accesing the data structure and are communicating directly to the database
* **handler** - all modules that responds directly to requests/messages of the browser
* **utils** - helper modules
# Module name conventions
Module file names starts with a capital letter and uses camelCase
# Where does it start?
server.js is started directly

View File

@ -18,7 +18,7 @@
* limitations under the License. * limitations under the License.
*/ */
var db = require("./db").db; var db = require("./DB").db;
var async = require("async"); var async = require("async");
/** /**
@ -32,39 +32,79 @@ exports.getAuthor4Token = function (token, callback)
{ {
var author; var author;
async.waterfall([ async.series([
//try to get the author for this token //try to get the author for this token
function(callback) function(callback)
{ {
db.get("token2author:" + token, callback); db.get("token2author:" + token, function (err, _author)
{
author = _author;
callback(err);
});
}, },
function(value, callback) function(callback)
{ {
//there is no author with this token, so create one //there is no author with this token, so create one
if(value == null) if(author == null)
{ {
//create the new author name createAuthor(token, function(err, _author)
author = "g." + _randomString(16); {
author = _author;
//set the token2author db entry callback(err);
db.set("token2author:" + token, author); });
//set the globalAuthors db entry
var authorObj = {colorId : Math.floor(Math.random()*32), name: null, timestamp: new Date().getTime()};
db.set("globalAuthor:" + author, authorObj);
callback(null);
} }
//there is a author with this token //there is a author with this token
else else
{ {
author = value; //check if there is also an author object for this token, if not, create one
db.get("globalAuthor:" + author, function(err, authorObject)
//update the author time {
db.setSub("globalAuthor:" + author, ["timestamp"], new Date().getTime()); if(authorObject == null)
{
callback(null); createAuthor(token, function(err, _author)
{
author = _author;
callback(err);
});
} }
//the author exists, update the timestamp of this author
else
{
db.setSub("globalAuthor:" + author, ["timestamp"], new Date().getTime());
callback();
}
});
}
}
], function(err)
{
callback(err, author);
});
}
/**
* Internal function that creates the database entry for an author
* @param {String} token The token
*/
function createAuthor (token, callback)
{
//create the new author name
var author = "g." + _randomString(16);
//create the globalAuthors db entry
var authorObj = {colorId : Math.floor(Math.random()*32), name: null, timestamp: new Date().getTime()};
//we do this in series to ensure this db entries are written in the correct order
async.series([
//set the global author db entry
function(callback)
{
db.set("globalAuthor:" + author, authorObj, callback);
},
//set the token2author db entry
function(callback)
{
db.set("token2author:" + token, author, callback);
} }
], function(err) ], function(err)
{ {

View File

@ -20,7 +20,7 @@
*/ */
var ueberDB = require("ueberDB"); var ueberDB = require("ueberDB");
var settings = require("./settings"); var settings = require("../utils/Settings");
//set database settings //set database settings
var db = new ueberDB.database(settings.dbType, settings.dbSettings); var db = new ueberDB.database(settings.dbType, settings.dbSettings);

View File

@ -2,12 +2,12 @@
* The pad object, defined with joose * The pad object, defined with joose
*/ */
var Changeset = require("../Changeset"); var Changeset = require("../utils/Changeset");
var AttributePoolFactory = require("../AttributePoolFactory"); var AttributePoolFactory = require("../utils/AttributePoolFactory");
var db = require("../db").db; var db = require("./DB").db;
var async = require("async"); var async = require("async");
var settings = require('../settings'); var settings = require('../utils/Settings');
var authorManager = require("../AuthorManager"); var authorManager = require("./AuthorManager");
/** /**
* Copied from the Etherpad source code. It converts Windows line breaks to Unix line breaks and convert Tabs to spaces * Copied from the Etherpad source code. It converts Windows line breaks to Unix line breaks and convert Tabs to spaces
@ -214,7 +214,7 @@ Class('Pad', {
db.setSub("pad:"+this.id, ["chatHead"], this.chatHead); db.setSub("pad:"+this.id, ["chatHead"], this.chatHead);
}, },
getChatMessage: function(entryNum, withName, callback) getChatMessage: function(entryNum, callback)
{ {
var _this = this; var _this = this;
var entry; var entry;
@ -232,8 +232,8 @@ Class('Pad', {
//add the authorName //add the authorName
function(callback) function(callback)
{ {
//skip if we don't need the authorName //this chat message doesn't exist, return null
if(!withName) if(entry == null)
{ {
callback(); callback();
return; return;
@ -287,14 +287,26 @@ Class('Pad', {
var entries = []; var entries = [];
async.forEach(neededEntries, function(entryObject, callback) async.forEach(neededEntries, function(entryObject, callback)
{ {
_this.getChatMessage(entryObject.entryNum, true, function(err, entry) _this.getChatMessage(entryObject.entryNum, function(err, entry)
{ {
entries[entryObject.order] = entry; entries[entryObject.order] = entry;
callback(err); callback(err);
}); });
}, function(err) }, function(err)
{ {
callback(err, entries); //sort out broken chat entries
//it looks like in happend in the past that the chat head was
//incremented, but the chat message wasn't added
var cleanedEntries = [];
for(var i=0;i<entries.length;i++)
{
if(entries[i]!=null)
cleanedEntries.push(entries[i]);
else
console.warn("WARNING: Found broken chat entry in pad " + _this.id);
}
callback(err, cleanedEntries);
}); });
}, },

View File

@ -18,7 +18,7 @@
* limitations under the License. * limitations under the License.
*/ */
var Changeset = require("./Models/Pad"); require("../db/Pad");
/** /**
* A Array with all known Pads * A Array with all known Pads

View File

@ -18,7 +18,7 @@
* limitations under the License. * limitations under the License.
*/ */
var db = require("./db").db; var db = require("./DB").db;
var async = require("async"); var async = require("async");
/** /**

View File

@ -18,15 +18,15 @@
* limitations under the License. * limitations under the License.
*/ */
var exporthtml = require("./exporters/exporthtml"); var exporthtml = require("../utils/ExportHtml");
var padManager = require("./PadManager"); var padManager = require("../db/PadManager");
var async = require("async"); var async = require("async");
var fs = require("fs"); var fs = require("fs");
var settings = require('./settings'); var settings = require('../utils/Settings');
//load abiword only if its enabled //load abiword only if its enabled
if(settings.abiword != null) if(settings.abiword != null)
var abiword = require("./Abiword"); var abiword = require("../utils/Abiword");
/** /**
* do a requested export * do a requested export

View File

@ -18,16 +18,16 @@
* limitations under the License. * limitations under the License.
*/ */
var padManager = require("./PadManager"); var padManager = require("../db/PadManager");
var padMessageHandler = require("./PadMessageHandler"); var padMessageHandler = require("./PadMessageHandler");
var async = require("async"); var async = require("async");
var fs = require("fs"); var fs = require("fs");
var settings = require('./settings'); var settings = require('../utils/Settings');
var formidable = require('formidable'); var formidable = require('formidable');
//load abiword only if its enabled //load abiword only if its enabled
if(settings.abiword != null) if(settings.abiword != null)
var abiword = require("./Abiword"); var abiword = require("../utils/Abiword");
/** /**
* do a requested import * do a requested import

View File

@ -19,11 +19,12 @@
*/ */
var async = require("async"); var async = require("async");
var padManager = require("./PadManager"); var padManager = require("../db/PadManager");
var Changeset = require("./Changeset"); var Changeset = require("../utils/Changeset");
var AttributePoolFactory = require("./AttributePoolFactory"); var AttributePoolFactory = require("../utils/AttributePoolFactory");
var authorManager = require("./AuthorManager"); var authorManager = require("../db/AuthorManager");
var readOnlyManager = require("./ReadOnlyManager"); var readOnlyManager = require("../db/ReadOnlyManager");
var settings = require('../utils/Settings');
/** /**
* A associative array that translates a session to a pad * A associative array that translates a session to a pad
@ -84,7 +85,7 @@ exports.handleDisconnect = function(client)
var sessionPad=session2pad[client.id]; var sessionPad=session2pad[client.id];
//if this connection was already etablished with a handshake, send a disconnect message to the others //if this connection was already etablished with a handshake, send a disconnect message to the others
if(sessioninfos[client.id].author) if(sessioninfos[client.id] && sessioninfos[client.id].author)
{ {
var author = sessioninfos[client.id].author; var author = sessioninfos[client.id].author;
@ -318,11 +319,6 @@ function handleUserInfoUpdate(client, message)
} }
} }
function errlog(name, value)
{
console.error(name+"=" + JSON.stringify(value));
}
/** /**
* Handles a USERINFO_UPDATE, that means that a user have changed his color or name. Anyway, we get both informations * Handles a USERINFO_UPDATE, that means that a user have changed his color or name. Anyway, we get both informations
* This Method is nearly 90% copied out of the Etherpad Source Code. So I can't tell you what happens here exactly * This Method is nearly 90% copied out of the Etherpad Source Code. So I can't tell you what happens here exactly
@ -414,9 +410,13 @@ function handleUserChanges(client, message)
function (callback) function (callback)
{ {
var prevText = pad.text(); var prevText = pad.text();
if (Changeset.oldLen(changeset) != prevText.length) {
throw "Can't apply USER_CHANGES "+changeset+" with oldLen " if (Changeset.oldLen(changeset) != prevText.length)
+ Changeset.oldLen(changeset) + " to document of length " + prevText.length; {
console.warn("Can't apply USER_CHANGES "+changeset+" with oldLen " + Changeset.oldLen(changeset) + " to document of length " + prevText.length);
client.json.send({disconnect:"badChangeset"});
callback();
return;
} }
var thisAuthor = sessioninfos[client.id].author; var thisAuthor = sessioninfos[client.id].author;
@ -644,6 +644,7 @@ function handleClientReady(client, message)
{ {
authorManager.getAuthor(authorId, function(err, author) authorManager.getAuthor(authorId, function(err, author)
{ {
delete author.timestamp;
historicalAuthorData[authorId] = author; historicalAuthorData[authorId] = author;
callback(err); callback(err);
}); });
@ -705,7 +706,7 @@ function handleClientReady(client, message)
}, },
"collab_client_vars": { "collab_client_vars": {
"initialAttributedText": atext, "initialAttributedText": atext,
"clientIp": (client.request && client.request.connection) ? client.request.connection.remoteAddress : "127.0.0.1", "clientIp": "127.0.0.1",
//"clientAgent": "Anonymous Agent", //"clientAgent": "Anonymous Agent",
"padId": message.padId, "padId": message.padId,
"historicalAuthorData": historicalAuthorData, "historicalAuthorData": historicalAuthorData,
@ -714,7 +715,7 @@ function handleClientReady(client, message)
"globalPadId": message.padId "globalPadId": message.padId
}, },
"colorPalette": ["#ffc7c7", "#fff1c7", "#e3ffc7", "#c7ffd5", "#c7ffff", "#c7d5ff", "#e3c7ff", "#ffc7f1", "#ff8f8f", "#ffe38f", "#c7ff8f", "#8fffab", "#8fffff", "#8fabff", "#c78fff", "#ff8fe3", "#d97979", "#d9c179", "#a9d979", "#79d991", "#79d9d9", "#7991d9", "#a979d9", "#d979c1", "#d9a9a9", "#d9cda9", "#c1d9a9", "#a9d9b5", "#a9d9d9", "#a9b5d9", "#c1a9d9", "#d9a9cd"], "colorPalette": ["#ffc7c7", "#fff1c7", "#e3ffc7", "#c7ffd5", "#c7ffff", "#c7d5ff", "#e3c7ff", "#ffc7f1", "#ff8f8f", "#ffe38f", "#c7ff8f", "#8fffab", "#8fffff", "#8fabff", "#c78fff", "#ff8fe3", "#d97979", "#d9c179", "#a9d979", "#79d991", "#79d9d9", "#7991d9", "#a979d9", "#d979c1", "#d9a9a9", "#d9cda9", "#c1d9a9", "#a9d9b5", "#a9d9d9", "#a9b5d9", "#c1a9d9", "#d9a9cd"],
"clientIp": (client.request && client.request.connection) ? client.request.connection.remoteAddress : "127.0.0.1", "clientIp": "127.0.0.1",
"userIsGuest": true, "userIsGuest": true,
"userColor": authorColorId, "userColor": authorColorId,
"padId": message.padId, "padId": message.padId,
@ -731,6 +732,7 @@ function handleClientReady(client, message)
"fullWidth": false, "fullWidth": false,
"hideSidebar": false "hideSidebar": false
}, },
"abiwordAvailable": settings.abiword != null,
"hooks": {} "hooks": {}
} }

View File

@ -19,6 +19,9 @@
* limitations under the License. * limitations under the License.
*/ */
var log4js = require('log4js');
var messageLogger = log4js.getLogger("message");
/** /**
* Saves all components * Saves all components
* key is the component name * key is the component name
@ -54,7 +57,7 @@ exports.setSocketIO = function(_socket)
client._send = client.send; client._send = client.send;
client.send = function(message) client.send = function(message)
{ {
console.log(new Date().toUTCString() + ": message to " + client.id + ": " + JSON.stringify(message)); messageLogger.info("to " + client.id + ": " + JSON.stringify(message));
client._send(message); client._send(message);
} }
@ -68,14 +71,14 @@ exports.setSocketIO = function(_socket)
{ {
if(message.protocolVersion && message.protocolVersion != 2) if(message.protocolVersion && message.protocolVersion != 2)
{ {
console.error("Protocolversion header is not correct:" + JSON.stringify(message)); messageLogger.warn("Protocolversion header is not correct:" + JSON.stringify(message));
return; return;
} }
//route this message to the correct component, if possible //route this message to the correct component, if possible
if(message.component && components[message.component]) if(message.component && components[message.component])
{ {
console.log(new Date().toUTCString() + ": message from " + client.id + ": " + JSON.stringify(message)); messageLogger.info("from " + client.id + ": " + JSON.stringify(message));
//check if component is registered in the components array //check if component is registered in the components array
if(components[message.component]) if(components[message.component])
@ -85,7 +88,7 @@ exports.setSocketIO = function(_socket)
} }
else else
{ {
console.error("Can't route the message:" + JSON.stringify(message)); messageLogger.error("Can't route the message:" + JSON.stringify(message));
} }
}); });

View File

@ -19,10 +19,10 @@
*/ */
var async = require("async"); var async = require("async");
var padManager = require("./PadManager"); var padManager = require("../db/PadManager");
var Changeset = require("./Changeset"); var Changeset = require("../utils/Changeset");
var AttributePoolFactory = require("./AttributePoolFactory"); var AttributePoolFactory = require("../utils/AttributePoolFactory");
var authorManager = require("./AuthorManager"); var authorManager = require("../db/AuthorManager");
/** /**
* Saves the Socket class we need to send and recieve data from the client * Saves the Socket class we need to send and recieve data from the client

View File

@ -24,14 +24,15 @@ require('joose');
var socketio = require('socket.io'); var socketio = require('socket.io');
var fs = require('fs'); var fs = require('fs');
var settings = require('./settings'); var settings = require('./utils/Settings');
var socketIORouter = require("./SocketIORouter"); var socketIORouter = require("./handler/SocketIORouter");
var db = require('./db'); var db = require('./db/DB');
var async = require('async'); var async = require('async');
var express = require('express'); var express = require('express');
var path = require('path'); var path = require('path');
var minify = require('./minify'); var minify = require('./utils/Minify');
var formidable = require('formidable'); var formidable = require('formidable');
var log4js = require('log4js');
var exportHandler; var exportHandler;
var importHandler; var importHandler;
var exporthtml; var exporthtml;
@ -48,7 +49,7 @@ try
} }
catch(e) catch(e)
{ {
console.error("Can't get git version for server header\n" + e.message) console.warn("Can't get git version for server header\n" + e.message)
} }
var serverName = "Etherpad-Lite " + version + " (http://j.mp/ep-lite)"; var serverName = "Etherpad-Lite " + version + " (http://j.mp/ep-lite)";
@ -69,14 +70,17 @@ async.waterfall([
var app = express.createServer(); var app = express.createServer();
//load modules that needs a initalized db //load modules that needs a initalized db
readOnlyManager = require("./ReadOnlyManager"); readOnlyManager = require("./db/ReadOnlyManager");
exporthtml = require("./exporters/exporthtml"); exporthtml = require("./utils/ExportHtml");
exportHandler = require('./ExportHandler'); exportHandler = require('./handler/ExportHandler');
importHandler = require('./ImportHandler'); importHandler = require('./handler/ImportHandler');
//set logging //install logging
if(settings.logHTTP) var httpLogger = log4js.getLogger("http");
app.use(express.logger({ format: ':date: :status, :method :url' })); app.configure(function()
{
app.use(log4js.connectLogger(httpLogger, { level: log4js.levels.INFO, format: ':status, :method :url'}));
});
//serve static files //serve static files
app.get('/static/*', function(req, res) app.get('/static/*', function(req, res)
@ -87,19 +91,19 @@ async.waterfall([
}); });
//serve minified files //serve minified files
app.get('/minified/:id', function(req, res) app.get('/minified/:id', function(req, res, next)
{ {
res.header("Server", serverName); res.header("Server", serverName);
var id = req.params.id; var id = req.params.id;
if(id == "pad.js") if(id == "pad.js" || id == "timeslider.js")
{ {
minify.padJS(req,res); minify.minifyJS(req,res,id);
} }
else else
{ {
res.send('404 - Not Found', 404); next();
} }
}); });
@ -224,7 +228,7 @@ async.waterfall([
{ {
new formidable.IncomingForm().parse(req, function(err, fields, files) new formidable.IncomingForm().parse(req, function(err, fields, files)
{ {
console.log(new Date().toUTCString() + ": DIAGNOSTIC-INFO: " + fields.diagnosticInfo); console.log("DIAGNOSTIC-INFO: " + fields.diagnosticInfo);
res.end("OK"); res.end("OK");
}); });
}); });
@ -254,8 +258,8 @@ async.waterfall([
}); });
//let the server listen //let the server listen
app.listen(settings.port); app.listen(settings.port, settings.ip);
console.log("Server is listening at port " + settings.port); console.log("Server is listening at " + settings.ip + ":" + settings.port);
//init socket.io and redirect all requests to the MessageHandler //init socket.io and redirect all requests to the MessageHandler
var io = socketio.listen(app); var io = socketio.listen(app);
@ -264,11 +268,33 @@ async.waterfall([
//we should remove this when the new socket.io version is more stable //we should remove this when the new socket.io version is more stable
io.set('transports', ['xhr-polling']); io.set('transports', ['xhr-polling']);
//reduce the log level var socketIOLogger = log4js.getLogger("socket.io");
io.set('log level', 2); io.set('logger', {
debug: function (str)
{
//supress debug messages
//socketIOLogger.debug(str);
},
info: function (str)
{
socketIOLogger.info(str);
},
warn: function (str)
{
socketIOLogger.warn(str);
},
error: function (str)
{
socketIOLogger.error(str);
},
});
var padMessageHandler = require("./PadMessageHandler"); //minify socket.io javascript
var timesliderMessageHandler = require("./TimesliderMessageHandler"); if(settings.minify)
io.enable('browser client minification');
var padMessageHandler = require("./handler/PadMessageHandler");
var timesliderMessageHandler = require("./handler/TimesliderMessageHandler");
//Initalize the Socket.IO Router //Initalize the Socket.IO Router
socketIORouter.setSocketIO(io); socketIORouter.setSocketIO(io);

View File

@ -21,7 +21,7 @@
var util = require('util'); var util = require('util');
var spawn = require('child_process').spawn; var spawn = require('child_process').spawn;
var async = require("async"); var async = require("async");
var settings = require("./settings"); var settings = require("./Settings");
//Queue with the converts we have to do //Queue with the converts we have to do
var queue = async.queue(doConvertTask, 1); var queue = async.queue(doConvertTask, 1);

View File

@ -14,8 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
var async = require("async"); var async = require("async");
var Changeset = require("../Changeset"); var Changeset = require("./Changeset");
var padManager = require("../PadManager"); var padManager = require("../db/PadManager");
function getPadPlainText(pad, revNum) { function getPadPlainText(pad, revNum) {

View File

@ -19,7 +19,7 @@
* limitations under the License. * limitations under the License.
*/ */
var settings = require('./settings'); var settings = require('./Settings');
var async = require('async'); var async = require('async');
var fs = require('fs'); var fs = require('fs');
var cleanCSS = require('clean-css'); var cleanCSS = require('clean-css');
@ -28,18 +28,34 @@ var pro = require("uglify-js").uglify;
var path = require('path'); var path = require('path');
var Buffer = require('buffer').Buffer; var Buffer = require('buffer').Buffer;
var gzip = require('gzip'); var gzip = require('gzip');
var server = require('./server'); var server = require('../server');
var padJS = ["jquery.min.js", "pad_utils.js", "plugins.js", "undo-xpopup.js", "json2.js", "pad_cookie.js", "pad_editor.js", "pad_editbar.js", "pad_docbar.js", "pad_modals.js", "ace.js", "collab_client.js", "pad_userlist.js", "pad_impexp.js", "pad_savedrevs.js", "pad_connectionstatus.js", "pad2.js", "jquery-ui.js", "chat.js"];
var timesliderJS = ["jquery.min.js", "plugins.js", "undo-xpopup.js", "json2.js", "colorutils.js", "draggable.js", "pad_utils.js", "pad_cookie.js", "pad_editor.js", "pad_editbar.js", "pad_docbar.js", "pad_modals.js", "easysync2_client.js", "domline_client.js", "linestylefilter_client.js", "cssmanager_client.js", "broadcast.js", "broadcast_slider.js", "broadcast_revisions.js"];
/** /**
* Answers a http request for the pad javascript * creates the minifed javascript for the given minified name
* @param req the Express request * @param req the Express request
* @param res the Express response * @param res the Express response
*/ */
exports.padJS = function(req, res) exports.minifyJS = function(req, res, jsFilename)
{ {
res.header("Content-Type","text/javascript"); res.header("Content-Type","text/javascript");
var jsFiles = ["jquery.min.js", "pad_utils.js", "plugins.js", "undo-xpopup.js", "json2.js", "pad_cookie.js", "pad_editor.js", "pad_editbar.js", "pad_docbar.js", "pad_modals.js", "ace.js", "collab_client.js", "pad_userlist.js", "pad_impexp.js", "pad_savedrevs.js", "pad_connectionstatus.js", "pad2.js", "jquery-ui.js", "chat.js"]; //choose the js files we need
if(jsFilename == "pad.js")
{
jsFiles = padJS;
}
else if(jsFilename == "timeslider.js")
{
jsFiles = timesliderJS;
}
else
{
throw new Error("there is no profile for creating " + name);
}
//minifying is enabled //minifying is enabled
if(settings.minify) if(settings.minify)
@ -91,7 +107,7 @@ exports.padJS = function(req, res)
function(callback) function(callback)
{ {
//check the modification time of the minified js //check the modification time of the minified js
fs.stat("../var/minified_pad.js", function(err, stats) fs.stat("../var/minified_" + jsFilename, function(err, stats)
{ {
if(err && err.code != "ENOENT") callback(err); if(err && err.code != "ENOENT") callback(err);
@ -122,6 +138,13 @@ exports.padJS = function(req, res)
//find all includes in ace.js and embed them //find all includes in ace.js and embed them
function(callback) function(callback)
{ {
//if this is not the creation of pad.js, skip this part
if(jsFilename != "pad.js")
{
callback();
return;
}
var founds = fileValues["ace.js"].match(/\$\$INCLUDE_[a-zA-Z_]+\([a-zA-Z0-9.\/_"]+\)/gi); var founds = fileValues["ace.js"].match(/\$\$INCLUDE_[a-zA-Z_]+\([a-zA-Z0-9.\/_"]+\)/gi);
//go trough all includes //go trough all includes
@ -194,7 +217,7 @@ exports.padJS = function(req, res)
//write the results plain in a file //write the results plain in a file
function(callback) function(callback)
{ {
fs.writeFile("../var/minified_pad.js", result, "utf8", callback); fs.writeFile("../var/minified_" + jsFilename, result, "utf8", callback);
}, },
//write the results compressed in a file //write the results compressed in a file
function(callback) function(callback)
@ -202,7 +225,7 @@ exports.padJS = function(req, res)
gzip(result, 9, function(err, compressedResult){ gzip(result, 9, function(err, compressedResult){
if(err) {callback(err); return} if(err) {callback(err); return}
fs.writeFile("../var/minified_pad.js.gz", compressedResult, callback); fs.writeFile("../var/minified_" + jsFilename + ".gz", compressedResult, callback);
}); });
} }
],callback); ],callback);
@ -217,12 +240,12 @@ exports.padJS = function(req, res)
var pathStr; var pathStr;
if(gzipSupport) if(gzipSupport)
{ {
pathStr = path.normalize(__dirname + "/../var/minified_pad.js.gz"); pathStr = path.normalize(__dirname + "/../../var/minified_" + jsFilename + ".gz");
res.header('Content-Encoding', 'gzip'); res.header('Content-Encoding', 'gzip');
} }
else else
{ {
pathStr = path.normalize(__dirname + "/../var/minified_pad.js"); pathStr = path.normalize(__dirname + "/../../var/minified_" + jsFilename );
} }
res.sendfile(pathStr, { maxAge: server.maxAge }); res.sendfile(pathStr, { maxAge: server.maxAge });

View File

@ -21,6 +21,11 @@
var fs = require("fs"); var fs = require("fs");
/**
* The IP ep-lite should listen to
*/
exports.ip = "0.0.0.0";
/** /**
* The Port ep-lite should listen to * The Port ep-lite should listen to
*/ */
@ -33,10 +38,6 @@ exports.dbType = "sqlite";
* This setting is passed with dbType to ueberDB to set up the database * This setting is passed with dbType to ueberDB to set up the database
*/ */
exports.dbSettings = { "filename" : "../var/sqlite.db" }; exports.dbSettings = { "filename" : "../var/sqlite.db" };
/**
* A flag that shows if http requests should be loged to stdout
*/
exports.logHTTP = true;
/** /**
* The default Text of a new pad * The default Text of a new pad
*/ */
@ -88,6 +89,6 @@ for(var i in settings)
else else
{ {
console.error("WARNING: Unkown Setting: '" + i + "'"); console.error("WARNING: Unkown Setting: '" + i + "'");
console.error("If this isn't a mistake, add the default settings for this value to node/settings.js"); console.error("This setting doesn't exist or it was removed");
} }
} }

View File

@ -6,18 +6,20 @@
"author" : "Peter 'Pita' Martischka <petermartischka@googlemail.com>", "author" : "Peter 'Pita' Martischka <petermartischka@googlemail.com>",
"contributors": [ "contributors": [
{ "name": "John McLear", { "name": "John McLear",
"name": "Hans Pinckaers"} "name": "Hans Pinckaers",
"name": "Robin Buse"}
], ],
"dependencies" : { "dependencies" : {
"socket.io" : "0.7.7", "socket.io" : "0.7.7",
"ueberDB" : "0.0.10", "ueberDB" : "0.0.12",
"async" : "0.1.9", "async" : "0.1.9",
"joose" : "3.18.0", "joose" : "3.18.0",
"express" : "2.4.3", "express" : "2.4.3",
"clean-css" : "0.2.4", "clean-css" : "0.2.4",
"uglify-js" : "1.0.6", "uglify-js" : "1.0.6",
"gzip" : "0.1.0", "gzip" : "0.1.0",
"formidable" : "1.0.2" "formidable" : "1.0.2",
"log4js" : "0.3.7"
}, },
"version" : "0.0.4" "version" : "0.0.4"
} }

View File

@ -4,6 +4,8 @@
Please edit settings.json, not settings.json.template Please edit settings.json, not settings.json.template
*/ */
{ {
//Ip and port which etherpad should bind at
"ip": "0.0.0.0",
"port" : 9001, "port" : 9001,
//The Type of the database. You can choose between sqlite and mysql //The Type of the database. You can choose between sqlite and mysql
@ -23,9 +25,6 @@
}, },
*/ */
//if true, every http request will be loged to stdout
"logHTTP" : true,
//the default text of a pad //the default text of a pad
"defaultPadText" : "Welcome to Etherpad Lite!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nEtherpad Lite on Github: http:\/\/j.mp/ep-lite\n", "defaultPadText" : "Welcome to Etherpad Lite!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nEtherpad Lite on Github: http:\/\/j.mp/ep-lite\n",

3
static/custom/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*
!js.template
!css.template

View File

@ -0,0 +1,5 @@
/*
You may have to use !important to override css attributs, for example:
* {color: blue !important;}
*/

View File

@ -0,0 +1,6 @@
function costumStart()
{
//define your javascript here
//jquery is avaiable - except index.js
//you can load extra scripts with $.getScript http://api.jquery.com/jQuery.getScript/
}

View File

@ -81,11 +81,13 @@
width: 40px; width: 40px;
} }
</style> </style>
<link href="static/custom/index.css" rel="stylesheet">
<script src="static/custom/index.js"></script>
<div id="container"> <div id="container">
<div id="button" onclick="go2Random()">New Pad</div> <div id="button" onclick="go2Random()">New Pad</div>
<br> <br>
<div class="label">or create/open a Pad with the name</div> <div class="label">or create/open a Pad with the name</div>
<form action="" onsubmit="go2Name();return false;"> <form action="#" onsubmit="go2Name();return false;">
<input type="text" id="padname" autofocus> <input type="text" id="padname" autofocus>
<input type="submit" value="OK"> <input type="submit" value="OK">
</form> </form>
@ -111,7 +113,7 @@
function randomPadName() function randomPadName()
{ {
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz"; var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var string_length = 10; var string_length = 10;
var randomstring = ''; var randomstring = '';
for (var i = 0; i < string_length; i++) for (var i = 0; i < string_length; i++)
@ -121,5 +123,8 @@
} }
return randomstring; return randomstring;
} }
//start the costum js
if(costumStart) costumStart();
</script> </script>
</html> </html>

View File

@ -20,7 +20,7 @@ function makeCSSManager(emptyStylesheetTitle, top)
function getSheetByTitle(title, top) function getSheetByTitle(title, top)
{ {
if(top) if(top)
var allSheets = window.top.document.styleSheets; var allSheets = window.parent.parent.document.styleSheets;
else else
var allSheets = document.styleSheets; var allSheets = document.styleSheets;

View File

@ -29,6 +29,9 @@ $(document).ready(function()
document.location = expectedURL; document.location = expectedURL;
} }
//start the costum js
if(costumStart) costumStart();
handshake(); handshake();
}); });
@ -64,7 +67,7 @@ function readCookie(name)
function randomString() function randomString()
{ {
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz"; var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var string_length = 20; var string_length = 20;
var randomstring = ''; var randomstring = '';
for (var i = 0; i < string_length; i++) for (var i = 0; i < string_length; i++)
@ -126,8 +129,8 @@ function handshake()
receivedClientVars = true; receivedClientVars = true;
clientVars = obj; clientVars = obj;
clientVars.userAgent = navigator.userAgent; clientVars.userAgent = "Anonymous";
clientVars.collab_client_vars.clientAgent = navigator.userAgent; clientVars.collab_client_vars.clientAgent = "Anonymous";
pad.init(); pad.init();

View File

@ -101,7 +101,7 @@ var padeditbar = (function()
else if (cmd == 'embed') else if (cmd == 'embed')
{ {
var padurl = document.location; var padurl = document.location;
$('#embedinput').val("<iframe src='" + padurl + "' width=500 height=400>"); $('#embedinput').val("<iframe src='" + padurl + "' width=600 height=400>");
self.toogleDropDown("embed"); self.toogleDropDown("embed");
$('#embedinput').focus().select(); $('#embedinput').focus().select();
} }

View File

@ -233,12 +233,26 @@ var padimpexp = (function()
// build the export links // build the export links
$("#exporthtmla").attr("href", document.location.href + "/export/html"); $("#exporthtmla").attr("href", document.location.href + "/export/html");
$("#exportplaina").attr("href", document.location.href + "/export/txt"); $("#exportplaina").attr("href", document.location.href + "/export/txt");
$("#exportwordlea").attr("href", document.location.href + "/export/wordle");
//hide stuff thats not avaible if abiword is disabled
if(!clientVars.abiwordAvailable)
{
$("#exportworda").remove();
$("#exportpdfa").remove();
$("#exportopena").remove();
$("#importexport").css({"height":"95px"});
$("#importexportline").css({"height":"95px"});
$("#import").html("Import is not available");
}
else
{
$("#exportworda").attr("href", document.location.href + "/export/doc"); $("#exportworda").attr("href", document.location.href + "/export/doc");
$("#exportpdfa").attr("href", document.location.href + "/export/pdf"); $("#exportpdfa").attr("href", document.location.href + "/export/pdf");
$("#exportopena").attr("href", document.location.href + "/export/odt"); $("#exportopena").attr("href", document.location.href + "/export/odt");
$("#exportwordlea").attr("href", document.location.href + "/export/wordle");
$("#importform").get(0).setAttribute('action', document.location.href + "/import"); $("#importform").get(0).setAttribute('action', document.location.href + "/import");
}
$("#impexp-close").click(function() $("#impexp-close").click(function()
{ {
@ -275,9 +289,7 @@ var padimpexp = (function()
}, },
export2Wordle: function() export2Wordle: function()
{ {
padUrl = location.pathname; var padUrl = document.location.href + "/export/txt";
padHost = location.host;
var padUrl = "http://" + padHost + padUrl + "/export/txt";
$.get(padUrl, function(data) $.get(padUrl, function(data)
{ {

View File

@ -13,6 +13,8 @@
</script> </script>
<script src="../socket.io/socket.io.js"></script> <script src="../socket.io/socket.io.js"></script>
<script src="../minified/pad.js"></script> <script src="../minified/pad.js"></script>
<link href="../static/custom/pad.css" rel="stylesheet">
<script src="../static/custom/pad.js"></script>
<style type="text/css" title="dynamicsyntax"></style> <style type="text/css" title="dynamicsyntax"></style>
</head> </head>
@ -79,17 +81,17 @@
<ul id="menu_right"> <ul id="menu_right">
<li> <li>
<a onClick="window.pad&&pad.editbarClick('readonly');return false;" title="Create a readonly link for this pad"> <a id="readonlylink" onClick="window.pad&&pad.editbarClick('readonly');return false;" title="Create a readonly link for this pad">
<div class="buttonicon" style="background-position:0px -150px"></div> <div class="buttonicon" style="background-position:0px -150px"></div>
</a> </a>
</li> </li>
<li> <li>
<a onClick="window.pad&&pad.editbarClick('import_export');return false;" title="Import/Export from/to different document formats"> <a id="exportlink" onClick="window.pad&&pad.editbarClick('import_export');return false;" title="Import/Export from/to different document formats">
<div class="buttonicon" style="background-position:0px -68px"></div> <div class="buttonicon" style="background-position:0px -68px"></div>
</a> </a>
</li> </li>
<li> <li>
<a onClick="window.pad&&pad.editbarClick('embed');return false;" title="Embed this pad"> <a id="embedlink" onClick="window.pad&&pad.editbarClick('embed');return false;" title="Embed this pad">
<div class="buttonicon" style="background-position:0px -18px"></div> <div class="buttonicon" style="background-position:0px -18px"></div>
</a> </a>
</li> </li>
@ -219,7 +221,7 @@ We removed this feature cause its not worth the space it needs in the editbar
<a id="exportworda" target="_blank" class="exportlink"><div class="exporttype" id="exportword">Microsoft Word</div></a> <a id="exportworda" target="_blank" class="exportlink"><div class="exporttype" id="exportword">Microsoft Word</div></a>
<a id="exportpdfa" target="_blank" class="exportlink"><div class="exporttype" id="exportpdf">PDF</div></a> <a id="exportpdfa" target="_blank" class="exportlink"><div class="exporttype" id="exportpdf">PDF</div></a>
<a id="exportopena" target="_blank" class="exportlink"><div class="exporttype" id="exportopen">OpenDocument</div></a> <a id="exportopena" target="_blank" class="exportlink"><div class="exporttype" id="exportopen">OpenDocument</div></a>
<a id="exportwordlea" target="_blank" onClick="loadCont();return false;" class="exportlink"><div class="exporttype" id="exportwordle">Wordle</div></a> <a id="exportwordlea" target="_blank" onClick="padimpexp.export2Wordle();return false;" class="exportlink"><div class="exporttype" id="exportwordle">Wordle</div></a>
<form id="wordlepost" name="wall" action="http://wordle.net/advanced" method="POST" style="margin-left:0px;"> <form id="wordlepost" name="wall" action="http://wordle.net/advanced" method="POST" style="margin-left:0px;">
<div id="hidetext" style=""><textarea id="text" name="text" id="text" style="display:none;">Coming soon!</textarea></div> <div id="hidetext" style=""><textarea id="text" name="text" id="text" style="display:none;">Coming soon!</textarea></div>
</form> </form>

View File

@ -8,7 +8,13 @@
<link rel="stylesheet" href="../../static/css/pad.css"> <link rel="stylesheet" href="../../static/css/pad.css">
<link rel="stylesheet" href="../../static/css/timeslider.css"> <link rel="stylesheet" href="../../static/css/timeslider.css">
<style type="text/css" title="dynamicsyntax"></style> <style type="text/css" title="dynamicsyntax"></style>
<script src="../../static/js/jquery.min.js"></script>
<script type="text/javascript" src="../../socket.io/socket.io.js"></script>
<script type="text/javascript" src="../../minified/timeslider.js"></script>
<link href="../../static/custom/timeslider.css" rel="stylesheet">
<script src="../../static/custom/timeslider.js"></script>
<script> <script>
// <![CDATA[ // <![CDATA[
var clientVars = {}; var clientVars = {};
@ -37,7 +43,7 @@
} }
function randomString() { function randomString() {
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz"; var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var string_length = 20; var string_length = 20;
var randomstring = ''; var randomstring = '';
for (var i=0; i<string_length; i++) { for (var i=0; i<string_length; i++) {
@ -49,8 +55,11 @@
var socket, token, padId; var socket, token, padId;
$(window).load(function () $(document).ready(function ()
{ {
//start the costum js
if(costumStart) costumStart();
//get the padId out of the url //get the padId out of the url
var urlParts= document.location.pathname.split("/"); var urlParts= document.location.pathname.split("/");
padId = urlParts[urlParts.length-2]; padId = urlParts[urlParts.length-2];
@ -133,26 +142,6 @@
// ]]> // ]]>
</script> </script>
<script type="text/javascript" src="../../static/js/plugins.js"></script>
<script type="text/javascript" src="../../static/js/undo-xpopup.js"></script>
<script type="text/javascript" src="../../socket.io/socket.io.js"></script>
<script type="text/javascript" src="../../static/js/json2.js"></script>
<script type="text/javascript" src="../../static/js/colorutils.js"></script>
<script type="text/javascript" src="../../static/js/draggable.js"></script>
<script type="text/javascript" src="../../static/js/pad_utils.js"></script>
<script type="text/javascript" src="../../static/js/pad_cookie.js"></script>
<script type="text/javascript" src="../../static/js/pad_editor.js"></script>
<script type="text/javascript" src="../../static/js/pad_editbar.js"></script>
<script type="text/javascript" src="../../static/js/pad_docbar.js"></script>
<script type="text/javascript" src="../../static/js/pad_modals.js"></script>
<script type="text/javascript" src="../../static/js/easysync2_client.js"></script>
<script type="text/javascript" src="../../static/js/domline_client.js"></script>
<script type="text/javascript" src="../../static/js/linestylefilter_client.js"></script>
<script type="text/javascript" src="../../static/js/cssmanager_client.js"></script>
<script type="text/javascript" src="../../static/js/broadcast.js"></script>
<script type="text/javascript" src="../../static/js/broadcast_slider.js"></script>
<script type="text/javascript" src="../../static/js/broadcast_revisions.js">
</script>
</head> </head>
<body id="padbody" class="timeslider limwidth nonpropad nonprouser"> <body id="padbody" class="timeslider limwidth nonpropad nonprouser">