Commit 8b66f91e authored by Tristan Cavelier's avatar Tristan Cavelier

OfficeJS: updated to work with jio, and security improved

parent b7e3ff26
<div id="basic_conflict_solver_div" style="text-align:center;" class="well"> <div id="basic_conflict_solver_div" style="text-align:center;" class="well">
<div class="row-fluid"> <div class="row-fluid">
<div class="span12"> <div class="span12">
A conflict occured while saving this document: There is a conflict in document <span id="basic_conflict_solver_docid"></span>
</div> </div>
</div> </div>
<div id="revisions"> <div id="revisions">
</div> </div>
<div class="row-fluid"> <div class="row-fluid">
<div class="span12"> <div class="span12">
<button onclick="basic_conflict_solver.abort()">Abort</button> <button onclick="OfficeJS_basic_conflict_solver.abort();">Abort</button>
</div> </div>
</div> </div>
</div> </div>
<script type="text/javascript">
<!--
window.basic_conflict_solver = {
conflict_object:{},
addRevision: function (doc) {
document.querySelector ('#basic_conflict_solver_div #revisions').
innerHTML += '<div class="row-fluid"><div class="span12">'+
'<div>'+(new Date(doc.last_modified)).toString()+'</div>'+
'<div><textarea id="'+doc.revision+'">'+doc.content+'</textarea></div>'+
'<div><button onclick="'+
//'console.log('+"'"+revision+"'"+');'+
"basic_conflict_solver.keepRevision('"+doc.revision+"');"+
'">Save this one</button></div><hr/>'+
'</div></div>';
},
addRemovedRevision: function (doc) {
document.querySelector ('#basic_conflict_solver_div #revisions').
innerHTML += '<div class="row-fluid"><div class="span12">'+
'<div>'+(new Date(doc.last_modified)).toString()+'</div>'+
'<div>Removed</div>'+
'<div><button onclick="'+
//'console.log('+"'"+revision+"'"+');'+
"basic_conflict_solver.removeRevision();"+
'">Save this one</button></div><hr/>'+
'</div></div>';
},
removeRevision: function () {
OfficeJS.solveConflict(this.conflict_object);
},
keepRevision: function (revision) {
OfficeJS.solveConflict(
this.conflict_object,
$('#'+revision).text()
);
},
abort: function () {
OfficeJS.abortSolveConflict();
}
};
//-->
</script>
...@@ -32,7 +32,8 @@ ...@@ -32,7 +32,8 @@
</script> </script>
<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
<!-- <!--
$().ready(function() { (function () {
$().ready(function() {
var opts = { var opts = {
cssClass : 'el-rte', cssClass : 'el-rte',
lang : 'en', lang : 'en',
...@@ -41,7 +42,8 @@ $().ready(function() { ...@@ -41,7 +42,8 @@ $().ready(function() {
cssfiles : ['lib/elrte/css/elrte-inner.css'] cssfiles : ['lib/elrte/css/elrte-inner.css']
} }
$('#elrte_editor').elrte(opts); $('#elrte_editor').elrte(opts);
}) });
}());
//--> //-->
</script> </script>
</head> </head>
...@@ -49,12 +51,12 @@ $().ready(function() { ...@@ -49,12 +51,12 @@ $().ready(function() {
<div> <div>
<input type="text" <input type="text"
name="fileName" name="fileName"
id="input_file_name" id="elrte_docid"
value="" value=""
placeholder="File name here" />&nbsp; placeholder="File name here" />&nbsp;
<button type="submit" <button type="submit"
class="btn btn-primary" class="btn btn-primary"
onclick="OfficeJS.save($('#input_file_name').attr('value'));"> onclick="OfficeJS_elrte.save();">
<i class="icon-download-alt icon-white"></i> <i class="icon-download-alt icon-white"></i>
Save Save
</button>&nbsp; </button>&nbsp;
......
...@@ -59,101 +59,7 @@ ...@@ -59,101 +59,7 @@
<!--/Optional--> <!--/Optional-->
<script type="text/javascript"> <script type="text/javascript">
<!-- <!--
$(function(){ OfficeJS_jquerysheet.firstload();
//Here is where we initiate the sheets
//every time sheet is created it creates a new jQuery.sheet.instance
//(array), to manipulate each sheet, the jQuery object is returned
$('#jQuerySheet').sheet({
title: '',
inlineMenu: inlineMenu($.sheet.instance),
urlGet: 'component/newspreadsheet.html',
// buildSheet: true,
editable: true,
autoFiller: true
});
//examples of how to use jQuery.sheet
/*
//Inline sheet(s), non-editable (like a gridview)
$('.jQuerySheet').sheet({
title: 'jQuery.sheet - The Web Based Spreadsheet Demo',
buildSheet: true, //will turn object #jQuerySheet's child tables into sheets
editable: false,
calcOff: true
});
//New single custom sized sheet
$('#jQuerySheet').sheet({
title: 'jQuery.sheet - The Web Based Spreadsheet Demo',
inlineMenu: inlineMenu(jQuery.sheet.instance),
buildSheet: '5x100'
});
//Custom object sheet(s)
$('#jQuerySheet').sheet({
title: 'jQuery.sheet - The Web Based Spreadsheet Demo',
inlineMenu: inlineMenu(jQuery.sheet.instance),
buildSheet: $('#jQuerySheet').find('table')
});
//Custom object sheet(s)
$('#jQuerySheet').sheet({
title: 'jQuery.sheet - The Web Based Spreadsheet Demo',
inlineMenu: inlineMenu(jQuery.sheet.instance),
buildSheet: $.sheet.makeTable.fromSize('5x100').add($.sheet.makeTable.fromSize('5x100'))
});
*/
//This is to give a themeswitcher on the page
//$('#themeSwitcher').themeswitcher();
//This is for some fancy menu stuff
var o = $('#structures');
var top = o.offset().top - 300;
$(document).scroll(function(e){
if ($(this).scrollTop() > top) {
$('#lockedMenu').removeClass('locked');
}
else {
$('#lockedMenu').addClass('locked');
}
}).scroll();
});
//This function builds the inline menu to make it easy to interact with each sheet instance
function inlineMenu(I){
I = (I ? I.length : 0);
//we want to be able to edit the html for the menu to make them multi
//instance
var html = $('#inlineMenu').html().
replace(/sheetInstance/g,
"$.sheet.instance[" + I + "]");
var menu = $(html);
//The following is just so you get an idea of how to style cells
menu.find('.colorPickerCell').colorPicker().change(function(){
$.sheet.instance[I].cellChangeStyle('background-color', $(this).val());
});
menu.find('.colorPickerFont').colorPicker().change(function(){
$.sheet.instance[I].cellChangeStyle('color', $(this).val());
});
menu.find('.colorPickers').children().eq(1).
css('background-image',
"url('lib/jquery.sheet/images/palette.png')");
menu.find('.colorPickers').children().eq(3).
css('background-image',
"url('lib/jquery.sheet/images/palette_bg.png')");
return menu;
}
function goToObj(s){
$('html, body').animate({
scrollTop: $(s).offset().top
}, 'slow');
return false;
}
//--> //-->
</script> </script>
<!--Page styles--> <!--Page styles-->
...@@ -208,12 +114,12 @@ function goToObj(s){ ...@@ -208,12 +114,12 @@ function goToObj(s){
<div> <div>
<input type="text" <input type="text"
name="fileName" name="fileName"
id="input_file_name" id="jquery-sheet_docid"
value="" value=""
placeholder="File name here" />&nbsp; placeholder="File name here" />&nbsp;
<button type="submit" <button type="submit"
class="btn btn-primary" class="btn btn-primary"
onclick="OfficeJS.save($('#input_file_name').attr('value'));"> onclick="OfficeJS_jquerysheet.save();">
<i class="icon-download-alt icon-white"></i> <i class="icon-download-alt icon-white"></i>
Save Save
</button>&nbsp; </button>&nbsp;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<li> <li>
<a href="#/login" <a href="#/login"
onclick="javascript: onclick="javascript:
OfficeJS.open({app:'login'}); OfficeJS_left_nav_bar.login();
return false;"> return false;">
<i class="icon-ok"> <i class="icon-ok">
</i> </i>
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
<li class="texteditor left-nav-tools"> <li class="texteditor left-nav-tools">
<a href="#/texteditor" <a href="#/texteditor"
onclick="javascript: onclick="javascript:
OfficeJS.open({app:'text_editor'}); OfficeJS_left_nav_bar.newTextDocument();
return false;"> return false;">
<i class="icon-font"></i> <i class="icon-font"></i>
New Text Document New Text Document
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
<li class="imgeditor left-nav-tools"> <li class="imgeditor left-nav-tools">
<a href="#/imgeditor" <a href="#/imgeditor"
onclick="javascript: onclick="javascript:
OfficeJS.open({app:'img_editor'}); OfficeJS_left_nav_bar.newImage();
return false;"> return false;">
<i class="icon-pencil"></i> <i class="icon-pencil"></i>
New Image New Image
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
<li class="spreadsheet left-nav-tools"> <li class="spreadsheet left-nav-tools">
<a href="#/spreadsheet" <a href="#/spreadsheet"
onclick="javascript: onclick="javascript:
OfficeJS.open({app:'spreadsheet'}); OfficeJS_left_nav_bar.newSpreadSheet();
return false;"> return false;">
<i class="icon-signal"></i> <i class="icon-signal"></i>
New Spreadsheet New Spreadsheet
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
<li class="spreadsheet left-nav-tools"> <li class="spreadsheet left-nav-tools">
<a href="#/workinprogress" <a href="#/workinprogress"
onclick="javascript: onclick="javascript:
OfficeJS.open({app:'workinprogress'}); OfficeJS_left_nav_bar.showActivities();
return false;"> return false;">
<i class="icon-tasks"></i> <i class="icon-tasks"></i>
Show Activity Show Activity
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
<!-- <li class="editpreferences left-nav-tools"> --> <!-- <li class="editpreferences left-nav-tools"> -->
<!-- <a href="#/edit_preferences" --> <!-- <a href="#/edit_preferences" -->
<!-- onclick="javascript: --> <!-- onclick="javascript: -->
<!-- OfficeJS.open({app:'edit_preferences'}); --> <!-- OfficeJS_left_nav_bar.editPreference(); -->
<!-- return false;"> --> <!-- return false;"> -->
<!-- <i class="icon-check"></i> --> <!-- <i class="icon-check"></i> -->
<!-- Edit Preferences --> <!-- Edit Preferences -->
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
<li id="nav_document_list_header left-nav-tools"> <li id="nav_document_list_header left-nav-tools">
<a href="#/doclist" <a href="#/doclist"
onclick="javascript: onclick="javascript:
OfficeJS.open({app:'document_lister'}); OfficeJS_left_nav_bar.showDocumentList();
return false;"> return false;">
<i class="icon-list"></i> <i class="icon-list"></i>
Document List Document List
......
...@@ -14,61 +14,66 @@ ...@@ -14,61 +14,66 @@
<div> <div>
Remember me&nbsp;&nbsp; Remember me&nbsp;&nbsp;
<input id="remember_me" type="checkbox" <input id="remember_me" type="checkbox"
onclick="window.OfficeJS_login.toggleRememberMe();"/> onclick="OfficeJS_login.object.toggleRememberMe();"/>
</div> </div>
<div> <div>
<button type="submit" <button type="submit"
class="btn" class="btn"
onclick="window.OfficeJS_login.createJIO();"> onclick="OfficeJS_login.object.connect();">
Create New JIO Create New JIO
</button> </button>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
<!-- <!--
window.OfficeJS_login = { (function () {
storageId:'#login-gadget #login_input', "use strict";
storagePath:'OfficeJS/login/login', var odf = function (obj,name,value) {
rememberId:'#login-gadget #remember_me', Object.defineProperty(obj,name,{
rememberPath:'OfficeJS/login/remember_me', configurable:false,enumerable:false,writable:false,value:value
localStorage: LocalOrCookieStorage, });
};
fillLogin: function () { odf(OfficeJS_login,'object',{});
$(this.storageId).attr( var that = OfficeJS_login.object;
'value',this.localStorage.getItem(this.storagePath) || ''); odf(OfficeJS_login.object,'storage_id','#login-gadget #login_input');
}, odf(OfficeJS_login.object,'storage_path','OfficeJS/login/login');
odf(OfficeJS_login.object,'remember_id','#login-gadget #remember_me');
isRememberMe: function () { odf(OfficeJS_login.object,'remember_path','OfficeJS/login/remember_me');
return $(this.rememberId).attr('checked'); odf(OfficeJS_login.object,'fillLogin',function () {
}, $(that.storage_id).attr(
fillRememberMe: function () { 'value',localStorage.getItem(that.storage_path) || '');
var t = this.localStorage.getItem(this.rememberPath); });
odf(OfficeJS_login.object,'isRememberMe',function () {
return $(that.remember_id).attr('checked');
});
odf(OfficeJS_login.object,'fillRememberMe',function () {
var t = localStorage.getItem(that.remember_path);
if (t) { if (t) {
this.rememberMe(); that.rememberMe();
} }
}, });
rememberMe: function () { odf(OfficeJS_login.object,'rememberMe',function () {
$(this.rememberId).attr('checked','1'); $(that.remember_id).attr('checked','1');
this.localStorage.setItem(this.rememberPath,'1'); localStorage.setItem(that.remember_path,'1');
}, });
dontRememberMe: function () { odf(OfficeJS_login.object,'dontRememberMe',function () {
$(this.rememberId).removeAttr('checked'); $(that.remember_id).removeAttr('checked');
this.localStorage.deleteItem(this.rememberPath); localStorage.deleteItem(that.remember_path);
}, });
toggleRememberMe: function () { odf(OfficeJS_login.object,'toggleRememberMe',function () {
var t = this.localStorage.getItem(this.rememberPath); var t = localStorage.getItem(that.remember_path);
if (t) { this.dontRememberMe() } else { this.rememberMe(); } if (t) { that.dontRememberMe() } else { that.rememberMe(); }
}, });
odf(OfficeJS_login.object,'connect',function () {
createJIO: function() {
var spec = $('#login-gadget #login_input').attr('value'); var spec = $('#login-gadget #login_input').attr('value');
this.localStorage.setItem(this.storagePath,spec); localStorage.setItem(that.storage_path,spec);
OfficeJS.setJio(spec); OfficeJS_login.connect (spec);
});
that.fillRememberMe();
if (that.isRememberMe()) {
that.fillLogin();
} }
}; }());
window.OfficeJS_login.fillRememberMe();
if (window.OfficeJS_login.isRememberMe()) {
window.OfficeJS_login.fillLogin();
}
//--> //-->
</script> </script>
</div> </div>
...@@ -24,8 +24,15 @@ ...@@ -24,8 +24,15 @@
<i class="icon-remove icon-white"></i> <i class="icon-remove icon-white"></i>
Remove Selected Remove Selected
</button> </button>
<button type="submit"
id="slickgrid_document_lister_refresh"
class="btn"
onclick="OfficeJS_slickgrid.refresh();">
<i class="icon-refresh"></i>
Refresh
</button>
</div> </div>
<div id="myDocumentList" style="width:100%;height:300px"></div> <div id="slickgrid_documentlist" style="width:100%;height:300px"></div>
<script type="text/javascript" <script type="text/javascript"
src="lib/jquery/jquery.js"></script> src="lib/jquery/jquery.js"></script>
<script type="text/javascript" <script type="text/javascript"
...@@ -42,135 +49,7 @@ ...@@ -42,135 +49,7 @@
<script type="text/javascript"> <script type="text/javascript">
<!-- <!--
window.OfficeJS_slickgrid = {}; OfficeJS_slickgrid.load();
window.OfficeJS_slickgrid.reload = function () {
$('#myDocumentList').html('');
var grid, onSortFunction, onClickFunction, check_box_selector,
onRemoveSeveral, showIconFormatter,
document_list = OfficeJS.cloneCurrentDocumentList(),
columns = [],
options = {
enableCellNavigation: true,
enableColumnReorder: false,
multiColumnSort: true,
forceFitColumns: true
};
showIconFormatter = function (row,cell,value,columnDef,dataContext) {
return dataContext.icon;
};
(function (array) {
var i, lm, cd, split, mime;
for (i = 0; i < array.length; i += 1) {
// file names
split = array[i].name.split('.');
array[i].ext = '';
if (split.length > 1) {
array[i].ext = split[split.length-1];
split.length -= 1;
}
array[i].base_name = split.join('.');
// app & icon
mime = OfficeJS.getMimeOfExt (array[i].ext);
if (!mime) {
array[i].icon = '?';
array[i].app = 'text_editor';
} else {
array[i].icon = mime.icon;
array[i].app = mime.preferred_application || mime.application;
}
if (array[i].revision) {
array[i].conflict = array[i].revision_object[
array[i].revision].conflict?'X':'';
} else {
array[i].conflict = '';
}
// dates
// FIXME : we can have 2012/1/1 12:5
// we should have 2012/01/01 12:05
lm = (new Date(array[i].last_modified));
cd = (new Date(array[i].creation_date));
array[i].last_modified = lm.getFullYear()+'/'+
(lm.getMonth()+1)+'/'+lm.getDate()+' '+
lm.getHours()+':'+lm.getMinutes();
array[i].creation_date = cd.getFullYear()+'/'+
(cd.getMonth()+1)+'/'+cd.getDate()+' '+
cd.getHours()+':'+cd.getMinutes();
}
}(document_list));
$(function () {
check_box_selector = new Slick.CheckboxSelectColumn({
cssClass: "slick-cell-checkboxsel"
});
columns.push(check_box_selector.getColumnDefinition());
columns.push({id:"icon",name:"",field:"icon",
sortable:true,resizable:false,width:24,
formatter:showIconFormatter});
columns.push({id:"file_name",name:"Document",
field:"base_name",sortable:true});
columns.push({id:"last_modified",name:"Modified",
field:"last_modified",sortable:true});
columns.push({id:"creation_date",name:"Created",
field:"creation_date",sortable:true});
columns.push({id:'on_conflict',name:'',
field:'conflict',sortable:true,
resizable:false,width:24});
grid = new Slick.Grid("#myDocumentList",
document_list,
columns,
options);
grid.setSelectionModel(new Slick.RowSelectionModel(
{selectActiveRow: false}));
grid.registerPlugin(check_box_selector);
onSortFunction = function (e, args) {
var cols = args.sortCols;
document_list.sort(function (data_row1, data_row2) {
var i, l, field, sign, value1, value2, result;
for (i = 0, l = cols.length; i < l; i++) {
field = cols[i].sortCol.field;
sign = cols[i].sortAsc ? 1 : -1;
value1 = data_row1[field];
value2 = data_row2[field];
result = (value1==value2?0:(value1>value2?1:-1))*sign;
if (result != 0) {
return result;
}
}
return 0;
});
grid.invalidate();
grid.render();
};
onClickFunction = function (e) {
var cell = grid.getCellFromEvent(e);
if (cell.cell === grid.getColumnIndex('file_name')) {
OfficeJS.open({app:document_list[cell.row].app,
file_name:document_list[cell.row].name});
}
};
onRemoveSeveral = function () {
var document_name_array = [], selected, i, l;
selected = grid.getSelectedRows();
for (i = 0, l = selected.length; i < l; i+= 1) {
document_name_array.push(document_list[selected[i]].name);
}
OfficeJS.removeSeveralFromArray (document_name_array);
};
document.querySelector ('#slickgrid_document_lister_remove_selected').
onclick = onRemoveSeveral;
grid.onClick.subscribe(onClickFunction);
grid.onSort.subscribe(onSortFunction);
});
};
window.OfficeJS_slickgrid.reload();
//--> //-->
</script> </script>
</body> </body>
......
<div> <div>
<input type="text" <input type="text"
name="fileName" name="fileName"
id="input_file_name" id="svg-edit_docid"
value="" value=""
placeholder="File name here" />&nbsp; placeholder="File name here" />&nbsp;
<button type="submit" <button type="submit"
class="btn btn-primary" class="btn btn-primary"
onclick="OfficeJS.save($('#input_file_name').attr('value'));"> onclick="OfficeJS_svgedit.save();">
<i class="icon-download-alt icon-white"></i> <i class="icon-download-alt icon-white"></i>
Save Save
</button>&nbsp; </button>&nbsp;
</div> </div>
<iframe src="lib/svg-edit/svg-editor.html" <iframe src="lib/svg-edit/svg-editor.html"
id="svg_edit_frame" id="svg-edit_frame"
style="width:100%; style="width:100%;
height:500px;" height:500px;"
scrolling="no"> scrolling="no">
......
...@@ -44,11 +44,11 @@ ...@@ -44,11 +44,11 @@
<li><h1>OfficeJS</h1></li> <li><h1>OfficeJS</h1></li>
<li><a href="#/about" <li><a href="#/about"
onclick="javascript: onclick="javascript:
OfficeJS.open({app:'about'}); OfficeJS_top_nav_bar.about();
return false;">About</a></li> return false;">About</a></li>
<li><a href="#/contact" <li><a href="#/contact"
onclick="javascript: onclick="javascript:
OfficeJS.open({app:'contact'}); OfficeJS_top_nav_bar.contact();
return false;">Contact</a></li> return false;">Contact</a></li>
</ul> </ul>
</div> </div>
......
<h2>Activities</h2> <h2>Activities</h2>
<div id="activities"></div> <div id="workinprogress_activities"></div>
<script type="text/javascript">
<!--
(function() {
var id;
if (typeof work_in_progress !== 'object') {
id = null;
work_in_progress = {
start:function(){
if (id === null) {
var update = function () {
var act = OfficeJS.getActivity(), i, str = '';
for (i = 0; i < act.length; i+= 1) {
str += act[i] + '<br />';
}
if (str === '') {
str = 'There is no on going tasks.<br />';
}
document.getElementById('activities').innerHTML = str;
};
update();
id = setInterval (update, 200);
}
},
stop:function(){
if (id !== null) {
clearInterval(id);
id = null;
}
}
};
}
}());
//-->
</script>
(function () { (function (scope) {
// Tools "use strict";
var baseName = function (file_name) { var odf = function (obj,name,value) {
var split = file_name.split('.'); Object.defineProperty(obj,name,{
if (split.length > 1) { configurable:false,enumerable:false,writable:false,value:value
split.length -= 1; });
return split.join('.');
} else {
return file_name;
}
}; };
var JIO = jio; var OfficeJS = {};
//////////////////////////////////////////////////////////////////////
/** odf(OfficeJS,'env',{});
* OfficeJS Object odf(OfficeJS,'tmp',{});
*/ odf(OfficeJS,'system',{});
window.OfficeJS = (function () { odf(OfficeJS,'run',{});
var that = {}, priv = {}; odf(OfficeJS,'lib',{});
// Attributes // odf(OfficeJS,'command',{});
priv.preference_object = {
document_lister:'slickgrid', //////////////////////////////////////////////////////////////////////
edit_preferences:'simplepreferenceeditor',
text_editor:'elrte', OfficeJS.system.preferences = {};
img_editor:'svg-edit', OfficeJS.system.applications = {};
spreadsheet:'jquery-sheet' OfficeJS.system.mime = {};
}; OfficeJS.system.icon = {};
priv.conflict_solver_object = {
// ext: "solver_name" // Top Nav Bar //
// default: "basic_conflict_solver" OfficeJS.system.applications['top_nav_bar'] = {
// ... name: 'top_nav_bar',
componentpath: 'component/top_nav_bar.html',
gadgetid: 'page-top_nav_bar',
varname: 'OfficeJS_top_nav_bar',
api: {
about: function () {
OfficeJS.lib.openApplication(
OfficeJS.system.applications['about']);
},
contact: function () {
OfficeJS.lib.openApplication(
OfficeJS.system.applications['contact']);
}
},
lib: {
spin:function (state) {
OfficeJS.system.applications['top_nav_bar'].spin[state]();
},
endspin:function (state) {
OfficeJS.system.applications['top_nav_bar'].spin['end'+state]();
}
},
spin: {
spinstate: 0,
savestate: 0,
loadstate: 0,
getliststate: 0,
removestate: 0,
main: function (string){
if (this[string+'state'] === 0){
document.querySelector ('#loading_'+string).
style.display = 'block';
}
this[string+'state'] ++;
},
endmain: function (string){
if (this[string+'state']>0) {
this[string+'state']--;
}
if (this[string+'state']===0){
document.querySelector ('#loading_'+string).
style.display = 'none';
}
},
spin:function(){this.main('spin');},
save:function(){this.main('save');this.spin();},
load:function(){this.main('load');this.spin();},
getlist:function(){this.main('getlist');this.spin();},
remove:function(){this.main('remove');this.spin();},
endspin:function(){this.endmain('spin');},
endsave:function(){this.endmain('save');this.endspin();},
endload:function(){this.endmain('load');this.endspin();},
endgetlist:function(){this.endmain('getlist');this.endspin();},
endremove:function(){this.endmain('remove');this.endspin();}
}
}; };
priv.app_object = { // End Top Nav Bar //
topnavbar: {
type:'nav', // Left Nav Bar //
path:'component/top_nav_bar.html', OfficeJS.system.applications['left_nav_bar'] = {
gadget_id:'page-top_nav_bar' name: 'left_nav_bar',
}, componentpath: 'component/left_nav_bar.html',
leftnavbar: { gadgetid: 'page-left_nav_bar',
type:'nav', varname: 'OfficeJS_left_nav_bar',
path:'component/left_nav_bar.html', api: {
gadget_id:'page-left_nav_bar', login: function () {
bar_tools: false, OfficeJS.lib.openApplication(
update: function () { OfficeJS.system.applications['login']
);
},
newTextDocument: function () {
OfficeJS.lib.openApplication(
OfficeJS.lib.getAppFromPref('html-editor')
);
},
newImage: function () {
OfficeJS.lib.openApplication(
OfficeJS.lib.getAppFromPref('svg-editor')
);
},
newSpreadSheet: function () {
OfficeJS.lib.openApplication(
OfficeJS.lib.getAppFromPref('jqs-sheet')
);
},
showActivities: function () {
OfficeJS.lib.openApplication(
OfficeJS.lib.getAppFromPref('activities')
);
},
showDocumentList: function () {
OfficeJS.lib.openApplication(
OfficeJS.lib.getAppFromPref('documentlister')
);
}
},
lib:{
showTools: function () {
var elmt; var elmt;
if (priv.isJioSet() && !this.bar_tools) { if (OfficeJS.run.jio && !OfficeJS.tmp.tools_opened) {
// add tools to nav bar OfficeJS.tmp.tools_opened = true;
elmt = document.querySelector ('script#left-nav-tools'); elmt = document.querySelector ('script#left-nav-tools');
document.querySelector ('#left-nav-bar').innerHTML += document.querySelector ('#left-nav-bar').innerHTML +=
elmt.innerHTML; elmt.innerHTML;
this.bar_tools = true;
} }
} }
}, }
login: {
type:'loader',
path:'component/login.html',
gadget_id:'page-content',
getContent: function () {
var tmp = {
user_name: 'NoName',
password: 'NoPwd'
}; };
// NOTE : stringify or not ? // End Left Nav Bar //
return JSON.stringify (tmp);
} // login //
}, OfficeJS.system.applications['login'] = {
about: { name: 'login',
type:'viewer', componentpath: 'component/login.html',
path:'component/about.html', gadgetid: 'page-content',
gadget_id:'page-content' varname: 'OfficeJS_login',
}, api: {
contact: { connect: function (spec) {
type:'viewer', if (!OfficeJS.run.jio) {
path:'component/contact.html', if (typeof spec === 'string') {
gadget_id:'page-content' spec = JSON.parse (spec);
}, }
simplepreferenceeditor: { OfficeJS.run.jio = jio.newJio(spec);
// NOTE OfficeJS.system.applications['left_nav_bar'].
type:'editor', lib.showTools();
path:'' OfficeJS.lib.allDocs();
// ...
},
elrte: {
type:'editor', // means it can edit a content
path:'component/elrte.html',
gadget_id:'page-content',
ext:'html',
element:'#elrte_editor',
getContent: function () {
$(this.element).elrte('updateSource');
return $(this.element).elrte('val');
},
setContent: function (content) {
$(this.element).elrte('val', content);
},
onload: function (param) {
// FIXME : wait for initialization end
setTimeout(function () {
if (typeof param.file_name !== 'undefined') {
$('#input_file_name').attr('value',
baseName(param.file_name));
that.load(baseName(param.file_name));
} }
},1000);
} }
// TODO : onunload, are you sure? leave without saving? }
};
// End login //
// about //
OfficeJS.system.applications['about'] = {
type: 'about',
'class': 'viewer',
name: 'about',
componentpath: 'component/about.html',
gadgetid: 'page-content'
};
// End about //
// contact //
OfficeJS.system.applications['contact'] = {
type: 'contact',
'class': 'viewer',
name: 'contact',
componentpath: 'component/contact.html',
gadgetid: 'page-content'
};
// End contact //
// elRTE //
OfficeJS.system.applications['elrte'] = {
type: 'html-editor',
name: 'elrte',
'class': 'editor',
componentpath: 'component/elrte.html',
gadgetid: 'page-content',
varname: 'OfficeJS_elrte',
exts: ['html'],
default_ext: 'html',
docid_elmnt: '#elrte_docid',
editor_elmnt: '#elrte_editor',
api: {
save: function () {
var id, content;
id = OfficeJS.system.applications['elrte'].
lib.getDocId();
content = OfficeJS.system.applications['elrte'].
lib.getContent();
console.log ('content ' + content);
if (id) {
OfficeJS.lib.put({
_id:id+'.'+OfficeJS.system.applications['elrte'].
default_ext,
content:content||''
},function (err,val) {
setTimeout(function(){
OfficeJS.lib.allDocs();
});
});
}
}
},
lib: {
getDocId: function () {
return $(OfficeJS.system.applications['elrte'].docid_elmnt).
attr('value');
}, },
'jquery-sheet': {
type:'editor',
path:'component/jquery-sheet.html',
gadget_id:'page-content',
ext:'jqs',
getContent: function () { getContent: function () {
return JSON.stringify ( $(OfficeJS.system.applications['elrte'].editor_elmnt).
$.sheet.instance[0].exportSheet.json() elrte('updateSource');
); return $(OfficeJS.system.applications['elrte'].editor_elmnt).
elrte('val');
},
setDocId: function (docid) {
$(OfficeJS.system.applications['elrte'].docid_elmnt).
attr('value',docid);
}, },
setContent: function (content) { setContent: function (content) {
$('#jQuerySheet').sheet({ return $(OfficeJS.system.applications['elrte'].editor_elmnt).
title: '', elrte('val',content);
inlineMenu: inlineMenu($.sheet.instance), }
buildSheet: $.sheet.makeTable.json( },
JSON.parse(content) onload: function (doc) {
), if (doc) {
autoFiller: true setTimeout(function(){
OfficeJS.system.applications['elrte'].
lib.setDocId(OfficeJS.lib.basename(doc._id));
OfficeJS.system.applications['elrte'].
lib.setContent('loading...');
console.log ('get docid ' + doc._id);
OfficeJS.lib.get(doc._id,null,function (err,val) {
if (val) {
console.log ('receive ' + JSON.stringify (val));
OfficeJS.system.applications['elrte'].
lib.setContent(val.content);
} else {
// TODO :
}
}); });
},500); // FIXME :
}
}, },
onload: function (param) { update: function (content) {
// FIXME : wait for initialization end OfficeJS.system.applications['elrte'].lib.setContent (content);
setTimeout(function () { }
if (typeof param.file_name !== 'undefined') { };
$('#input_file_name').attr('value', OfficeJS.system.preferences['html-editor'] =
baseName(param.file_name)); OfficeJS.system.applications['elrte'];
that.load(baseName(param.file_name)); OfficeJS.system.mime['html'] = 'html-editor';
OfficeJS.system.icon['html'] = '<i class="icon-font"></i>';
// End elRTE //
// svg edit //
OfficeJS.system.applications['svg-edit'] = {
type: 'svg-editor',
name: 'svg-edit',
'class': 'editor',
componentpath: 'component/svg-edit.html',
gadgetid: 'page-content',
varname: 'OfficeJS_svgedit',
exts: ['svg'],
default_ext: 'svg',
docid_elmnt: '#svg-edit_docid',
editor_elmnt: '#svg-edit_frame',
api: {
save: function () {
var id, content;
id = OfficeJS.system.applications['svg-edit'].
lib.getDocId();
content = OfficeJS.system.applications['svg-edit'].
lib.getContent();
if (id) {
OfficeJS.lib.put({
_id:id+'.'+OfficeJS.system.applications['svg-edit'].
default_ext,
content:content||''
},function (err,val) {
setTimeout(function(){
OfficeJS.lib.allDocs();
});
});
} }
},1000);
} }
}, },
'svg-edit': { lib:{
type:'editor', getDocId: function () {
path:'component/svg-edit.html', return $(OfficeJS.system.applications['svg-edit'].docid_elmnt).
gadget_id:'page-content', attr('value');
ext:'svg', },
frameid:'svg_edit_frame', setDocId: function (docid) {
$(OfficeJS.system.applications['svg-edit'].docid_elmnt).
attr('value',docid);
},
getContent: function () { getContent: function () {
return document.getElementById (this.frameid). return document.querySelector (
OfficeJS.system.applications['svg-edit'].editor_elmnt).
contentWindow.svgCanvas.getSvgString(); contentWindow.svgCanvas.getSvgString();
}, },
setContent: function (content) { setContent: function (content) {
document.getElementById (this.frameid). return document.querySelector (
OfficeJS.system.applications['svg-edit'].editor_elmnt).
contentWindow.svgCanvas.setSvgString(content); contentWindow.svgCanvas.setSvgString(content);
}
}, },
onload: function (param) { onload: function (doc) {
var waitForInit = function (fun) { if (doc) {
// FIXME : wait for init end setTimeout(function(){
setTimeout(fun,1000); OfficeJS.system.applications['svg-edit'].
lib.setDocId(OfficeJS.lib.basename(doc._id));
OfficeJS.lib.get(doc._id,null,function (err,val) {
if (val) {
OfficeJS.system.applications['svg-edit'].
lib.setContent(val.content);
} else {
// TODO :
}
});
},500); // FIXME :
} }
waitForInit(function () {
if (typeof param.file_name !== 'undefined') {
$('#input_file_name').attr('value',
baseName(param.file_name));
that.load(baseName(param.file_name));
} }
};
OfficeJS.system.preferences['svg-editor'] =
OfficeJS.system.applications['svg-edit'];
OfficeJS.system.mime['svg'] = 'svg-editor';
OfficeJS.system.icon['svg'] = '<i class="icon-pencil"></i>';
// End svg edit //
// jquery-sheet //
OfficeJS.system.applications['jquery-sheet'] = {
type: 'jqs-sheet',
name: 'jquery-sheet',
'class': 'editor',
componentpath: 'component/jquery-sheet.html',
gadgetid: 'page-content',
varname: 'OfficeJS_jquerysheet',
exts: ['jqs'],
default_ext: 'jqs',
docid_elmnt: '#jquery-sheet_docid',
sheet_elmnt: '#jQuerySheet',
api: {
save: function () {
var id, content;
id = OfficeJS.system.applications['jquery-sheet'].
lib.getDocId();
content = OfficeJS.system.applications['jquery-sheet'].
lib.getContent();
if (id) {
OfficeJS.lib.put({
_id:id+'.'+OfficeJS.system.applications['jquery-sheet'].
default_ext,
content:content||''
},function (err,val) {
setTimeout(function(){
OfficeJS.lib.allDocs();
});
}); });
} }
}, },
slickgrid: { firstload: function () {
type:'editor', OfficeJS.system.applications['jquery-sheet'].lib.firstload();
path:'component/slickgrid_document_lister.html',
gadget_id:'page-content',
interval_id:null,
onload: function () {
var t = this;
if (this.interval_id === null) {
this.interval_id = setInterval (function() {
that.getList(t.update);
}, 5000);
} }
}, },
update: function () { lib:{
window.OfficeJS_slickgrid.reload(); getDocId: function () {
return $(OfficeJS.system.applications['jquery-sheet'].
docid_elmnt).attr('value');
}, },
onunload: function () { setDocId: function (docid) {
if (this.interval_id !== null) { $(OfficeJS.system.applications['jquery-sheet'].
clearInterval (this.interval_id); docid_elmnt).attr('value',docid);
this.interval_id = null;
}
delete window.OfficeJS_slickgrid;
return true;
}
}, },
workinprogress: { getContent: function () {
type:'viewer', return JSON.stringify (
path:'component/workinprogress.html', $.sheet.instance[0].exportSheet.json()
gadget_id:'page-content', );
onload: function () { },
var i = null, wait = function() { setContent: function (content) {
// wait for workinprogress initialization end. return $(OfficeJS.system.applications['jquery-sheet'].
if (window.work_in_progress) { sheet_elmnt).sheet({
window.work_in_progress.start(); title: '',
clearInterval(i); inlineMenu: OfficeJS.system.applications[
'jquery-sheet'].lib.inlineMenu(
$.sheet.instance),
buildSheet: $.sheet.makeTable.json(
JSON.parse (content)),
autoFiller: true
});
},
//This function builds the inline menu to make it easy to
//interact with each sheet instance
inlineMenu: function (I) {
I = (I ? I.length : 0);
//we want to be able to edit the
//html for the menu to make them multi
//instance
var html = $('#inlineMenu').html().
replace(/sheetInstance/g,
"$.sheet.instance[" + I + "]");
var menu = $(html);
//The following is just so you get an idea of how to style cells
menu.find('.colorPickerCell').colorPicker().change(function(){
$.sheet.instance[I].cellChangeStyle(
'background-color', $(this).val());
});
menu.find('.colorPickerFont').colorPicker().change(function(){
$.sheet.instance[I].cellChangeStyle('color', $(this).val());
});
menu.find('.colorPickers').children().eq(1).
css('background-image',
"url('lib/jquery.sheet/images/palette.png')");
menu.find('.colorPickers').children().eq(3).
css('background-image',
"url('lib/jquery.sheet/images/palette_bg.png')");
return menu;
},
firstload: function () {
//Here is where we initiate the sheets
//every time sheet is created it creates a new
//jQuery.sheet.instance
//(array), to manipulate each sheet,
//the jQuery object is returned
$('#jQuerySheet').sheet({
title: '',
inlineMenu: OfficeJS.system.applications[
'jquery-sheet'].lib.inlineMenu($.sheet.instance),
urlGet: 'component/newspreadsheet.html',
// buildSheet: true,
editable: true,
autoFiller: true
});
//This is for some fancy menu stuff
var o = $('#structures');
var top = o.offset().top - 300;
$(document).scroll(function(e){
if ($(this).scrollTop() > top) {
$('#lockedMenu').removeClass('locked');
} }
else {
$('#lockedMenu').addClass('locked');
} }
i = setInterval (wait,100); }).scroll();
},
onunload: function () {
window.work_in_progress.stop();
delete window.work_in_progress;
return true;
} }
}, },
basic_conflict_solver: { onload: function (doc) {
type:'solver', if (doc) {
path:'component/basic_conflict_solver.html', setTimeout(function(){
gadget_id:'page-conflict', OfficeJS.system.applications['jquery-sheet'].
onload: function (param) { lib.setDocId(OfficeJS.lib.basename(doc._id));
var rev_list = [], i; OfficeJS.lib.get(doc._id,null,function (err,val) {
for (var rev in param.conflict_object.revision_object) { if (val) {
rev_list.push(rev); OfficeJS.system.applications['jquery-sheet'].
} lib.setContent(val.content);
// FIXME : load jobs are in conflict ! redesign jio !
var load = function (rev,i) {
if (rev) {
i++;
setTimeout(function() {
priv.jio.loadDocument(
param.conflict_object.path,{
revision: rev,
max_retry:3,
success: function (result) {
var doc = {
path:param.conflict_object.path,
content:result.content,
last_modified:result.last_modified,
creation_date:result.creation_date,
revision:rev
};
window.basic_conflict_solver.
conflict_object =
param.conflict_object;
window.basic_conflict_solver.
addRevision(doc);
load(rev_list[i],i);
},
error: function (error) {
var doc = {
path:param.conflict_object.path,
revision:rev
};
window.basic_conflict_solver.
conflict_object =
param.conflict_object;
if (error.status === 404) {
window.basic_conflict_solver.
addRemovedRevision(doc);
} else { } else {
console.error (error.message); // TODO :
}
load(rev_list[i],i);
} }
}); });
}); },500); // FIXME :
} }
};
load (rev_list[0],0);
// NOTE : improve, don't load already loaded revision
} }
}
};
priv.mime_object = {
// <preferred_application> if the name of the app set in
// preferences.
// If <preferred_application> does not exist it means that the
// extension is very specific, so <application> is called instead of
// the default editor.
// NOTE : the icon may be set in the app in app_object.
html:{preferred_application:'text_editor',application:'elrte',
icon:'<i class="icon-font"></i>'},
svg:{preferred_application:'img_editor',application:'svg-edit',
icon:'<i class="icon-pencil"></i>'},
jqs:{application:'jquery-sheet',
icon:'<i class="icon-signal"></i>'}
};
priv.data_object = {
documentList:[],
gadget_object:{}, // contains current gadgets id with their location
currentFile:null,
currentEditor:null,
currentSolver:null,
currentApp:null,
currentActivity:null,
currentRevision:null
}; };
priv.loading_object = { OfficeJS.system.preferences['jqs-sheet'] =
spinstate: 0, OfficeJS.system.applications['jquery-sheet'];
savestate: 0, OfficeJS.system.mime['jqs'] = 'jqs-sheet';
loadstate: 0, OfficeJS.system.icon['jqs'] = '<i class="icon-signal"></i>';
getliststate: 0, // End jquery-sheet //
removestate: 0,
main: function (string){ // slickgrid //
if (this[string+'state'] === 0){ OfficeJS.system.applications['slickgrid'] = {
document.querySelector ('#loading_'+string). type: 'documentlister',
style.display = 'block'; name: 'slickgrid',
} 'class': 'viewer',
this[string+'state'] ++; componentpath: 'component/slickgrid_document_lister.html',
gadgetid: 'page-content',
varname: 'OfficeJS_slickgrid',
list_elmnt: '#slickgrid_documentlist',
api: {
load: function () {
setTimeout (function () {
try {
OfficeJS.tmp.slick_reload = 0;
OfficeJS.system.applications['slickgrid'].lib.reload();
} catch (e) {} // avoid reload the wrong component
});
}, },
end_main: function (string){ refresh: function () {
if (this[string+'state']>0) { OfficeJS.lib.allDocs(function (err,val) {
this[string+'state']--; if (val) {
try {
OfficeJS.tmp.slick_reload = 0;
OfficeJS.system.applications['slickgrid'].
lib.reload();
} catch (e) {} // avoid reload the wrong component
} else {
// TODO :
} }
if (this[string+'state']===0){ });
document.querySelector ('#loading_'+string).
style.display = 'none';
} }
}, },
spin:function(){this.main('spin');}, lib:{
save:function(){this.main('save');this.spin();}, reload: function () {
load:function(){this.main('load');this.spin();}, var grid, onSortFunction, onClickFunction,
getlist:function(){this.main('getlist');this.spin();}, check_box_selector, i, array,
remove:function(){this.main('remove');this.spin();}, onRemoveSeveral,showIconFormatter,
end_spin:function(){this.end_main('spin');}, document_list,columns,options;
end_save:function(){this.end_main('save');this.end_spin();},
end_load:function(){this.end_main('load');this.end_spin();},
end_getlist:function(){this.end_main('getlist');this.end_spin();},
end_remove:function(){this.end_main('remove');this.end_spin();}
};
priv.lastfailure = {};
// Initializer //
priv.init = function() {
};
// Methods // if (!OfficeJS.tmp.documentlist) {
/** if (OfficeJS.tmp.slick_reload === 3) { return; }
* Shows a list of document inside the left nav bar setTimeout(function() {
* @method showDocumentListInsideLeftNavBar OfficeJS.tmp.slick_reload =
*/ OfficeJS.tmp.slick_reload?
priv.showDocumentListInsideLeftNavBar = function () { OfficeJS.tmp.slick_reload++:1;
$('#nav_document_list_header').show(); OfficeJS.system.applications['slickgrid'].lib.reload();
}; },100);
return;
}
/** $(OfficeJS.system.applications['slickgrid'].
* @method getRealApplication list_elmnt).html('');
* @param {string} appname The app name set in preference. document_list = OfficeJS.tmp.documentlist;
* @return {object} The real application object. options = {
*/ enableCellNavigation: true,
priv.getRealApplication = function (appname) { enableColumnReorder: false,
var realappname = that.getPreference (appname); multiColumnSort: true,
if (!realappname) { forceFitColumns: true
return priv.app_object[appname];
}
return priv.app_object[realappname];
}; };
showIconFormatter = function (
/** row,cell,value,columnDef,dataContext) {
* @method isJioSet return dataContext.icon;
* @return {boolean} true if jio is set else false.
*/
priv.isJioSet = function () {
return (typeof priv.jio === 'object');
}; };
// make array
/** array = [];
* Opens an application for (i = 0; i < document_list.total_rows; i+= 1) {
* @method open var arrayi = {}, lm, cd, j;
* @param {object} option Contains some settings: arrayi.id = document_list.rows[i].id;
* - app {string} The app name we want to open, set in preferences arrayi.basename = OfficeJS.lib.basename(arrayi.id);
* - force {boolean} To reload applications even if it is the same. arrayi.ext = OfficeJS.lib.extOf(arrayi.id);
* (optional) if (arrayi.ext) {
* - ... and some other parameters arrayi.icon = OfficeJS.system.icon[arrayi.ext] || '?';
*/ arrayi.app = OfficeJS.lib.getAppFromMime(arrayi.ext) ||
that.open = function (option) { OfficeJS.lib.getAppFromPref('html-editor');
var realapp, realgadgetid, realpath, acientapp; } else {
if (!option) { arrayi.icon = '?';
console.error ('open: This function needs a parameter'); arrayi.app = OfficeJS.lib.getAppFromPref('html-editor');
return null; }
if (document_list.conflicts) {
arrayi.conflict = '';
for (j = 0;
j < document_list.conflicts.total_rows;
j+= 1) {
if (document_list.conflicts.rows[j].id ===
arrayi.id) {
var row = document_list.conflicts.rows[j];
arrayi.conflict = 'X';
arrayi.showConflict = function () {
console.log ('showConflict');
OfficeJS.lib.openApplication(
OfficeJS.lib.getAppFromPref(
'conflictsolver'),
{_id:arrayi.id,row:row} // wrong
);
}; };
realapp = priv.getRealApplication (option.app);
if (!realapp) {
// cannot get real app
console.error ('Unknown application: ' + option.app);
return null;
}
realgadgetid = option.gadget_id || realapp.gadget_id;
realpath = realapp.path;
if (option.force || priv.data_object.currentEditor !== realapp) {
ancientapp = priv.data_object.gadget_object[realgadgetid];
if (ancientapp) {
// if there is already a gadget there, unload it
if (typeof ancientapp.onunload !== 'undefined' &&
!ancientapp.onunload()) {
// if onunload return false, it means that we must not
// load a new gadget because this one is not ready to
// exit.
return null;
}
}
priv.data_object.gadget_object[realgadgetid] = realapp;
TabbularGadget.addNewTabGadget(realpath,realgadgetid);
// set current editor
switch (realapp.type) {
case 'editor':
priv.data_object.currentEditor = realapp;
break;
case 'solver':
priv.data_object.currentSolver = realapp;
break;
default:
break; break;
} }
priv.data_object.currentApp = realapp;
} }
// onload call
if (typeof realapp.onload !== 'undefined') {
return realapp.onload(option);
} }
// dates
// FIXME : we can have 2012/1/1 12:5
// we should have 2012/01/01 12:05
lm = (new Date(document_list.rows[i].value._last_modified));
cd = (new Date(document_list.rows[i].value._creation_date));
arrayi.last_modified = lm.getFullYear()+'/'+
(lm.getMonth()+1)+'/'+lm.getDate()+' '+
lm.getHours()+':'+lm.getMinutes();
arrayi.creation_date = cd.getFullYear()+'/'+
(cd.getMonth()+1)+'/'+cd.getDate()+' '+
cd.getHours()+':'+cd.getMinutes();
array.push(arrayi);
}
check_box_selector = new Slick.CheckboxSelectColumn({
cssClass: "slick-cell-checkboxsel"
});
columns = [];
columns.push(check_box_selector.getColumnDefinition());
columns.push({id:"icon",name:"",field:"icon",
sortable:true,resizable:false,width:24,
formatter:showIconFormatter});
columns.push({id:"file_name",name:"Document",
field:"basename",sortable:true});
columns.push({id:"last_modified",name:"Modified",
field:"last_modified",sortable:true});
columns.push({id:"creation_date",name:"Created",
field:"creation_date",sortable:true});
if (document_list.conflicts) {
columns.push({id:'on_conflict',name:'',
field:'conflict',sortable:true,
resizable:false,width:24});
}
grid = new Slick.Grid(
OfficeJS.system.applications['slickgrid'].list_elmnt,
array,columns,options);
grid.setSelectionModel(new Slick.RowSelectionModel(
{selectActiveRow: false}));
grid.registerPlugin(check_box_selector);
onSortFunction = function (e, args) {
var cols = args.sortCols;
document_list.sort(function (data_row1, data_row2) {
var i, l, field, sign, value1, value2, result;
for (i = 0, l = cols.length; i < l; i++) {
field = cols[i].sortCol.field;
sign = cols[i].sortAsc ? 1 : -1;
value1 = data_row1[field];
value2 = data_row2[field];
result = (value1==value2?0:
(value1>value2?1:-1))*sign;
if (result != 0) {
return result;
}
}
return 0;
});
grid.invalidate();
grid.render();
}; };
onClickFunction = function (e) {
/** var cell = grid.getCellFromEvent(e);
* Load an empty page in the place of a specific gadget id if (cell.cell === grid.getColumnIndex('file_name')) {
* @method closeGadgetId OfficeJS.lib.openApplication(
* @param {string} gadgetid The gadget id array[cell.row].app,{_id:array[cell.row].id});
*/ } else if (cell.cell ===
that.closeGadgetId = function (gadgetid) { grid.getColumnIndex('on_conflict')) {
TabbularGadget.addNewTabGadget('component/empty.html',gadgetid); array[cell.row].showConflict?
}; array[cell.row].showConflict():true;
}
/**
* @method getPreference
* @param {string} key The preference
* @return {string} The content of the preference.
*/
that.getPreference = function (key) {
return priv.preference_object[key];
};
/**
* @method getContentOf
* @param {string} app The application name
* @return {string} The content of the application, or null.
*/
that.getContentOf = function (app) {
var realapp = priv.getRealApplication (app);
if (!realapp) {
console.error ('Unknown application: ' + app);
return null;
}
if (typeof realapp.getContent !== 'undefined') {
return realapp.getContent();
}
return null;
}; };
onRemoveSeveral = function () {
/** var document_name_array = [], selected, i, l, cpt = 0;
* @method getPathOf selected = grid.getSelectedRows();
* @param {string} app The application name for (i = 0, l = selected.length; i < l; i+= 1) {
* @return {string} The path of the application component, or null. OfficeJS.lib.remove(
*/ {_id:document_list.rows[selected[i]].id},'last',
that.getPathOf = function (app) { function (err,val) {
var realapp = priv.getRealApplication (app); cpt ++;
if (!realapp) { if (l === cpt) {
console.error ('Unknown application: ' + app); OfficeJS_slickgrid.refresh();
return null; }
} });
return realapp.path; }
}; };
document.querySelector (
/** '#slickgrid_document_lister_remove_selected').
* Returns the current editor file extension. onclick = onRemoveSeveral;
* @return {string} The current editor file extension. document.querySelector (
*/ '#slickgrid_document_lister_refresh').
that.getExt = function () { onclick = OfficeJS_slickgrid.refresh;
return priv.data_object.currentEditor.ext; grid.onClick.subscribe(onClickFunction);
grid.onSort.subscribe(onSortFunction);
}
},
update: function () {
OfficeJS.system.applications['slickgrid'].lib.reload();
}
}; };
OfficeJS.system.preferences['documentlister'] =
OfficeJS.system.applications['slickgrid'];
// End slickgrid //
/** // work in progress //
* Returns a clone of the mime object having this file [extension]. OfficeJS.system.applications['workinprogress'] = {
* @method getMimeOfExt type: 'activities',
* @param {string} extension The extension without '.'. name: 'workinprogress',
* @return {object} A clone of the mime object 'class': 'viewer',
*/ componentpath: 'component/workinprogress.html',
that.getMimeOfExt = function (extension) { gadgetid: 'page-content',
if (typeof priv.mime_object[extension] === 'undefined') { main_elmnt: '#workinprogress_activities',
return null; api: {},
} lib:{
return $.extend (true,{},priv.mime_object[extension]); id: null,
start: function () {
if (OfficeJS.system.applications['workinprogress'].
lib.id === null) {
var update = function () {
var act = OfficeJS.run.jio.getJobArray(), i, str = '';
for (i = 0; i < act.length; i+= 1) {
str += act[i].command.label +' try number '+
act[i].command.tried + '<br />';
}
if (OfficeJS.tmp.lastfailure) {
str += '<span style="color:red;">Last failure: '+
OfficeJS.tmp.lastfailure.label +
', status: '+OfficeJS.tmp.lastfailure.status+
', reason: '+OfficeJS.tmp.lastfailure.reason+
'</span><br/>';
}
if (str === '') {
str = 'There is no on going tasks.<br />';
}
document.querySelector (
OfficeJS.system.applications['workinprogress'].
main_elmnt).innerHTML = str;
}; };
update();
/** OfficeJS.system.applications['workinprogress'].
* @method setJio lib.id = setInterval (update, 200);
* @param {object} storage The storage informations }
*/ },
that.setJio = function (storage) { stop: function () {
var leftnavbar; if (OfficeJS.system.applications['workinprogress'].
if (priv.isJioSet()) { lib.id !== null) {
alert ('Jio already set.'); clearInterval(OfficeJS.system.applications[
return; 'workinprogress'].lib.id);
OfficeJS.system.applications['workinprogress'].
lib.id = null;
} }
// if there is not any jio created
priv.jio = JIO.newJio (JSON.parse(storage));
// update left nav bar
leftnavbar = priv.getRealApplication ('leftnavbar');
if (typeof leftnavbar.update !== 'undefined') {
leftnavbar.update();
} }
that.getList(); },
onload: function () {
setTimeout(function(){
OfficeJS.system.applications['workinprogress'].lib.start();
},50);
},
onunload: function () {
OfficeJS.system.applications['workinprogress'].lib.stop();
return true;
}
}; };
OfficeJS.system.preferences['activities'] =
OfficeJS.system.applications['workinprogress'];
// End work in progress //
/** // basic conflict solver //
* Returns the array list in priv.data_object OfficeJS.system.applications['basic_conflict_solver'] = {
* @method getList type: 'conflictsolver',
* @param {function} callback Another callback called after retrieving 'class': 'editor',
* the list. (optional) name: 'basic_conflict_solver',
*/ componentpath: 'component/basic_conflict_solver.html',
that.getList = function (callback) { gadgetid: 'page-conflict',
if (!priv.isJioSet()) { varname: 'OfficeJS_basic_conflict_solver',
console.error ('No Jio set yet.'); docid_elmnt: '#basic_conflict_solver_docid',
return; main_elmnt: '#basic_conflict_solver_div',
api: {
abort: function () {
OfficeJS.lib.openApplication(
OfficeJS.system.applications['close_conflict_solver']);
},
removeRevision: function () {
OfficeJS.system.applications['top_nav_bar'].lib.spin('remove');
OfficeJS.tmp.basic_conflict_solver_current_conflict.value.
_solveConflict(
{conflicts:true,revs:true,revs_info:true},
function (err,val) {
OfficeJS.system.applications['top_nav_bar'].lib.
endspin('remove');
if (err && err.conflicts.total_rows > 0) {
OfficeJS.lib.openApplication(
OfficeJS.lib.getAppFromPref(
'conflictsolver'));
}
OfficeJS.lib.allDocs ( function () {
if (OfficeJS.tmp['page-content'].type ===
'documentlister') {
OfficeJS.tmp['page-content'].update?
OfficeJS.tmp['page-content'].update():
true;
}
});
if (OfficeJS.tmp['page-content']['class'] ===
'editor') {
OfficeJS.tmp['page-content'].update?
OfficeJS.tmp['page-content'].update(''):
true;
} }
priv.loading_object.getlist(); });
priv.jio.getDocumentList( OfficeJS.system.applications['basic_conflict_solver'].
'.',{ api.abort();
sort:{last_modified:'descending', },
name:'ascending'}, keepRevision: function (revision) {
limit:{begin:0,end:50}, var content = $('#'+revision).text();
// search:{name:'a'}, OfficeJS.system.applications['top_nav_bar'].lib.spin('save');
max_retry:3, OfficeJS.tmp.basic_conflict_solver_current_conflict.value.
success: function (result) { _solveConflict(
priv.data_object.documentList = result; content,
priv.showDocumentListInsideLeftNavBar(); {conflicts:true,revs:true,revs_info:true},
priv.loading_object.end_getlist(); function (err,val) {
if (typeof callback === 'function') { OfficeJS.system.applications['top_nav_bar'].lib.
callback(); endspin('save');
if (err && err.conflicts.total_rows > 0) {
OfficeJS.lib.openApplication(
OfficeJS.lib.getAppFromPref(
'conflictsolver'));
}
OfficeJS.lib.allDocs ( function () {
if (OfficeJS.tmp['page-content'].type ===
'documentlister') {
OfficeJS.tmp['page-content'].update?
OfficeJS.tmp['page-content'].update():
true;
}
});
if (OfficeJS.tmp['page-content']['class'] ===
'editor') {
OfficeJS.tmp['page-content'].update?
OfficeJS.tmp['page-content'].update(
content):
true;
}
});
OfficeJS.system.applications['basic_conflict_solver'].
api.abort();
} }
}, },
error: function (error) { lib:{
priv.lastfailure.path = '.'; addRevision: function (doc) {
priv.lastfailure.method = 'getDocumentList'; setTimeout( function () {
console.error (error.message); document.querySelector (OfficeJS.system.applications[
priv.loading_object.end_getlist(); 'basic_conflict_solver'].main_elmnt+' #revisions').
if (typeof callback === 'function') { innerHTML += '<div class="row-fluid"><div class="span12">'+
callback(); '<div>'+(new Date(doc._last_modified)).toString()+'</div>'+
'<div><textarea id="'+doc._rev+'">'+doc.content+
'</textarea></div>'+
'<div><button onclick="'+
//'console.log('+"'"+revision+"'"+');'+
"OfficeJS_basic_conflict_solver.keepRevision('"+doc._rev+"');"+
'">Save this one</button></div><hr/>'+
'</div></div>';
},50);
},
addRemovedRevision: function (doc) {
setTimeout( function () {
document.querySelector (OfficeJS.system.applications[
'basic_conflict_solver'].main_elmnt+' #revisions').
innerHTML += '<div class="row-fluid"><div class="span12">'+
'<div>'+(new Date(doc._last_modified)).toString()+'</div>'+
'<div>Removed</div>'+
'<div><button onclick="'+
//'console.log('+"'"+revision+"'"+');'+
"OfficeJS_basic_conflict_solver.removeRevision();"+
'">Save this one</button></div><hr/>'+
'</div></div>';
},50);
} }
},
onload: function (doc) {
// doc.row
OfficeJS.tmp.basic_conflict_solver_current_conflict = doc.row;
setTimeout(function(){
document.querySelector (
OfficeJS.system.applications[
'basic_conflict_solver'].docid_elmnt
).textContent = doc._id;
},50); // FIXME : wait for init end
console.log (OfficeJS.tmp.basic_conflict_solver_current_conflict);
var i;
for (i = 0; i < OfficeJS.tmp.basic_conflict_solver_current_conflict.
key.length; i+= 1) {
console.log ('a');
OfficeJS.system.applications['top_nav_bar'].lib.spin('load');
OfficeJS.lib.get(
doc._id,
OfficeJS.tmp.basic_conflict_solver_current_conflict.key[i],
function (err,val) {
OfficeJS.system.applications['top_nav_bar'].lib.
endspin('load');
if (val) {
OfficeJS.system.applications[
'basic_conflict_solver'].
lib.addRevision(val);
} else if (err && err.status === 404) {
OfficeJS.system.applications[
'basic_conflict_solver'].
lib.addRemovedRevision(err);
} }
}); });
}
}
}; };
OfficeJS.system.preferences['conflictsolver'] =
OfficeJS.system.applications['basic_conflict_solver'];
// End basic conflict solver //
that.cloneCurrentDocumentList = function () { OfficeJS.system.applications['close_conflict_solver'] = {
// clone document list componentpath: 'component/empty.html',
return $.extend(true,[],priv.data_object.documentList); gadgetid: 'page-conflict'
}; };
//////////////////////////////////////////////////////////////////////
/** odf(OfficeJS.lib,'basename',function (docid) {
* Saves the document. var basename = docid.split('.').slice(0,-1).join('.');
* @method save if (basename === '') {
* @param {string} basename The document name without ext. return docid;
*/
that.save = function (basename) {
var current_editor = priv.data_object.currentEditor,
current_content = current_editor.getContent();
if (!priv.isJioSet()) {
console.error ('No Jio set yet.');
return;
} }
priv.loading_object.save(); return basename;
priv.jio.saveDocument( });
basename+'.'+current_editor.ext, odf(OfficeJS.lib,'extOf',function (docid) {
current_content,{ var ext = docid.split('.').splice(-1)[0];
previous_revision: priv.data_object.currentRevision || '0', if (ext === docid) {
success: function (result) { return '';
if (result && result.revision) {
priv.data_object.currentRevision = result.revision;
} }
priv.loading_object.end_save(); return ext;
that.getList(); });
}, odf(OfficeJS.lib,'put',function (doc,callback) {
error: function (error) { if (OfficeJS.run.jio) {
priv.lastfailure.path = basename; if (OfficeJS.tmp[doc._id + ' knownrevision']) {
priv.lastfailure.method = 'saveDocument'; doc._rev = OfficeJS.tmp[doc._id + ' knownrevision'];
console.error (error.message); }
priv.loading_object.end_save(); OfficeJS.system.applications['top_nav_bar'].lib.spin('save');
that.getList(); OfficeJS.run.jio.put(
if (error.conflict_object) { doc,{conflicts:true,revs:true,revs_info:true},
priv.onConflict (error.conflict_object); function (err,val) {
OfficeJS.system.applications['top_nav_bar'].lib.
endspin('save');
OfficeJS.tmp[doc._id + ' knownrevision'] =
(err||val||{rev:undefined}).rev;
if (err) {
OfficeJS.tmp.lastfailure =
OfficeJS.lib.cloneObjectRoot(err);
OfficeJS.tmp.lastfailure.label = 'put';
OfficeJS.tmp.lastfailure.docid = doc._id;
}
if ((err||val).conflicts &&
(err||val).conflicts.total_rows > 0) {
OfficeJS.lib.openApplication(
OfficeJS.lib.getAppFromPref(
'conflictsolver'),
{_id:doc._id,row:(err||val).conflicts.rows[0]}
);
} }
callback?callback(err,val):true;
}
);
} }
}); });
}; odf(OfficeJS.lib,'get',function (docid,rev,callback) {
if (OfficeJS.run.jio) {
/** var opts = {conflicts:true,revs:true,revs_info:true,max_retry:3};
* Loads a document. if (rev) {
* @method load opts.rev = rev;
* @param {string} basename The document name without ext. }
*/ OfficeJS.system.applications['top_nav_bar'].lib.spin('load');
that.load = function (basename) { OfficeJS.run.jio.get(
var current_editor = priv.data_object.currentEditor; docid,opts,
if (!priv.isJioSet()) { function (err,val) {
console.error ('No Jio set yet.'); OfficeJS.system.applications['top_nav_bar'].lib.
return; endspin('load');
if (!rev) {
OfficeJS.tmp[docid + ' knownrevision'] =
(err||val||{_rev:undefined})._rev;
if ((err||val)._conflicts &&
(err||val)._conflicts.total_rows > 0) {
OfficeJS.lib.openApplication(
OfficeJS.lib.getAppFromPref(
'conflictsolver'),
{_id:docid,row:(err||val)._conflicts.rows[0]}
);
} }
priv.loading_object.load();
priv.jio.loadDocument(
basename+'.'+current_editor.ext,{
max_retry:3,
success: function (result) {
if (result && result.revision) {
priv.data_object.currentRevision = result.revision;
if (result.conflict_object) {
priv.onConflict(result.conflict_object);
} }
if (err) {
OfficeJS.tmp.lastfailure =
OfficeJS.lib.cloneObjectRoot(err);
OfficeJS.tmp.lastfailure.label = 'get';
OfficeJS.tmp.lastfailure.docid = docid;
} }
current_editor.setContent(result.content); callback?callback(err,val):true;
priv.loading_object.end_load();
},
error: function (error) {
priv.lastfailure.path = basename;
priv.lastfailure.method = 'loadDocument';
console.error (error.message);
priv.loading_object.end_load();
} }
}); );
};
/**
* Removes a document.
* @method remove
* @param {string} name The document name.
* @param {string} revision The document name.
*/
that.remove = function (name,revision) {
console.log (arguments);
if (!priv.isJioSet()) {
console.error ('No Jio set yet.');
return;
} }
priv.loading_object.remove(); });
priv.jio.removeDocument( odf(OfficeJS.lib,'allDocs',function (callback) {
name,{ if (OfficeJS.run.jio) {
revision: revision || 'last', OfficeJS.system.applications['top_nav_bar'].lib.spin('getlist');
success: function (result) { OfficeJS.run.jio.allDocs(
priv.loading_object.end_remove(); {conflicts:true,revs:true,revs_info:true,max_retry:3},
that.getList(); function (err,val) {
}, OfficeJS.system.applications['top_nav_bar'].lib.
error: function (error) { endspin('getlist');
priv.lastfailure.path = name; if (val) {
priv.lastfailure.method = 'removeDocument'; OfficeJS.tmp.documentlist = val;
console.error (error.message); } else if (err) {
priv.loading_object.end_remove(); OfficeJS.tmp.lastfailure =
that.getList(); OfficeJS.lib.cloneObjectRoot(err);
if (error.conflict_object) { OfficeJS.tmp.lastfailure.label = 'allDocs';
priv.onConflict (error.conflict_object); }
callback?callback(err,val):true;
} }
);
} }
}); });
}; odf(OfficeJS.lib,'remove',function (doc,rev,callback) {
if (OfficeJS.run.jio) {
/** var opts = {conflicts:true,revs:true,revs_info:true};
* Removes several files. if (rev) {
* @method removeSeveralFromArray opts.rev = rev;
* @param {array} documentarray Contains all file names ({string}). } else if (OfficeJS.tmp[doc._id + ' knownrevision']) {
*/ opts.rev = OfficeJS.tmp[doc._id + ' knownrevision'];
that.removeSeveralFromArray = function (documentarray) { }
var i, l, cpt = 0, current_editor = priv.data_object.currentEditor; OfficeJS.system.applications['top_nav_bar'].lib.spin('remove');
if (!priv.isJioSet()) { OfficeJS.run.jio.remove(
console.error ('No Jio set yet.'); doc,opts,
return; function (err,val) {
OfficeJS.system.applications['top_nav_bar'].lib.
endspin('remove');
if (err) {
OfficeJS.tmp.lastfailure =
OfficeJS.lib.cloneObjectRoot(err);
OfficeJS.tmp.lastfailure.label = 'remove';
OfficeJS.tmp.lastfailure.docid = doc._id;
}
callback?callback(err,val):true;
} }
var onResponse = function (result) { );
cpt += 1;
if (cpt === l) {
if (typeof current_editor.update !== 'undefined') {
if (priv.data_object.currentEditor !== null &&
current_editor.path ===
priv.data_object.currentEditor.path) {
that.getList(current_editor.update);
} else {
that.getList();
} }
});
odf(OfficeJS.lib,'getAppFromPref',function (spec) {
return OfficeJS.system.preferences[spec];
});
odf(OfficeJS.lib,'getAppFromMime',function (ext) {
return OfficeJS.lib.getAppFromPref(OfficeJS.system.mime[ext]);
});
odf(OfficeJS.lib,'cloneObjectRoot',function (obj) {
var cloned_obj = {}, key;
for (key in obj) {
cloned_obj[key] = obj[key];
} }
return cloned_obj;
});
odf(OfficeJS.lib,'cloneAndProtectObjectRoot',function (obj) {
var cloned_obj = {}, key;
for (key in obj) {
odf(cloned_obj,key,obj[key]);
} }
priv.loading_object.end_remove(); return cloned_obj;
};
for (i = 0, l = documentarray.length; i < l; i+= 1) {
priv.loading_object.remove();
priv.jio.removeDocument(
documentarray[i],{
revision: 'last',
success: onResponse,
error: onResponse
}); });
odf(OfficeJS.lib,'openApplication',function (app,obj) {
// unload
if (app.gadgetid && OfficeJS.tmp[app.gadgetid] &&
OfficeJS.tmp[app.gadgetid].onunload) {
if (!OfficeJS.tmp[app.gadgetid].onunload()) {
return false;
} }
};
/**
* Called when there is conflict
* @method onConflict
* @param {object} doc The document object
* @param {object} conflict_object The conflict object
*/
priv.onConflict = function (conflict_object) {
// get the good conflict solver and load it
// if (ext && priv.conflict_solver_object[ext]) {
// that.open({app:priv.conflict_solver_object[ext],
// // local_content:document.content,
// conflict_object:conflict_object});
// } else {
that.open({app:'basic_conflict_solver',
// local_content:document.content,
conflict_object:conflict_object});
// }
};
/**
* Solve the conflict
* @method solveConflict
* @param {object} conflict_data The conflict object
* @param {string} data The new content of the new revision
*/
that.solveConflict = function (conflict_object, data) {
that.closeGadgetId (priv.data_object.currentSolver.gadget_id);
priv.data_object.currentSolver = null;
priv.data_object.currentEditor.setContent(data);
priv.loading_object.save();
conflict_object.solveConflict(
data,{
success: function (result) {
if (result && result.revision) {
priv.data_object.currentRevision = result.revision;
}
priv.loading_object.end_save();
that.getList();
},
error: function (error) {
priv.lastfailure.path = basename;
priv.lastfailure.method = 'saveDocument';
console.error (error.message);
priv.loading_object.end_save();
that.getList();
if (error.conflict_object) {
priv.onConflict (error.conflict_object);
} }
// set api
if (app.varname) {
scope[app.varname]=OfficeJS.lib.cloneAndProtectObjectRoot(app.api);
}
// open
TabbularGadget.addNewTabGadget(app.componentpath,app.gadgetid);
OfficeJS.tmp[app.gadgetid] = app;
// load
if (app.onload) {
app.onload(obj);
} }
return true;
});
odf(OfficeJS.lib,'hideApplication',function (app) {
// TODO :
}); });
};
that.abortSolveConflict = function () { //////////////////////////////////////////////////////////////////////
that.closeGadgetId (priv.data_object.currentSolver.gadget_id);
priv.data_object.currentSolver = null;
};
/** odf(OfficeJS.command,'getEnv',function (env) {
* Get current activity. return OfficeJS.env[env];
* @method getActivity });
* @return {array} A list of current states for each current activities. odf(OfficeJS.command,'setEnv',function (env,value) {
*/ OfficeJS.env[env] = value;
that.getActivity = function () { });
var activity = priv.jio.getJobArray (); odf(OfficeJS.command,'setPreference',function (id,value) {
var lastfailure = that.getLastFailure(); // TODO :
var res = [], i; });
for (i = 0; i < activity.length; i+= 1) {
switch (activity[i].command.label) {
case 'saveDocument':
res.push(activity[i].storage.type+
': Saving "' + activity[i].command.path + '".');
break;
case 'loadDocument':
res.push(activity[i].storage.type+
': Loading "' + activity[i].command.path + '".');
break;
case 'removeDocument':
res.push(activity[i].storage.type+
': Removing "' + activity[i].command.path + '".');
break;
case 'getDocumentList':
res.push(activity[i].storage.type+
': Get document list' +
' at "' + activity[i].command.path + '".');
break;
default:
res.push('Unknown action.');
break;
}
}
if (lastfailure.method) {
switch (lastfailure.method) {
case 'saveDocument':
res.push('<span style="color:red;">LastFailure: '+
'Fail to save "'+ lastfailure.path + '"</span>');
break;
case 'loadDocument':
res.push('<span style="color:red;">LastFailure: '+
'Fail to load "'+ lastfailure.path + '"</span>');
break;
case 'removeDocument':
res.push('<span style="color:red;">LastFailure: '+
'Fail to remove "'+ lastfailure.path + '"</span>');
break;
case 'getDocumentList':
res.push('<span style="color:red;">LastFailure: '+
'Fail to retreive list ' +
' at "' + lastfailure.path + '"</span>');
break;
default:
break;
}
}
return res;
};
/** //////////////////////////////////////////////////////////////////////
* Returns the last job failure.
* @method getLastFailure
* @return {object} The last failure.
*/
that.getLastFailure = function () {
return priv.lastfailure;
};
// End of class // odf(scope,'OfficeJS',OfficeJS.command);
priv.init();
return that;
}()); // end OfficeJS
// show gadgets OfficeJS.lib.openApplication(OfficeJS.system.applications['top_nav_bar']);
OfficeJS.open({app:'topnavbar'}); OfficeJS.lib.openApplication(OfficeJS.system.applications['left_nav_bar']);
OfficeJS.open({app:'leftnavbar'}); OfficeJS.lib.openApplication(OfficeJS.system.applications['login']);
OfficeJS.open({app:'login'}); }(window));
}());
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment