├── .gitignore ├── .npmignore ├── .travis.yml ├── SpecRunner.html ├── css ├── bootstrap-responsive.min.css ├── bootstrap.min.css ├── custom.css └── webodf.css ├── dialog.html ├── documents.html ├── goToStep.html ├── images ├── back.svg ├── browserid.png ├── down_arrow.png ├── glyphicons-halflings-white.png ├── glyphicons-halflings.png ├── libredocs.png ├── libredocs.svg ├── loading.gif ├── plus.png ├── remoteStorage-icon.png ├── remoteStorage.png └── trash.png ├── index.html ├── js ├── ConnectPad.js ├── account.js ├── async.js ├── base64.js ├── bootstrap-modal.js ├── bootstrap.min.js ├── documents.js ├── etherpad.js ├── features.js ├── helpers.js ├── ieblock.js ├── index.js ├── init.js ├── jquery.min.js ├── load.js ├── models │ └── document.js ├── require.js ├── src │ ├── lib │ │ ├── couch.js │ │ ├── dav.js │ │ ├── hardcoded.js │ │ ├── platform.js │ │ └── webfinger.js │ ├── remoteStorage.js │ └── require.js ├── sync.js └── welcome.js ├── lib ├── core │ ├── Async.js │ ├── Base64.js │ ├── ByteArray.js │ ├── ByteArrayWriter.js │ ├── Cursor.js │ ├── JSLint.js │ ├── PointWalker.js │ ├── RawDeflate.js │ ├── RawInflate.js │ ├── UnitTester.js │ ├── Zip.js │ └── dummyxmlmodel.js_ ├── export.js ├── gui │ ├── Caret.js │ ├── PresenterUI.js │ ├── SelectionMover.js │ └── XMLEdit.js ├── jasmine-sinon.js ├── jasmine │ ├── jasmine-html.js │ ├── jasmine.css │ ├── jasmine.js │ ├── json2.js │ └── version.rb ├── manifest.js ├── odf │ ├── FontLoader.js │ ├── Formatting.js │ ├── OdfCanvas.js │ ├── OdfContainer.js │ ├── Style2CSS.js │ └── StyleInfo.js ├── packages.js ├── runtime.js ├── sinon │ └── sinon.js └── xmldom │ ├── LSSerializer.js │ ├── LSSerializerFilter.js │ ├── OperationalTransformDOM.js │ ├── OperationalTransformInterface.js │ ├── RelaxNG.js │ ├── RelaxNG2.js │ ├── RelaxNGParser.js │ └── XPath.js ├── old ├── README ├── config.js ├── config.sample.js ├── featureFreezeBugs.txt ├── handler.js ├── package.json └── server.js ├── reset.html ├── spec └── ConnectPadSpec.js ├── webodf.html └── welcome.html /.gitignore: -------------------------------------------------------------------------------- 1 | # just sane ignores 2 | .*.sw[po] 3 | *.bak 4 | *.BAK 5 | *~ 6 | *.orig 7 | *.class 8 | .cvsignore 9 | Thumbs.db 10 | .DS_Store 11 | *.py[co] 12 | _darcs/* 13 | CVS/* 14 | .svn/* 15 | RCS/* 16 | 17 | # config files 18 | irisCouchCredentials.js 19 | userDbCredentials.js 20 | createDb/config.js 21 | provision/config.js 22 | squat/config.js 23 | users/config.js 24 | userExists/config.js 25 | useraddress/config.js 26 | setConfig/config.js 27 | 28 | # node modules 29 | node_modules 30 | 31 | # Cloud9IDE 32 | .settings.xml 33 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 0.4 4 | - 0.6 5 | - 0.7 # development version of 0.8, may be unstable 6 | -------------------------------------------------------------------------------- /SpecRunner.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | Jasmine Spec Runner 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /css/bootstrap-responsive.min.css: -------------------------------------------------------------------------------- 1 | .hidden{display:none;visibility:hidden;} 2 | @media (max-width:480px){.nav-collapse{-webkit-transform:translate3d(0, 0, 0);} .page-header h1 small{display:block;line-height:18px;} input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;} .input-prepend input[class*="span"],.input-append input[class*="span"]{width:auto;} input[type="checkbox"],input[type="radio"]{border:1px solid #ccc;} .form-horizontal .control-group>label{float:none;width:auto;padding-top:0;text-align:left;} .form-horizontal .controls{margin-left:0;} .form-horizontal .control-list{padding-top:0;} .form-horizontal .form-actions{padding-left:10px;padding-right:10px;} .modal{position:absolute;top:10px;left:10px;right:10px;width:auto;margin:0;}.modal.fade.in{top:auto;} .modal-header .close{padding:10px;margin:-10px;} .carousel-caption{position:static;}}@media (max-width:768px){.container{width:auto;padding:0 20px;} .row-fluid{width:100%;} .row{margin-left:0;} .row>[class*="span"],.row-fluid>[class*="span"]{float:none;display:block;width:auto;margin:0;}}@media (min-width:768px) and (max-width:980px){.row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:"";} .row:after{clear:both;} [class*="span"]{float:left;margin-left:20px;} .span1{width:42px;} .span2{width:104px;} .span3{width:166px;} .span4{width:228px;} .span5{width:290px;} .span6{width:352px;} .span7{width:414px;} .span8{width:476px;} .span9{width:538px;} .span10{width:600px;} .span11{width:662px;} .span12,.container{width:724px;} .offset1{margin-left:82px;} .offset2{margin-left:144px;} .offset3{margin-left:206px;} .offset4{margin-left:268px;} .offset5{margin-left:330px;} .offset6{margin-left:392px;} .offset7{margin-left:454px;} .offset8{margin-left:516px;} .offset9{margin-left:578px;} .offset10{margin-left:640px;} .offset11{margin-left:702px;} .row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";} .row-fluid:after{clear:both;} .row-fluid>[class*="span"]{float:left;margin-left:2.762430939%;} .row-fluid>[class*="span"]:first-child{margin-left:0;} .row-fluid .span1{width:5.801104972%;} .row-fluid .span2{width:14.364640883%;} .row-fluid .span3{width:22.928176794%;} .row-fluid .span4{width:31.491712705%;} .row-fluid .span5{width:40.055248616%;} .row-fluid .span6{width:48.618784527%;} .row-fluid .span7{width:57.182320438000005%;} .row-fluid .span8{width:65.74585634900001%;} .row-fluid .span9{width:74.30939226%;} .row-fluid .span10{width:82.87292817100001%;} .row-fluid .span11{width:91.436464082%;} .row-fluid .span12{width:99.999999993%;} input.span1,textarea.span1,.uneditable-input.span1{width:32px;} input.span2,textarea.span2,.uneditable-input.span2{width:94px;} input.span3,textarea.span3,.uneditable-input.span3{width:156px;} input.span4,textarea.span4,.uneditable-input.span4{width:218px;} input.span5,textarea.span5,.uneditable-input.span5{width:280px;} input.span6,textarea.span6,.uneditable-input.span6{width:342px;} input.span7,textarea.span7,.uneditable-input.span7{width:404px;} input.span8,textarea.span8,.uneditable-input.span8{width:466px;} input.span9,textarea.span9,.uneditable-input.span9{width:528px;} input.span10,textarea.span10,.uneditable-input.span10{width:590px;} input.span11,textarea.span11,.uneditable-input.span11{width:652px;} input.span12,textarea.span12,.uneditable-input.span12{width:714px;}}@media (max-width:980px){body{padding-top:0;} .navbar-fixed-top{position:static;margin-bottom:18px;} .navbar-fixed-top .navbar-inner{padding:5px;} .navbar .container{width:auto;padding:0;} .navbar .brand{padding-left:10px;padding-right:10px;margin:0 0 0 -5px;} .navbar .nav-collapse{clear:left;} .navbar .nav{float:none;margin:0 0 9px;} .navbar .nav>li{float:none;} .navbar .nav>li>a{margin-bottom:2px;} .navbar .nav>.divider-vertical{display:none;} .navbar .nav>li>a,.navbar .dropdown-menu a{padding:6px 15px;font-weight:bold;color:#999999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} .navbar .dropdown-menu li+li a{margin-bottom:2px;} .navbar .nav>li>a:hover,.navbar .dropdown-menu a:hover{background-color:#222222;} .navbar .dropdown-menu{position:static;top:auto;left:auto;float:none;display:block;max-width:none;margin:0 15px;padding:0;background-color:transparent;border:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} .navbar .dropdown-menu:before,.navbar .dropdown-menu:after{display:none;} .navbar .dropdown-menu .divider{display:none;} .navbar-form,.navbar-search{float:none;padding:9px 15px;margin:9px 0;border-top:1px solid #222222;border-bottom:1px solid #222222;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.1);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.1);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.1);} .navbar .nav.pull-right{float:none;margin-left:0;} .navbar-static .navbar-inner{padding-left:10px;padding-right:10px;} .btn-navbar{display:block;} .nav-collapse{overflow:hidden;height:0;}}@media (min-width:980px){.nav-collapse.collapse{height:auto !important;}}@media (min-width:1200px){.row{margin-left:-30px;*zoom:1;}.row:before,.row:after{display:table;content:"";} .row:after{clear:both;} [class*="span"]{float:left;margin-left:30px;} .span1{width:70px;} .span2{width:170px;} .span3{width:270px;} .span4{width:370px;} .span5{width:470px;} .span6{width:570px;} .span7{width:670px;} .span8{width:770px;} .span9{width:870px;} .span10{width:970px;} .span11{width:1070px;} .span12,.container{width:1170px;} .offset1{margin-left:130px;} .offset2{margin-left:230px;} .offset3{margin-left:330px;} .offset4{margin-left:430px;} .offset5{margin-left:530px;} .offset6{margin-left:630px;} .offset7{margin-left:730px;} .offset8{margin-left:830px;} .offset9{margin-left:930px;} .offset10{margin-left:1030px;} .offset11{margin-left:1130px;} .row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";} .row-fluid:after{clear:both;} .row-fluid>[class*="span"]{float:left;margin-left:2.564102564%;} .row-fluid>[class*="span"]:first-child{margin-left:0;} .row-fluid .span1{width:5.982905983%;} .row-fluid .span2{width:14.529914530000001%;} .row-fluid .span3{width:23.076923077%;} .row-fluid .span4{width:31.623931624%;} .row-fluid .span5{width:40.170940171000005%;} .row-fluid .span6{width:48.717948718%;} .row-fluid .span7{width:57.264957265%;} .row-fluid .span8{width:65.81196581200001%;} .row-fluid .span9{width:74.358974359%;} .row-fluid .span10{width:82.905982906%;} .row-fluid .span11{width:91.45299145300001%;} .row-fluid .span12{width:100%;} input.span1,textarea.span1,.uneditable-input.span1{width:60px;} input.span2,textarea.span2,.uneditable-input.span2{width:160px;} input.span3,textarea.span3,.uneditable-input.span3{width:260px;} input.span4,textarea.span4,.uneditable-input.span4{width:360px;} input.span5,textarea.span5,.uneditable-input.span5{width:460px;} input.span6,textarea.span6,.uneditable-input.span6{width:560px;} input.span7,textarea.span7,.uneditable-input.span7{width:660px;} input.span8,textarea.span8,.uneditable-input.span8{width:760px;} input.span9,textarea.span9,.uneditable-input.span9{width:860px;} input.span10,textarea.span10,.uneditable-input.span10{width:960px;} input.span11,textarea.span11,.uneditable-input.span11{width:1060px;} input.span12,textarea.span12,.uneditable-input.span12{width:1160px;} .thumbnails{margin-left:-30px;} .thumbnails>li{margin-left:30px;}} 3 | -------------------------------------------------------------------------------- /css/custom.css: -------------------------------------------------------------------------------- 1 | html, body { background-color:#eee; } 2 | .container > footer p { text-align:center; } 3 | .container { width:60em; } 4 | footer { border:none; margin:1em; } 5 | #write footer { margin:3em; } 6 | 7 | .page-header { background-color:#f5f5f5; padding:5em 1.5em 1em; margin:-20px -20px 0; } 8 | .page-header img { height:5em; margin:-3em -1em 1.5em -1em; } 9 | body#write .page-header img { height:3em; margin:-4em 0em 1em 0em } 10 | h1 { position:relative; font-size:4em; display:inline; color:#000; } 11 | h1 a { color:#000; } 12 | h1 a:hover, h1 a:focus { color:#333; text-decoration:none; } 13 | h1 span#docTitle { position:absolute; left:.08em; width:11em; white-space:nowrap; text-overflow:ellipsis; overflow:hidden; } 14 | h1+small { float:right; position:relative; top:-2em; right:0em; } 15 | h1>small { font-size:12px; position:absolute; left:16.8em; top:.5em; white-space:nowrap; } 16 | 17 | #signin { margin-top:5.5em; padding:0 8em 1em 7em; white-space:nowrap; height:2.6em; } 18 | #write #signin { position:relative; float:right; top:1em; margin:0; } 19 | .content #welcome { height:29em; } 20 | #steps { position:absolute; top:22em; } 21 | .step, .step.done, .step.done:hover { opacity:.5; position:relative; } 22 | .step.active, .step:hover { opacity:1; } 23 | .step.remotestorage { position:absolute; width:20em; left:0; } 24 | .step.remotestorage img, .step.write img { position:relative; left:20%; } 25 | .step.remotestorage img { margin:2em 0; width:12em; } 26 | .step.connect { position:absolute; width:18em; left:21em; } 27 | .step.connect #connect { position:absolute; width:15em; } 28 | .step.connect #connect-address { position:absolute; margin:4em 0 .5em; width:9.35em; padding-right:6em; height:2.5em; padding-left:3em; background:url('../images/remoteStorage-icon.png') no-repeat .3em center; } 29 | .step.connect #connect-button { position:absolute; margin:4.6em -3em 0 0; right:0; } 30 | .step.write { position:absolute; width:20em; left:41em; } 31 | .step.write img { margin-top:-1em; } 32 | .step>h3 { position:absolute; top:7.3em; white-space:nowrap; } 33 | .step>p { position:absolute; top:12.5em; } 34 | 35 | .checkmark { position:absolute; font-size:15em; left:.15em; top:.6em; color:#005580; opacity: 0.5 } 36 | 37 | .progress { display:block; height:3em; margin:0 0 1.5em 0; } 38 | .progress .bar { height:3.5em; } 39 | .progress .bar p { padding:.7em; display:inline; position:absolute; } 40 | 41 | #new-document { position:absolute; float:right; margin:-3.5em 0 0 33em; } 42 | #upload-document { position:relative; float:right; margin:-3.5em 0 0 0; } 43 | ul#doclist { margin:-20px; font-size:1.3em; list-style:none; clear:both; } 44 | ul#doclist { margin-left:-20px; font-size:1.3em; cursor:pointer; list-style:none; } 45 | ul#doclist #loadingdocs { background:url('../images/loading.gif') no-repeat left; margin-left:.7em; padding-left:1.2em; } 46 | ul#doclist li { width:100%; padding:.7em 0; border:none; white-space:nowrap; position:relative; } 47 | ul#doclist li:hover { background:#f8f8f8; } 48 | ul#doclist li:last-child { height:1.5em; } 49 | ul#doclist li .doclink { cursor:pointer; text-decoration:none; } 50 | ul#doclist strong { color:#000; padding:.7em; } 51 | ul#doclist span { font-size:.75em; } 52 | ul#doclist span.preview { position:absolute; top:0; padding:1em 2em 1em .5em; overflow:hidden; white-space:nowrap; color:#555; } 53 | ul#doclist time { position:absolute; right:1.2em; font-size:.75em; } 54 | /* 55 | ul#doclist li a.btn { display:none; } 56 | ul#doclist li:hover a.btn { position:absolute; display:inline; right:1em; top:.5em; } 57 | */ 58 | ul#doclist li:hover .preview { color:#000; } 59 | ul#doclist li:hover .date { display:none; } 60 | ul#doclist li .buttons { display:none; } 61 | ul#doclist li.active .buttons { display:inline; float:right; margin:-1em 6em 0 0; } 62 | ul#doclist li a.btn { margin:1em .2em; } 63 | 64 | #docTitleInput { height:1.2em; width:6em; font-size:1em; margin:-.7em -.05em -.5em; padding:0; color:#000; font-weight:bold; } 65 | .editTitle { margin:0; } 66 | 67 | #previewPad { position:absolute; margin-top:43px; margin-left:-11px; width:73em; height:32em; background:none; border:none; } 68 | li .editor { display:none; } 69 | li.pad.active .editor { min-height:30em; height:30em; margin-top:1em; display:block; } 70 | li.odf.active .editor { display:none; } 71 | .editor iframe { width:100%; min-height:100%; border:1px solid #bbb; } 72 | #editorcontainer { margin:1em 0; } 73 | .more { margin-top: 2em; cursor: pointer; display: block;} 74 | 75 | #error { z-index:1; position:absolute; width:63em; } 76 | 77 | /* The white background content wrapper */ 78 | .container > .content { 79 | background-color:#fff; 80 | padding:20px; 81 | margin:0 -20px; /* negative indent the amount of the padding to maintain the grid system */ 82 | -webkit-border-radius:0 0 6px 6px; 83 | -moz-border-radius:0 0 6px 6px; 84 | border-radius:0 0 6px 6px; 85 | -webkit-box-shadow:0 1px 2px rgba(0,0,0,.15); 86 | -moz-box-shadow:0 1px 2px rgba(0,0,0,.15); 87 | box-shadow:0 1px 2px rgba(0,0,0,.15); 88 | } 89 | 90 | .container.modal { width:84em; margin-left: -42em; } 91 | -------------------------------------------------------------------------------- /css/webodf.css: -------------------------------------------------------------------------------- 1 | @namespace draw url(urn:oasis:names:tc:opendocument:xmlns:drawing:1.0); 2 | @namespace fo url(urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0); 3 | @namespace office url(urn:oasis:names:tc:opendocument:xmlns:office:1.0); 4 | @namespace presentation url(urn:oasis:names:tc:opendocument:xmlns:presentation:1.0); 5 | @namespace style url(urn:oasis:names:tc:opendocument:xmlns:style:1.0); 6 | @namespace svg url(urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0); 7 | @namespace table url(urn:oasis:names:tc:opendocument:xmlns:table:1.0); 8 | @namespace text url(urn:oasis:names:tc:opendocument:xmlns:text:1.0); 9 | @namespace runtimens url(urn:webodf); /* namespace for runtime only */ 10 | 11 | office|document > *, office|document-content > * { 12 | display: none; 13 | } 14 | office|body, office|document { 15 | display: inline-block; 16 | position: relative; 17 | } 18 | 19 | text|p, text|h { 20 | display: block; 21 | padding: 3px 3px 3px 3px; 22 | margin: 5px 5px 5px 5px; 23 | } 24 | text|h { 25 | font-weight: bold; 26 | } 27 | *[runtimens|containsparagraphanchor] { 28 | position: relative; 29 | } 30 | text|s:before { /* this needs to be the number of spaces given by text:c */ 31 | content: ' '; 32 | } 33 | text|tab:before { 34 | display: inline; 35 | content: ' '; 36 | } 37 | text|line-break { 38 | content: " "; 39 | display: block; 40 | } 41 | text|tracked-changes { 42 | /*Consumers that do not support change tracking, should ignore changes.*/ 43 | display: none; 44 | } 45 | office|binary-data { 46 | display: none; 47 | } 48 | office|text { 49 | display: block; 50 | width: 216mm; /* default to A4 width */ 51 | min-height: 279mm; 52 | padding-left: 32mm; 53 | padding-right: 32mm; 54 | padding-top: 25mm; 55 | padding-bottom: 13mm; 56 | margin: 2px; 57 | text-align: left; 58 | overflow: hidden; 59 | } 60 | office|spreadsheet { 61 | display: block; 62 | border-collapse: collapse; 63 | empty-cells: show; 64 | font-family: sans-serif; 65 | font-size: 10pt; 66 | text-align: left; 67 | page-break-inside: avoid; 68 | overflow: hidden; 69 | } 70 | office|presentation { 71 | display: inline-block; 72 | text-align: left; 73 | } 74 | draw|page { 75 | display: block; 76 | height: 21cm; 77 | width: 28cm; 78 | margin: 3px; 79 | position: relative; 80 | overflow: hidden; 81 | } 82 | presentation|notes { 83 | display: none; 84 | } 85 | @media print { 86 | draw|page { 87 | border: 1pt solid black; 88 | page-break-inside: avoid; 89 | } 90 | presentation|notes { 91 | /*TODO*/ 92 | } 93 | } 94 | office|spreadsheet text|p { 95 | border: 0px; 96 | padding: 1px; 97 | margin: 0px; 98 | } 99 | office|spreadsheet table|table { 100 | margin: 3px; 101 | } 102 | office|spreadsheet table|table:after { 103 | /* show sheet name the end of the sheet */ 104 | /*content: attr(table|name);*/ /* gives parsing error in opera */ 105 | } 106 | office|spreadsheet table|table-row { 107 | counter-increment: row; 108 | } 109 | office|spreadsheet table|table-row:before { 110 | width: 3em; 111 | background: #cccccc; 112 | border: 1px solid black; 113 | text-align: center; 114 | content: counter(row); 115 | } 116 | office|spreadsheet table|table-cell { 117 | border: 1px solid #cccccc; 118 | } 119 | table|table { 120 | display: table; 121 | } 122 | draw|frame table|table { 123 | width: 100%; 124 | height: 100%; 125 | background: white; 126 | } 127 | table|table-row { 128 | display: table-row; 129 | } 130 | table|table-column { 131 | display: table-column; 132 | } 133 | table|table-cell { 134 | display: table-cell; 135 | } 136 | draw|frame { 137 | display: block; 138 | } 139 | draw|image { 140 | display: block; 141 | width: 100%; 142 | height: 100%; 143 | top: 0px; 144 | left: 0px; 145 | background-repeat: no-repeat; 146 | background-size: 100% 100%; 147 | -moz-background-size: 100% 100%; 148 | } 149 | text|list { 150 | display: block; 151 | padding-left: 1.5em; 152 | counter-reset: list; 153 | } 154 | text|list-item { 155 | display: block; 156 | } 157 | text|list-item:before { 158 | display: inline-block; 159 | content: '•'; 160 | counter-increment: list; 161 | width: 0.5em; 162 | margin-left: -0.5em; 163 | padding: 0px; 164 | border: 0px; 165 | } 166 | text|list-item > *:first-child { 167 | display: inline-block; 168 | } 169 | text|a { 170 | color: blue; 171 | text-decoration: underline; 172 | } 173 | text|note-citation { 174 | vertical-align: super; 175 | font-size: smaller; 176 | } 177 | text|note-body { 178 | display: none; 179 | } 180 | text|note:hover text|note-citation { 181 | background: #dddddd; 182 | } 183 | text|note:hover text|note-body { 184 | display: block; 185 | left:1em; 186 | max-width: 80%; 187 | position: absolute; 188 | background: #ffffaa; 189 | } 190 | svg|title, svg|desc { 191 | display: none; 192 | } 193 | -------------------------------------------------------------------------------- /dialog.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Connecting your remote storage 4 | 5 | 6 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /documents.html: -------------------------------------------------------------------------------- 1 |
2 |
+ New document
3 | 4 | 5 | 7 | more … 8 |
Syncing documents …
9 |
10 | -------------------------------------------------------------------------------- /goToStep.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Setting your enroll step in localStorage 6 | 11 | 12 | 13 |

Done. Go back to the main page.

14 | 15 | 16 | -------------------------------------------------------------------------------- /images/back.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /images/browserid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unhosted/libredocs/9b73259ae8f0f579c3939ef609f1e73e4fb6193d/images/browserid.png -------------------------------------------------------------------------------- /images/down_arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unhosted/libredocs/9b73259ae8f0f579c3939ef609f1e73e4fb6193d/images/down_arrow.png -------------------------------------------------------------------------------- /images/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unhosted/libredocs/9b73259ae8f0f579c3939ef609f1e73e4fb6193d/images/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /images/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unhosted/libredocs/9b73259ae8f0f579c3939ef609f1e73e4fb6193d/images/glyphicons-halflings.png -------------------------------------------------------------------------------- /images/libredocs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unhosted/libredocs/9b73259ae8f0f579c3939ef609f1e73e4fb6193d/images/libredocs.png -------------------------------------------------------------------------------- /images/libredocs.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | image/svg+xml 81 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /images/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unhosted/libredocs/9b73259ae8f0f579c3939ef609f1e73e4fb6193d/images/loading.gif -------------------------------------------------------------------------------- /images/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unhosted/libredocs/9b73259ae8f0f579c3939ef609f1e73e4fb6193d/images/plus.png -------------------------------------------------------------------------------- /images/remoteStorage-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unhosted/libredocs/9b73259ae8f0f579c3939ef609f1e73e4fb6193d/images/remoteStorage-icon.png -------------------------------------------------------------------------------- /images/remoteStorage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unhosted/libredocs/9b73259ae8f0f579c3939ef609f1e73e4fb6193d/images/remoteStorage.png -------------------------------------------------------------------------------- /images/trash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unhosted/libredocs/9b73259ae8f0f579c3939ef609f1e73e4fb6193d/images/trash.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Write with Libre Docs – liberate your ideas 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 28 | 35 |
36 | 37 |
38 | 41 |
42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /js/ConnectPad.js: -------------------------------------------------------------------------------- 1 | connectPad = (function() { 2 | var host = "http://ownpad.unhosted.org:82"; 3 | var api = "/ownapi/1/"; 4 | 5 | function urlFor(functionName, params){ 6 | var query = []; 7 | for (var p in params) { 8 | query.push(encodeURIComponent(p) + "=" + encodeURIComponent(params[p])); 9 | } 10 | return host+api+functionName+"?"+query.join("&"); 11 | } 12 | 13 | function paramsFor(sessionObj){ 14 | return { 15 | userAddress: sessionObj.userAddress, 16 | storageInfo: JSON.stringify(sessionObj.storageInfo), 17 | bearerToken: sessionObj.bearerToken 18 | } 19 | } 20 | 21 | function connect(sessionObj, callback){ 22 | var xhr = new XMLHttpRequest(); 23 | xhr.open('GET', urlFor("connect", paramsFor(sessionObj))); 24 | xhr.onreadystatechange = function() { 25 | if(xhr.readyState==4) { 26 | if(xhr.status==201 || xhr.status==200) { 27 | callback(true); 28 | } else { 29 | callback(false); 30 | } 31 | } 32 | }; 33 | xhr.send(); 34 | } 35 | 36 | return { 37 | urlFor: urlFor, 38 | paramsFor: paramsFor, 39 | connect: connect 40 | }; 41 | })(); 42 | -------------------------------------------------------------------------------- /js/account.js: -------------------------------------------------------------------------------- 1 | //deal with legacy accounts and anonymous users: 2 | (function() { 3 | // make sure we throw no errors in old browsers 4 | if(!window.localStorage) return; 5 | 6 | localStorage.documents = localStorage.documents || '{}'; 7 | localStorage.index = localStorage.index || '{}'; 8 | if(!currentUser()) return; 9 | var sessionObj = JSON.parse(localStorage.getItem('sessionObj')); 10 | var changed = false; 11 | //unless the sessionObj specifies that it wants to stay on the clientSide, do these data format upgrades: 12 | if(!sessionObj.clientSide && (!sessionObj.storageInfo || !sessionObj.ownPadBackDoor || !sessionObj.couchHost)) { 13 | sessionObj.storageInfo = { 14 | api: 'CouchDB', 15 | template: 'http://'+sessionObj.proxy+sessionObj.subdomain+'.iriscouch.com/{category}/', 16 | auth: 'http://'+sessionObj.subdomain+'.iriscouch.com/cors/auth/modal.html' 17 | }; 18 | sessionObj.couchHost = sessionObj.couchHost || sessionObj.subdomain+'.iriscouch.com'; 19 | sessionObj.ownPadBackDoor = 'https://'+sessionObj.couchHost+'/documents'; 20 | changed = true; 21 | } 22 | if(sessionObj.proxy && sessionObj.proxy.indexOf('yourremotestorage.net') != -1) 23 | { 24 | sessionObj.proxy = 'proxy.'+location.host+'/'; 25 | sessionObj.storageInfo.template = 26 | 'http://' + sessionObj.proxy + sessionObj.couchHost + '/{category}/'; 27 | changed = true; 28 | } 29 | if(changed) 30 | { 31 | sessionObj.state = 'storing' // write this to the db next time. 32 | localStorage.setItem('sessionObj', JSON.stringify(sessionObj)); 33 | } 34 | })(); 35 | 36 | function addSignout() { 37 | var sessionObj = localGet('sessionObj') || {}; 38 | var signout = document.getElementById('signout'); 39 | signout.innerHTML = ' '; 40 | $('#signout').on('click', 'a', signOut); 41 | $('#signout').show(); 42 | $('#signout a').tooltip({placement:'left'}); 43 | } 44 | 45 | function signOut() { 46 | // signing a user out means clearing all their personal data off the device: 47 | localStorage.clear(); 48 | window.location.href = ''; 49 | } 50 | 51 | function currentUser() { 52 | var sessionObj = JSON.parse(localStorage.getItem('sessionObj') || '{}'); 53 | return sessionObj.userAddress; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /js/base64.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Base64 encode / decode 4 | * http://www.webtoolkit.info/ 5 | * 6 | **/ 7 | 8 | var Base64 = { 9 | 10 | // private property 11 | _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", 12 | 13 | // public method for encoding 14 | encode : function (input) { 15 | var output = ""; 16 | var chr1, chr2, chr3, enc1, enc2, enc3, enc4; 17 | var i = 0; 18 | 19 | input = Base64._utf8_encode(input); 20 | 21 | while (i < input.length) { 22 | 23 | chr1 = input.charCodeAt(i++); 24 | chr2 = input.charCodeAt(i++); 25 | chr3 = input.charCodeAt(i++); 26 | 27 | enc1 = chr1 >> 2; 28 | enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); 29 | enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); 30 | enc4 = chr3 & 63; 31 | 32 | if (isNaN(chr2)) { 33 | enc3 = enc4 = 64; 34 | } else if (isNaN(chr3)) { 35 | enc4 = 64; 36 | } 37 | 38 | output = output + 39 | this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + 40 | this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4); 41 | 42 | } 43 | 44 | return output; 45 | }, 46 | 47 | // public method for decoding 48 | decode : function (input) { 49 | var output = ""; 50 | var chr1, chr2, chr3; 51 | var enc1, enc2, enc3, enc4; 52 | var i = 0; 53 | 54 | input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); 55 | 56 | while (i < input.length) { 57 | 58 | enc1 = this._keyStr.indexOf(input.charAt(i++)); 59 | enc2 = this._keyStr.indexOf(input.charAt(i++)); 60 | enc3 = this._keyStr.indexOf(input.charAt(i++)); 61 | enc4 = this._keyStr.indexOf(input.charAt(i++)); 62 | 63 | chr1 = (enc1 << 2) | (enc2 >> 4); 64 | chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); 65 | chr3 = ((enc3 & 3) << 6) | enc4; 66 | 67 | output = output + String.fromCharCode(chr1); 68 | 69 | if (enc3 != 64) { 70 | output = output + String.fromCharCode(chr2); 71 | } 72 | if (enc4 != 64) { 73 | output = output + String.fromCharCode(chr3); 74 | } 75 | 76 | } 77 | 78 | output = Base64._utf8_decode(output); 79 | 80 | return output; 81 | 82 | }, 83 | 84 | // private method for UTF-8 encoding 85 | _utf8_encode : function (string) { 86 | string = string.replace(/\r\n/g,"\n"); 87 | var utftext = ""; 88 | 89 | for (var n = 0; n < string.length; n++) { 90 | 91 | var c = string.charCodeAt(n); 92 | 93 | if (c < 128) { 94 | utftext += String.fromCharCode(c); 95 | } 96 | else if((c > 127) && (c < 2048)) { 97 | utftext += String.fromCharCode((c >> 6) | 192); 98 | utftext += String.fromCharCode((c & 63) | 128); 99 | } 100 | else { 101 | utftext += String.fromCharCode((c >> 12) | 224); 102 | utftext += String.fromCharCode(((c >> 6) & 63) | 128); 103 | utftext += String.fromCharCode((c & 63) | 128); 104 | } 105 | 106 | } 107 | 108 | return utftext; 109 | }, 110 | 111 | // private method for UTF-8 decoding 112 | _utf8_decode : function (utftext) { 113 | var string = ""; 114 | var i = 0; 115 | var c = c1 = c2 = 0; 116 | 117 | while ( i < utftext.length ) { 118 | 119 | c = utftext.charCodeAt(i); 120 | 121 | if (c < 128) { 122 | string += String.fromCharCode(c); 123 | i++; 124 | } 125 | else if((c > 191) && (c < 224)) { 126 | c2 = utftext.charCodeAt(i+1); 127 | string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); 128 | i += 2; 129 | } 130 | else { 131 | c2 = utftext.charCodeAt(i+1); 132 | c3 = utftext.charCodeAt(i+2); 133 | string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); 134 | i += 3; 135 | } 136 | 137 | } 138 | 139 | return string; 140 | } 141 | 142 | } 143 | -------------------------------------------------------------------------------- /js/bootstrap-modal.js: -------------------------------------------------------------------------------- 1 | /* ========================================================= 2 | * bootstrap-modal.js v2.0.2 3 | * http://twitter.github.com/bootstrap/javascript.html#modals 4 | * ========================================================= 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ========================================================= */ 19 | 20 | 21 | !function( $ ){ 22 | 23 | "use strict" 24 | 25 | /* MODAL CLASS DEFINITION 26 | * ====================== */ 27 | 28 | var Modal = function ( content, options ) { 29 | this.options = options 30 | this.$element = $(content) 31 | .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this)) 32 | } 33 | 34 | Modal.prototype = { 35 | 36 | constructor: Modal 37 | 38 | , toggle: function () { 39 | return this[!this.isShown ? 'show' : 'hide']() 40 | } 41 | 42 | , show: function () { 43 | var that = this 44 | 45 | if (this.isShown) return 46 | 47 | $('body').addClass('modal-open') 48 | 49 | this.isShown = true 50 | this.$element.trigger('show') 51 | 52 | escape.call(this) 53 | backdrop.call(this, function () { 54 | var transition = $.support.transition && that.$element.hasClass('fade') 55 | 56 | !that.$element.parent().length && that.$element.appendTo(document.body) //don't move modals dom position 57 | 58 | that.$element 59 | .show() 60 | 61 | if (transition) { 62 | that.$element[0].offsetWidth // force reflow 63 | } 64 | 65 | that.$element.addClass('in') 66 | 67 | transition ? 68 | that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) : 69 | that.$element.trigger('shown') 70 | 71 | }) 72 | } 73 | 74 | , hide: function ( e ) { 75 | e && e.preventDefault() 76 | 77 | if (!this.isShown) return 78 | 79 | var that = this 80 | this.isShown = false 81 | 82 | $('body').removeClass('modal-open') 83 | 84 | escape.call(this) 85 | 86 | this.$element 87 | .trigger('hide') 88 | .removeClass('in') 89 | 90 | $.support.transition && this.$element.hasClass('fade') ? 91 | hideWithTransition.call(this) : 92 | hideModal.call(this) 93 | } 94 | 95 | } 96 | 97 | 98 | /* MODAL PRIVATE METHODS 99 | * ===================== */ 100 | 101 | function hideWithTransition() { 102 | var that = this 103 | , timeout = setTimeout(function () { 104 | that.$element.off($.support.transition.end) 105 | hideModal.call(that) 106 | }, 500) 107 | 108 | this.$element.one($.support.transition.end, function () { 109 | clearTimeout(timeout) 110 | hideModal.call(that) 111 | }) 112 | } 113 | 114 | function hideModal( that ) { 115 | this.$element 116 | .hide() 117 | .trigger('hidden') 118 | 119 | backdrop.call(this) 120 | } 121 | 122 | function backdrop( callback ) { 123 | var that = this 124 | , animate = this.$element.hasClass('fade') ? 'fade' : '' 125 | 126 | if (this.isShown && this.options.backdrop) { 127 | var doAnimate = $.support.transition && animate 128 | 129 | this.$backdrop = $('