define([
"sugar-web/activity/activity",
"activity/palettes/format-text-palette",
"activity/palettes/list-palette",
"activity/palettes/paragraph-palette",
"activity/palettes/font-palette",
"sugar-web/graphics/colorpalette",
"sugar-web/datastore",
"sugar-web/graphics/journalchooser",
"sugar-web/env",
"sugar-web/graphics/presencepalette",
"activity/palettes/export-palette",
"webL10n",
], function (activity,formatpalette,listpalette,parapalette,fontPalette,colorpalette , datastore , journalchooser,env,presencepalette,exportpalette,webL10n) {
// Manipulate the DOM only when it is ready.
requirejs(['domReady!','humane'], function (doc,humane) {
// Initialize the activity.
activity.setup();
var options = {
modules: {
toolbar: '#main-toolbar',
history: {
maxStack: 500,
},
imageResize: {},
cursors: {
transformOnTextChange: true,
},
clipboard: true
},
};
Quill.register('modules/cursors', QuillCursors);
var container = document.getElementById('editor');
var editor = new Quill(container,options);
editor.focus();
editor.format('size','24px');
const cursors = editor.getModule('cursors');
const Delta = Quill.import('delta');
// Journal Handling (Load)
env.getEnvironment(function(err, environment) {
currentenv = environment;
// Language Settings
var defaultLanguage = (typeof chrome != 'undefined' && chrome.app && chrome.app.runtime) ? chrome.i18n.getUILanguage() : navigator.language;
var language = environment.user ? environment.user.language : defaultLanguage;
webL10n.language.code = language;
window.addEventListener("localized", function() {
document.getElementById("network-button").title = webL10n.get("Network");
document.getElementById("color-button-1").title = webL10n.get("ForegroundColor");
document.getElementById("color-button-2").title = webL10n.get("BackgroundColor");
document.getElementById("format-text").title = webL10n.get("Formattext");
document.getElementById("paragraph").title = webL10n.get("Paragraph");
document.getElementById("list").title = webL10n.get("List");
document.getElementById("resize-inc").title = webL10n.get("Increasefontsize");
document.getElementById("font-button").title = webL10n.get("ChooseFont");
document.getElementById("resize-dec").title = webL10n.get("Decreasefontsize");
document.getElementById("insert-picture").title = webL10n.get("Image");
document.getElementById("edit-undo").title = webL10n.get("Undo");
document.getElementById("edit-redo").title = webL10n.get("Redo");
document.getElementById("edit-copy").title = webL10n.get("Copy");
document.getElementById("edit-paste").title = webL10n.get("Paste");
document.getElementById("export").title = webL10n.get("Export");
document.getElementById(5).title = webL10n.get("Bold");
document.getElementById(6).title = webL10n.get("Italic");
document.getElementById(7).title = webL10n.get("Underline");
document.getElementById(8).title = webL10n.get("Strike");
document.getElementById(9).title = webL10n.get("OrderedList");
document.getElementById(10).title = webL10n.get("UnorderedList");
document.getElementById(11).title = webL10n.get("JustifyLeft");
document.getElementById(12).title = webL10n.get("JustifyRight");
document.getElementById(13).title = webL10n.get("JustifyCenter");
document.getElementById(19).title = webL10n.get("ExportToTxt");
document.getElementById(20).title = webL10n.get("ExportToPdf");
document.getElementById(21).title = webL10n.get("ExportToDoc");
document.getElementById(22).title = webL10n.get("ExportToOdt");
});
if (!environment.objectId && !environment.sharedId) {
// New instance
// Intentionally added setTimeout to allow locale.ini file to be loaded
setTimeout(function(){
editor.setContents([
{insert: webL10n.get('Welcome',{username: environment.user.name}) + '\n' , attributes: { size: "40px" , color : environment.user.colorvalue.stroke , bold: true }},
]);
var length = editor.getLength();
editor.clipboard.dangerouslyPasteHTML(length,webL10n.get('Write'));
length = editor.getLength();
editor.clipboard.dangerouslyPasteHTML(length,webL10n.get('Writefeatures'));
length = editor.getLength();
editor.clipboard.dangerouslyPasteHTML(length,webL10n.get('Enjoy'));
length = editor.getLength();
editor.clipboard.dangerouslyPasteHTML(length,"
");
length = editor.getLength();
editor.updateContents(
new Delta()
.retain(editor.getSelection().index+1)
.insert({
image: window.initialImageDataUrl
})
);
},200);
} else {
// Existing instance
activity.getDatastoreObject().loadAsText(function(error, metadata, data) {
if (error==null && data!=null) {
var delta = JSON.parse(data);
console.log(delta);
editor.setContents(delta);
}
});
}
// Shared instances
if (environment.sharedId) {
console.log("Shared instance");
// Hide GUI of undo and redo for non host users
document.getElementById("edit-undo").style.display = "none";
document.getElementById("edit-redo").style.display = "none";
document.getElementById("shared-button").click();
presence = activity.getPresenceObject(function(error, network) {
network.onDataReceived(onNetworkDataReceived);
network.onSharedActivityUserChanged(onNetworkUserChanged);
});
}
});
// Save in Journal on Stop
document.getElementById("stop-button").addEventListener('click', function (event) {
// Journal handling
var data = editor.getContents();
var jsondata = JSON.stringify(data);
activity.getDatastoreObject().setDataAsText(jsondata);
activity.getDatastoreObject().save(function (error) {
if (error === null) {
console.log("write done.");
} else {
console.log("write failed.");
}
});
});
var changeMadebyUser=false;
var copiedContent = null ;
document.getElementById("edit-copy").addEventListener('click',function(){
var range = editor.getSelection();
copiedContent = editor.getContents(range.index,range.length);
document.execCommand('copy');
});
document.getElementById("edit-paste").addEventListener('click',function(){
if(document.execCommand('paste')){
// Your browser supports execCommand('paste')
} else if(copiedContent!=null) {
// Your browser does not support execCommand('paste')
changeMadebyUser=true;
editor.updateContents(
new Delta()
.retain(editor.getSelection().index)
.concat(copiedContent)
);
}
});
// Sync Keyboard Shortcut of copy with custom events
editor.keyboard.addBinding({ key: 'C', shortKey: true }, function(){document.getElementById("edit-copy").click()});
document.getElementById("edit-undo").addEventListener('click',function(){
editor.history.undo();
});
document.getElementById("edit-redo").addEventListener('click',function(){
editor.history.redo();
});
// Initiating format-text-palette ( for cut/copy/undo/redo )
var formatButton = document.getElementById("format-text");
var formatoptions = [
{"id": 5, "title": "bold", "cmd":"bold"},
{"id": 6, "title": "italic", "cmd":"italic"},
{"id": 7, "title": "underline", "cmd":"underline"},
{"id": 8, "title": "strike", "cmd":"strikeThrough"}
];
formatpalette = new formatpalette.Formatpalette(formatButton, undefined);
formatpalette.setCategories(formatoptions);
formatpalette.addEventListener('format', function () {
formatpalette.popDown();
editor.focus();
});
document.getElementById(5).addEventListener('click',function(){
document.getElementById("bold").click();
});
document.getElementById(6).addEventListener('click',function(){
document.getElementById("italic").click();
});
document.getElementById(7).addEventListener('click',function(){
document.getElementById("underline").click();
});
document.getElementById(8).addEventListener('click',function(){
document.getElementById("strike").click();
});
// Initiating lists palette
var listButton = document.getElementById("list");
var listoptions = [
{"id": 10, "title": "unordered list", "cmd":"insertUnorderedList"},
{"id": 9, "title": "ordered list", "cmd":"insertorderedList"},
];
listpalette = new listpalette.Listpalette(listButton, undefined);
listpalette.setCategories(listoptions);
listpalette.addEventListener('list', function () {
listpalette.popDown();
});
document.getElementById("9").addEventListener("click",function(){
document.getElementById("list-ordered").click();
});
document.getElementById("10").addEventListener("click",function(){
document.getElementById("list-unordered").click();
});
// Initiating paragraph palette ( Alignment settings )
var paraButton = document.getElementById("paragraph");
var paraoptions = [
{"id": 11, "title":"justify Left" , "cmd":"justifyLeft"},
{"id": 13, "title":"justify Center" , "cmd":"justifyCenter"},
{"id": 12, "title":"justify Right" , "cmd":"justifyRight"},
];
parapalette = new parapalette.Parapalette(paraButton, undefined);
parapalette.setCategories(paraoptions);
parapalette.addEventListener('para', function () {
parapalette.popDown();
editor.focus();
});
document.getElementById(11).addEventListener("click",function(){
changeMadebyUser=true;
editor.format('align','justify');
})
document.getElementById(12).addEventListener("click",function(){
changeMadebyUser=true;
editor.format('align','right');
});
document.getElementById(13).addEventListener("click",function(){
changeMadebyUser=true;
editor.format('align','center');
});
// Initialise font palette
var fontButton = document.getElementById("font-button");
fontPalette = new fontPalette.Fontpalette(fontButton);
fontPalette.addEventListener('fontChange', function(e) {
var newfont = e.detail.family;
if(newfont=="Arial") newfont="arial";
if(newfont=="Comic Sans MS") newfont="comic";
changeMadebyUser=true;
editor.format('font',newfont);
});
// Initiating colour palette for foreground and background
var forecolorButton = document.getElementById("color-button-1");
var changeForeColorPalette = new colorpalette.ColorPalette(forecolorButton);
changeForeColorPalette.setColor('rgb(0, 0, 0)');
changeForeColorPalette.addEventListener('colorChange', function(e) {
changeMadebyUser=true;
editor.format('color',e.detail.color);
});
var backcolorButton = document.getElementById("color-button-2");
var changeBackColorPalette = new colorpalette.ColorPalette(backcolorButton);
changeBackColorPalette.setColor('rgb(255,255,255)');
changeBackColorPalette.addEventListener('colorChange', function(e) {
changeMadebyUser=true;
editor.format('background-color',e.detail.color);
});
// Initiating font-size-palette
// For increase
var sizes = ['16px', '24px', '32px' ,'40px', '48px' , '56px', '64px' , '72px' , '80px' , '100px'];
var sizeIncButton = document.getElementById("resize-inc");
sizeIncButton.addEventListener("click",function(){
var currentSize = editor.getFormat();
if(currentSize.size==null){
var index = sizes.indexOf('24px');
editor.format('size',sizes[index+1]);
}
else {
var index = sizes.indexOf(currentSize.size);
index++;
if(index0)
editor.format('size',sizes[index-1]);
}
else {
var index = sizes.indexOf(currentSize.size);
index--;
if(index>=0){
editor.format('size',sizes[index]);
}
}
});
// Insert Image handling
document.getElementById("insert-picture").addEventListener("click",function(e){
journalchooser.show(function (entry) {
if (!entry) {
return;
}
var dataentry = new datastore.DatastoreObject(entry.objectId);
dataentry.loadAsText(function (err, metadata, data) {
editor.focus();
changeMadebyUser=true;
editor.updateContents(
new Delta()
.retain(editor.getSelection().index)
.insert({
image: data
})
);
});
}, { mimetype: 'image/png' }, { mimetype: 'image/jpeg' });
});
// Initiating export-palette
var exportButton = document.getElementById("export");
var options = [
{"id": 19, "title": "export to txt" , "cmd":"save-as-txt"},
{"id": 20, "title": "export to pdf", "cmd":"save-as-pdf"},
{"id": 21, "title": "export to doc", "cmd":"doc"},
{"id": 22, "title": "export to odt", "cmd":"odt"},
];
exportpalette = new exportpalette.Exportpalette(exportButton, undefined);
exportpalette.setCategories(options);
exportpalette.addEventListener('export', function () {
exportpalette.popDown();
});
// save as txt
document.getElementById("19").addEventListener('click',function(){
var title = document.getElementById("title").value;
var mimetype = 'text/plain';
var inputData = document.getElementById("editor").textContent;
inputData=JSON.stringify(inputData);
var metadata = {
mimetype: mimetype,
title: title+".txt",
activity: "",
timestamp: new Date().getTime(),
creation_time: new Date().getTime(),
file_size: 0
};
datastore.create(metadata, function() {
console.log("export done.");
humane.log(webL10n.get("Txt"));
}, inputData);
});
// save as PDF
document.getElementById("20").addEventListener('click',function(){
var title = document.getElementById("title").value;
editor.scrollingContainer.style.overflowY = 'visible';
console.log(editor.scrollingContainer.style.height);
var h = editor.scrollingContainer.offsetHeight;
editor.scrollingContainer.style.height="auto";
editor.scrollingContainer.scrollTop=0;
html2canvas(editor.scrollingContainer).then(function(canvas){
editor.scrollingContainer.style.height=h;
editor.scrollingContainer.style.overflowY = 'auto';
var imgData = canvas.toDataURL('image/png');
var imgData = canvas.toDataURL('image/png');
var imgWidth = 210;
var pageHeight = 295;
var imgHeight = canvas.height * imgWidth / canvas.width;
var heightLeft = imgHeight;
var doc = new jsPDF('p', 'mm' , '',true);
var position = 0;
doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight , '' , 'FAST');
heightLeft -= pageHeight;
while (heightLeft >= 0) {
position = heightLeft - imgHeight;
doc.addPage();
doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight , '' , 'FAST');
heightLeft -= pageHeight;
}
var inputData = doc.output('dataurlstring');
var mimetype = 'application/pdf';
var metadata = {
mimetype: mimetype,
title: title+".pdf",
activity: "",
timestamp: new Date().getTime(),
creation_time: new Date().getTime(),
file_size: 0
};
datastore.create(metadata, function() {
console.log("export done.");
humane.log(webL10n.get("Pdf"));
}, inputData);
});
});
// Save as doc
document.getElementById(21).addEventListener("click",function(){
var title = document.getElementById("title").value;
var content =document.getElementById("editor").innerHTML;
var header = ""+
"";
var footer = "";
var sourceHTML = header+content+footer;
var inputData = 'data:application/vnd.ms-word;charset=utf-8;base64,' + btoa(unescape(encodeURIComponent( sourceHTML )));
var mimetype = 'application/msword';
var metadata = {
mimetype: mimetype,
title: title+".doc",
activity: "",
timestamp: new Date().getTime(),
creation_time: new Date().getTime(),
file_size: 0
};
datastore.create(metadata, function() {
console.log("export done.");
humane.log(webL10n.get("Doc"));
}, inputData);
});
//Save as odt
document.getElementById("22").addEventListener("click",function(){
// resetXML();
var data = document.getElementsByClassName("ql-editor");
var xml = traverse(data[0]);
var mimetype = 'application/vnd.oasis.opendocument.text';
var title = document.getElementById("title").value;
var inputData = 'data:application/vnd.oasis.opendocument.text;charset=utf-8;base64,' + btoa(unescape(encodeURIComponent( xml )));
var metadata = {
mimetype: mimetype,
title: title+".odt",
activity: "",
timestamp: new Date().getTime(),
creation_time: new Date().getTime(),
file_size: 0
};
datastore.create(metadata, function() {
console.log("export done.");
humane.log(webL10n.get("Odt"));
resetXML();
}, inputData);
});
// On content change handlers , sends data to other users on content being changed
editor.on('text-change', function(delta, oldDelta, source) {
// Executes on text or formatting changes
if ((source == 'user' || changeMadebyUser==true) && presence!=null) {
var range = editor.getSelection();
presence.sendMessage(presence.getSharedInfo().id, {
user: presence.getUserInfo(),
content: {
action: 'typing',
data: delta,
range: range
}
});
changeMadebyUser=false;
}
});
editor.on('selection-change', function(range, oldRange, source) {
// Executes when user selection changes
if (range) {
if (presence!=null) {
presence.sendMessage(presence.getSharedInfo().id, {
user: presence.getUserInfo(),
content: {
action: 'selection',
range: range
}
});
}
}
});
// Presence Palette
// Link presence palette
var presence = null;
var isHost = false;
var myid;
var nomoreinit = false;
var mycursor;
var palette = new presencepalette.PresencePalette(document.getElementById("network-button"), undefined);
palette.addEventListener('shared', function() {
palette.popDown();
console.log("Want to share");
presence = activity.getPresenceObject(function(error, network) {
if (error) {
console.log("Sharing error");
return;
}
network.createSharedActivity('org.sugarlabs.Write', function(groupId) {
console.log("Activity shared");
isHost = true;
});
network.onDataReceived(onNetworkDataReceived);
network.onSharedActivityUserChanged(onNetworkUserChanged);
});
});
var onNetworkDataReceived = function(msg) {
if (presence.getUserInfo().networkId === msg.user.networkId) {
return;
}
if(msg.content.action=='init' && nomoreinit==false){
editor.updateContents(msg.content.data);
var getallcursors = msg.content.allcursors;
for(var i = 0 ; i < getallcursors.length ; i++){
console.log(getallcursors[i]);
if(getallcursors[i].id!=myid){
cursors.createCursor(getallcursors[i].id, getallcursors[i].name,getallcursors[i].color) ;
cursors.moveCursor(getallcursors[i].id, getallcursors[i].range) ;
}
}
cursors.update();
// Create Fake event to init Cursors
document.getElementById("list-ordered").click();
document.getElementById("list-ordered").click();
nomoreinit=true;
}
if(msg.content.action=='typing'){
editor.updateContents(msg.content.data);
}
if(msg.content.action=='selection'){
setTimeout(function() {cursors.moveCursor(msg.user.networkId,msg.content.range)} , 5);
}
};
var onNetworkUserChanged = function(msg) {
if (isHost) {
var data = editor.getContents();
var range = editor.getSelection();
mycursor.range = range;
var allcursors = cursors.cursors();
presence.sendMessage(presence.getSharedInfo().id, {
user: presence.getUserInfo(),
content: {
action: 'init',
data: data,
allcursors: allcursors
}
});
mycursor.range = null;
}
if(!myid){
myid = msg.user.networkId;
}
// handle user enter/exit Notifications
var userName = msg.user.name.replace('<', '<').replace('>', '>');
var html = "";
presence.listSharedActivities(function(activities){
for (var i = 0; i < activities.length; i++) {
if (activities[i].id === presence.getSharedInfo().id) {
getConnectedPeople(activities[i].users);
}
}
});
for (var key in connectedPeople) {
console.log(connectedPeople[key].name,key,connectedPeople[key].networkId);
}
if(msg.move==1){
humane.log(html + webL10n.get("PlayerJoin",{user: userName}));
var c = cursors.createCursor(msg.user.networkId, userName, msg.user.colorvalue.stroke);
if(myid==msg.user.networkId) {mycursor=c;}
}
if (msg.move === -1) {
cursors.removeCursor(msg.user.networkId);
humane.log(html + webL10n.get("PlayerLeave",{user: userName}));
if(msg.user.networkId == connectedPeople[0].networkId){
if(connectedPeople[1].networkId == myid){
document.getElementById(3).style.display = "inline";
document.getElementById(4).style.display = "inline";
isHost=true;
}
}
}
};
var xoLogo = ']>';
function generateXOLogoWithColor(color) {
var coloredLogo = xoLogo;
coloredLogo = coloredLogo.replace("#010101", color.stroke)
coloredLogo = coloredLogo.replace("#FFFFFF", color.fill)
return "data:image/svg+xml;base64," + btoa(coloredLogo);
}
var connectedPeople = {};
// Maintain a list of connected users
function displayConnectedPeople(){
var presenceUsersDiv = document.getElementById("presence-users");
var html = "
";
for (var key in connectedPeople) {
html += "- " + connectedPeople[key].name + "
"
}
html += "
"
presenceUsersDiv.innerHTML = html
}
function getConnectedPeople(users){
var presenceUsersDiv = document.getElementById("presence-users");
if (!users || !presenceUsersDiv) {
return;
}
connectedPeople = {};
presence.listSharedActivityUsers(presence.getSharedInfo().id , function(usersConnected){
connectedPeople = {};
for (var i = 0; i < usersConnected.length; i++) {
var userConnected = usersConnected[i];
connectedPeople[i] = userConnected;
}
displayConnectedPeople();
});
}
});
});