Commit 41a76efb authored by Cédric Le Ninivin's avatar Cédric Le Ninivin

Initial Version in FileSystem Mode

parent 34853bdc
* Use Indexeddb to save URL list in service worker
* Improve storage organisation (breaks compatibility)
* Provide Diff Tool for collaboration
nav.navbar-default {
background-color: none;
}
\ No newline at end of file
This diff is collapsed.
html body nav.navbar-default {
background-color: transparent;
}
html body .navbar-default .navbar-nav>li>a {
color: #337ab7;
}
html body .navbar-default .navbar-brand {
color: #337ab7;
}
\ No newline at end of file
/*global window, rJS, RSVP, URI, location,
loopEventListener*/
/*jslint nomen: true, indent: 2, maxerr: 3*/
(function (window, rJS, RSVP) {
"use strict";
function setERP5Configuration(gadget) {
var old_date = new Date(),
configuration = {};
// We are looking for documents modified in the past 3 month
old_date.setMonth(old_date - 2);
old_date.setDay(1);
configuration = {
type: "replicate",
// XXX This drop the signature lists...
query: {
query: 'portal_type:"Web Page" '
// XX Synchonizing the whole module is too much, here is a way to start quietly
// Supsended until modification_date is handled for synchronization
+ ' AND modification_date:>="'
+ today.toISOString(),
limit: [0, 1234567890]
},
use_remote_post: true,
conflict_handling: 1,
check_local_modification: true,
check_local_creation: true,
check_local_deletion: false,
check_remote_modification: true,
check_remote_creation: true,
check_remote_deletion: true,
local_sub_storage: {
type: "query",
sub_storage: {
type: "uuid",
sub_storage: {
type: "indexeddb",
database: "officejs"
}
}
},
remote_sub_storage: {
type: "erp5",
url: (new URI("hateoas"))
.absoluteTo(location.href)
.toString(),
default_view_reference: "jio_view"
}
};
return gadget.setSetting('jio_storage_description', configuration)
.push(function () {
return gadget.setSetting('jio_storage_name', "ERP5");
})
.push(function () {
return gadget.reload();
});
}
function setLocalConfiguration(gadget) {
var configuration = {
type: "query",
sub_storage: {
type: "uuid",
sub_storage: {
type: "indexeddb",
database: "officejs"
}
}
};
return gadget.setSetting('jio_storage_description', configuration)
.push(function () {
return gadget.reload();
});
}
function setDAVConfiguration(gadget) {
return gadget.redirect({page: 'jio_dav_configurator'});
}
var gadget_klass = rJS(window);
gadget_klass
.ready(function (g) {
g.props = {};
return g.getElement()
.push(function (element) {
g.props.element = element;
g.props.deferred = RSVP.defer();
});
})
.declareAcquiredMethod("updateHeader", "updateHeader")
.declareAcquiredMethod("translateHtml", "translateHtml")
.declareAcquiredMethod("redirect", "redirect")
.declareAcquiredMethod("reload", "reload")
.declareAcquiredMethod("setSetting", "setSetting")
.declareMethod("render", function () {
var gadget = this;
return gadget.updateHeader({
title: "Storage Configuration"
}).push(function () {
return gadget.props.deferred.resolve();
});
})
/////////////////////////////////////////
// Form submit
/////////////////////////////////////////
.declareService(function () {
var gadget = this;
return new RSVP.Queue()
.push(function () {
return gadget.props.deferred.promise;
})
.push(function () {
return RSVP.all([
loopEventListener(
gadget.props.element.querySelector('form.select-erp5-form'),
'submit',
true,
function () {
return setERP5Configuration(gadget);
}
),
loopEventListener(
gadget.props.element.querySelector('form.select-local-form'),
'submit',
true,
function () {
return setLocalConfiguration(gadget);
}
),
loopEventListener(
gadget.props.element.querySelector('form.select-dav-form'),
'submit',
true,
function () {
return setDAVConfiguration(gadget);
}
)
]);
});
});
}(window, rJS, RSVP));
\ No newline at end of file
nav.navbar-default {
background-color: none;
}
\ No newline at end of file
/*globals window, document, RSVP, rJS, Handlebars, console*/
/*jslint indent: 2, maxlen: 80*/
(function (window, document, RSVP, rJS, Handlebars, console) {
"use strict";
function callCribSWGadget(gadget, method, param_list) {
var called = false;
return new RSVP.Queue()
.push(function () {
return gadget.getDeclaredGadget("crib_sw_gadget");
})
.push(function (crib_sw_gadget) {
return crib_sw_gadget[method].apply(crib_sw_gadget, param_list);
})
.push(function (result) {
return result;
}, function (error) {
throw error;
});
}
rJS(window)
.ready(function (g) {
g.props = {};
return g.getElement()
.push(function (element) {
g.props.element = element;
});
})
.allowPublicAcquisition("crib_sw_allDocs", function (param_list) {
return callCribSWGadget(this, "allDocs", param_list);
})
.allowPublicAcquisition("crib_sw_remove", function (param_list) {
return callCribSWGadget(this, "remove", param_list);
})
.allowPublicAcquisition("crib_sw_put", function (param_list) {
return callCribSWGadget(this, "put", param_list);
})
.allowPublicAcquisition("crib_sw_get", function (param_list) {
return callCribSWGadget(this, "get", param_list);
})
.declareMethod('render', function (options) {
var promise_list = [],
gadget = this;
gadget.props.options = options;
// Add promise for list Cache content
// promise to use dav storage for jIO
return RSVP.Queue()
.push(function () {
return gadget.getDeclaredGadget('crib_ide_gadget');
})
.push(function (crib_ide_gadget) {
return crib_ide_gadget.render();
});
})
}(window, document, RSVP, rJS, console));
\ No newline at end of file
html body nav.navbar-default {
background-color: transparent;
}
/*Test*/
html body .navbar-default .navbar-nav>li>a {
color: #337ab7;
}
html body .navbar-default .navbar-brand {
color: #337ab7;
}
iframe {
width: 100%;
height: 100%;
top: 0;
bottom: 0;
position: fixed;
}
\ No newline at end of file
This diff is collapsed.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="/lib/bootstrap/bootstrap.min.css">
<link rel="stylesheet" href="/crib-editor3/cribjs.css">
<title>CribJS</title>
<script src="/lib/rsvp.js"></script>
<script src="/lib/jio-latest.js"></script>
<script src="/lib/renderjs.js"></script>
<script src="/gadget/gadget_global.js"></script>
<script src="cribjs_launcher.js"></script>
</head>
<body>
<div data-gadget-url="/gadget/gadget_jio.html"
data-gadget-scope="setting_gadget"
data-gadget-sandbox="public"></div>
<div data-gadget-url="/gadget/gadget_cribjs_router.html"
data-gadget-scope="router"
data-gadget-sandbox="public"></div>
<div data-gadget-url="/gadget/gadget_cribjs_header.html"
data-gadget-scope="header"
data-gadget-sandbox="public"></div>
<div data-gadget-url="/gadget/crib-sw-gadget.html"
data-gadget-scope="crib_sw_gadget"
data-gadget-sandbox="public"></div>
<div data-gadget-url="/gadget/gadget_jio.html"
data-gadget-scope="jio_gadget"
data-gadget-sandbox="public"></div>
<div role="main" class="ui-content gadget-content"></div>
</body>
</html>
\ No newline at end of file
https://www.cribjs.com/cribjs-conqueror.html
https://cedriclendav.node.vifib.com/public/cribjs/cribjs-conqueror.html
https://cedriclendav.node.vifib.com/public/cribjs-storage/
\ No newline at end of file
......@@ -6,8 +6,8 @@
<title>Crib SW interface Gadget</title>
<!-- renderjs -->
<script src="../lib/rsvp.js" type="text/javascript"></script>
<script src="../lib/renderjs.js" type="text/javascript"></script>
<script src="/lib/rsvp.js" type="text/javascript"></script>
<script src="/lib/renderjs.js" type="text/javascript"></script>
<!-- custom script -->
<script src="crib-sw-gadget.js" type="text/javascript"></script>
......
......@@ -135,7 +135,6 @@
.declareMethod('put', function(url, parameter) {
return new RSVP.Queue()
.push(function() {
console.log(url);
if (parameter.blob !== undefined) {
return sendMessage({
command: 'add',
......
......@@ -4,13 +4,13 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../lib/bootstrap/bootstrap.min.css">
<link rel="stylesheet" href="/lib/bootstrap/bootstrap.min.css">
<title>CribJS</title>
<script src="../lib/sha256.js"></script>
<script src="../lib/sha256.amd.js"></script>
<script src="../lib/rsvp.js"></script>
<script src="../lib/jio-latest.js"></script>
<script src="../lib/renderjs.js"></script>
<script src="/lib/sha256.js"></script>
<script src="/lib/sha256.amd.js"></script>
<script src="/lib/rsvp.js"></script>
<script src="/lib/jio-latest.js"></script>
<script src="/lib/renderjs.js"></script>
<script src="cribjs-ide-gadget.js"></script>
<!--The following CSS shows a lack of developing style -->
<style>
......
......@@ -5,23 +5,23 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Codemirror Gadget</title>
<script src="../lib/rsvp.js" type="text/javascript"></script>
<script src="../lib/renderjs.js" type="text/javascript"></script>
<script src="/lib/rsvp.js" type="text/javascript"></script>
<script src="/lib/renderjs.js" type="text/javascript"></script>
<link rel="stylesheet" href="../lib/codemirror.css">
<link rel="stylesheet" href="../lib/codemirror/addon/dialog/dialog.css">
<link rel="stylesheet" href="../lib/codemirror/addon/search/matchesonscrollbar.css">
<link rel="stylesheet" href="/lib/codemirror.css">
<link rel="stylesheet" href="/lib/codemirror/addon/dialog/dialog.css">
<link rel="stylesheet" href="/lib/codemirror/addon/search/matchesonscrollbar.css">
<script src="../lib/codemirror.js"></script>
<script src="../lib/codemirror/mode/css/css.js"></script>
<script src="../lib/codemirror/mode/xml/xml.js"></script>
<script src="../lib/codemirror/mode/javascript/javascript.js"></script>
<script src="../lib/codemirror/mode/htmlmixed/htmlmixed.js"></script>
<script src="../lib/codemirror/addon/dialog/dialog.js"></script>
<script src="../lib/codemirror/addon/search/searchcursor.js"></script>
<script src="../lib/codemirror/addon/search/search.js"></script>
<script src="../lib/codemirror/addon/scroll/annotatescrollbar.js"></script>
<script src="../lib/codemirror/addon/search/matchesonscrollbar.js"></script>
<script src="/lib/codemirror.js"></script>
<script src="/lib/codemirror/mode/css.js"></script>
<script src="/lib/codemirror/mode/xml.js"></script>
<script src="/lib/codemirror/mode/javascript.js"></script>
<script src="/lib/codemirror/mode/htmlmixed.js"></script>
<script src="/lib/codemirror/addon/dialog/dialog.js"></script>
<script src="/lib/codemirror/addon/search/searchcursor.js"></script>
<script src="/lib/codemirror/addon/search/search.js"></script>
<script src="/lib/codemirror/addon/scroll/annotatescrollbar.js"></script>
<script src="/lib/codemirror/addon/search/matchesonscrollbar.js"></script>
<script src="gadget_codemirror.js" type="text/javascript"></script>
</head>
......
<!DOCTYPE html>
<html>
<head>
<base href="https://texteditor.app.officejs.com/gadget_officejs_header.html/" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>OfficeJS Header</title>
<!-- renderjs -->
<script src="/lib/rsvp.js" type="text/javascript"></script>
<script src="/lib/renderjs.js" type="text/javascript"></script>
<script src="/lib/handlebars.js" type="text/javascript"></script>
<script src="gadget_global.js" type="text/javascript"></script>
<!-- custom script -->
<script src="gadget_cribjs_header.js" type="text/javascript"></script>
<script id="header-title-link-template" type="text/x-handlebars-template"><a data-i18n="{{title}}" class="ui-btn ui-btn-icon-left ui-icon-arrow-down" href="{{url}}">{{title}}</a></script>
<script id="header-title-template" type="text/x-handlebars-template"><span data-i18n="{{title}}">{{title}}</span></script>
<script id="header-link-template" type="text/x-handlebars-template">
<a role="button" data-i18n="{{title}}" href="{{url}}" class="responsive ui-btn ui-icon-{{icon}} ui-btn-icon-left ui-first-child ui-last-child {{class}}">{{title}}</a>
</script>
<script id="header-button-template" type="text/x-handlebars-template">
<form><button name='{{name}}' data-i18n="{{title}}" type='submit' class='responsive ui-btn ui-icon-{{icon}} ui-btn-icon-left ui-first-child ui-last-child {{class}}'>{{title}}</button></form>
</script>
</head>
<body>
<!--div data-role="header" data-theme="a" class="ui-header ui-bar-a" data-position="fixed" data-tap-toggle="false">
<div data-role="header" data-theme="a" class="ui-header ui-bar-a" data-tap-toggle="false">
<div class="ui-controlgroup ui-controlgroup-horizontal ui-btn-left">
<div class="ui-controlgroup-controls">
</div>
</div>
<h1 class="ui-title"></h1>
<div class="ui-controlgroup ui-controlgroup-horizontal ui-btn-right">
<div class="ui-controlgroup-controls">
</div>
</div>
</div-->
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#page=cribjs_home">CribJS</a>
</div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li><a href="#page=url_list">URL List</a></li>
<li><a href="#page=editor">Editor</a></li>
<li><a href="#page=save_load">Export/Import</a></li>
<li><a href="#page=mass_remove">Remove</a></li>
</ul>
</div>
</div>
</nav>
</body>
</html>
\ No newline at end of file
This diff is collapsed.
......@@ -6,16 +6,16 @@
<meta name="viewport" content="width=device-width">
<title>CribJS Loader</title>
<script src="../lib/rsvp.js"></script>
<script src="../lib/renderjs.js"></script>
<script src="/lib/rsvp.js"></script>
<script src="/lib/renderjs.js"></script>
<script src="gadget_cribjs_loader.js"></script>
</head>
<body>
<h1>CribJS Loader</h1>
<div data-gadget-url="gadget_jio_cribjs.html"
<div data-gadget-url="/gadget/gadget_jio_cribjs.html"
data-gadget-scope="jio_cribjs"
data-gadget-sandbox="public"></div>
<div data-gadget-url="gadget_jio_configurator.html"
<div data-gadget-url="/gadget/gadget_jio_configurator.html"
data-gadget-scope="jio_configurator"
data-gadget-sandbox="public"></div>
<form>
......
......@@ -8,7 +8,7 @@
jio_configurator_gadget;
return RSVP.Queue()
.push(function() {
return RSPV.all([
return RSVP.all([
gadget.getDeclaredGadget("jio_cribjs"),
gadget.getDeclaredGadget("jio_configurator")]);
})
......@@ -19,14 +19,14 @@
})
.push(function (jio_string) {
return jio_cribjs_gadget.load({
path: document.location.href,
path: document.location.origin,
jio_config: JSON.parse(jio_string),
application_id: "cribjs"
})
})
.push(function (url_list) {
console.log(url_list);
document.location = document.location.href + "/crib-editor/";
document.location = document.location.origin + "/crib-editor/";
})
}
......@@ -35,7 +35,6 @@
.declareMethod('render', function (options) {
var gadget = this,
jio_configuration_string = "";
console.log("rendering");
if (localStorage.hasOwnProperty("crib_js_loader_jio")) {
jio_configuration_string = localStorage.getItem("crib_js_loader_jio");
} else {
......@@ -46,12 +45,11 @@
return gadget.getDeclaredGadget('jio_configurator');
})
.push(function (jio_configurator_gadget) {
console.log(jio_configuration_string);
return jio_configurator_gadget.render({value: jio_configuration_string});
})
.push(function () {
return loopEventListener(
gadget.props.element.querySelector("form"),
gadget.props.element.querySelector("form.loading"),
'submit',
false,
function (event) {loadCribJS(gadget, event)}
......
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>CribJS Header</title>
</head>
<body>
<div class="nav_content cribjs container">
<h1>CribJS: have a taste of your web</h1>
<p>Developed to bring the free software idea to the web,
CribJS offer to you the possibility to create your version of the web application you are using.
Make your copy of the web from here: learn, modify, improve, share.</p>
<p>As this application is a place to develop web applications, it can edit itself.
See how it is made, modify it, improve it.
Start developping your own way. Feel free to make this place your own crib.</p>
<ul>
<li>1. Browse the <a href="#view=url_list">list of URLs</a> you wish to edit</li>
<li>2. Edit and add files in your <a href="#view=editor">Editor</a></li>
<li>3. <a href="#view=save_load">Export and Import</a> your copy of the web locally and remotly</li>
<li>4. <a href="#view=mass_remove">Remove</a> uncessary URLs</li>
</ul>
<p>Have fun building the web :), here is your <a href="/crib-editor/todo.txt">TODO list</a>.</p>
</div>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>CribJS Header</title>
<!-- renderjs -->
<script src="/lib/rsvp.js" type="text/javascript"></script>
<script src="/lib/renderjs.js" type="text/javascript"></script>
<script src="gadget_global.js" type="text/javascript"></script>
<!-- Custom -->
<script src="gadget_cribjs_page_editor.js" type="text/javascript"></script>
</head>
<body>
<div class="nav_content editor">
<div class="container">
<div class="row">
<form class="crib-editor-get form-inline">
<h3>Edit</h3>
<div class="form-group">
<label>URL:
<input name="url" class="url form-control" type="text" size="50" value=""></label>
</div>
<button type="submit" name="get" class="btn btn-default">Load</button>
</form>
</div>
<div class="row">
<form class="crib-editor-save form-inline">
<div class="form-group">
<label>Mimetype:
<input class="mimetype form-control" name="mimetype" type="text" size="50" value="text/html">
</label>
</div>
<div class="form-group">
<button name="add" type="submit" class="btn btn-primary">Save</button>
</div>
</form>
</div>
<div class="row">
<table class="table">
<tr>
<td class="success"><span class="crib-editor-save-status"></span></td>
</tr>
</table>
</div>
</div>
<div class="container-fluid">
<div data-gadget-url="/gadget/gadget_codemirror.html"
data-gadget-scope="codeeditor"
data-gadget-sandbox="public"></div>
</div>
</div>
</body>
</html>
\ No newline at end of file
/*global window, rJS, loopEventListener */
/*jslint nomen: true, indent: 2, maxerr: 3*/
(function (window, rJS, loopEventListener) {
"use strict";
var CODE_CONTENT_KEY = "text_content";
function saveTextContent(gadget, event) {
var content,
url = gadget.props.element.querySelector("form.crib-editor-get .url").value,
mimetype = gadget.props.element.querySelector("form.crib-editor-save .mimetype").value;
return new RSVP.Queue()
.push(function () {
return gadget.getDeclaredGadget('codeeditor');
})
.push(function (code_editor_gadget) {
return code_editor_gadget.getContent();
})
.push(function (data) {
content = data[CODE_CONTENT_KEY] || "";
return gadget.crib_sw_put(url, {content:content, type:mimetype});
})
.push(function() {
gadget.props.element.querySelector(".crib-editor-save-status").textContent = "Saved " + url + " files at "+ Date ()
})
}
function getUrlTextContent(gadget, event, url) {
return new RSVP.Queue()
.push(function () {
return RSVP.all([gadget.crib_sw_get(url),
gadget.getDeclaredGadget('codeeditor')])
})
.push(function(data_list) {
//gadget.props.element.querySelector("form.crib-editor-save .content").value = data_list[0].responseText;
gadget.props.element.querySelector("form.crib-editor-save .mimetype").value = data_list[0].responseType;
return data_list[1].render({
key: CODE_CONTENT_KEY,
value: data_list[0].responseText,
mode: data_list[0].responseType
});
})
}
rJS(window)
.ready(function (g) {
g.props = {};
return g.getElement()
.push(function (element) {
g.props.element = element;
g.props.start_deferred = RSVP.defer();
});
})
.allowPublicAcquisition("editor_saveContent", function () {
return saveTextContent(this, undefined);
})
.declareAcquiredMethod("crib_sw_get", "crib_sw_get")
.declareAcquiredMethod("crib_sw_put", "crib_sw_put")
.declareAcquiredMethod("getUrlFor", "getUrlFor")
.declareMethod('render', function (options) {
var gadget = this;
if (options === undefined)
options = {}
gadget.props.options = options;
return new RSVP.Queue()
.push(function () {
if (options.url !== undefined) {
gadget.props.element.querySelector("form.crib-editor-get .url").value = options.url;
return getUrlTextContent(gadget, undefined, options.url)
}
})
.push(function () {
return gadget.props.start_deferred.resolve();
})
})
.declareService(function () {
var gadget = this;
return new RSVP.Queue()
.push(function () {
return gadget.props.start_deferred.promise;
})
.push(function () {
var promise_list = [];
// promise to get content from URL
promise_list.push(loopEventListener(
gadget.props.element.querySelector(".crib-editor-get"),
'submit',
false,
function (event) {
var url = gadget.props.element.querySelector("form.crib-editor-get .url").value;
return getUrlTextContent(gadget, event, url);
}
));
// promise to save content
promise_list.push(loopEventListener(
gadget.props.element.querySelector(".crib-editor-save"),
'submit',
false,
function (event) {saveTextContent(gadget, event)}
));
return RSVP.all(promise_list);
});
})
}(window, rJS, loopEventListener));
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>CribJS Header</title>
<!-- renderjs -->
<script src="/lib/rsvp.js" type="text/javascript"></script>
<script src="/lib/renderjs.js" type="text/javascript"></script>
<script src="gadget_global.js" type="text/javascript"></script>
<!-- Custom -->
<script src="gadget_cribjs_page_mass_remove.js" type="text/javascript"></script>
</head>
<body>
<div class="nav_content mass_remove container">
<form class="crib-mass-remove">
<h3>Mass removal</h3>
<div class="form-group">
<textarea name="mass-remove-list" cols="35" wrap="soft" class="form-control"></textarea>
</div>
<button type="submit" class="mass-remove btn btn-danger" name="mass-remove">Mass remove from Cache</button>
<div><span class="crib-mass-remove-status"></span></div>
</form>
</div>
</body>
</html>
\ No newline at end of file
/*global window, rJS, loopEventListener */
/*jslint nomen: true, indent: 2, maxerr: 3*/
(function (window, rJS, loopEventListener) {
"use strict";
function massRemoveFromCache(gadget, event) {
var url_list = gadget.props.element.querySelector("form.crib-mass-remove textarea").value.match(/[^\r\n]+/g),
url_list_length = url_list.length;
return new RSVP.Queue()
.push(function () {
var i,
promise_list = [];
for (i = 0; i < url_list_length; i += 1) {
promise_list.push(gadget.crib_sw_remove(url_list[i]));
};
return RSVP.all(promise_list);
})
.push(function() {
gadget.props.element.querySelector(".crib-mass-remove-status").textContent = "Removed " + url_list.length + " files at "+ Date ()
})
.fail(function(error) {
gadget.props.element.querySelector(".crib-mass-remove-status").textContent = error;
console.log(error);
});
}
rJS(window)
.ready(function (g) {
g.props = {};
return g.getElement()
.push(function (element) {
g.props.element = element;
g.props.start_deferred = RSVP.defer();
});
})
.declareAcquiredMethod("crib_sw_remove", "crib_sw_remove")
.declareMethod('render', function (options) {
var gadget = this;
if (options === undefined)
options = {};
gadget.props.options = options;
return new RSVP.Queue()
.push(function () {
return gadget.props.start_deferred.resolve();
})
})
.declareService(function () {
var gadget = this;
return new RSVP.Queue()
.push(function () {
return gadget.props.start_deferred.promise;
})
.push(function () {
var promise_list = [];
// promise to remove content from cache
promise_list.push(loopEventListener(
gadget.props.element.querySelector(".crib-mass-remove"),
'submit',
false,
function (event) {massRemoveFromCache(gadget, event)}
));
return RSVP.all(promise_list);
});
})
}(window, rJS, loopEventListener));
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>CribJS Header</title>
<!-- renderjs -->
<script src="/lib/rsvp.js" type="text/javascript"></script>
<script src="/lib/renderjs.js" type="text/javascript"></script>
<script src="/lib/jszip.js" type="text/javascript"></script>
<script src="/lib/FileSaver.js" type="text/javascript"></script>
<script src="gadget_global.js" type="text/javascript"></script>
<!-- Custom -->
<script src="gadget_cribjs_page_save_load.js" type="text/javascript"></script>
</head>
<body>
<div class="nav_content save_load container">
<h3>Storage</h3>
<h4>Dav Storage</h4>
<form class="form-horizontal form-use-jio-dav">
<div class="form-group">
<label for="url" class="col-sm-2 control-label">URL</label>
<div class="col-sm-10">
<input type="text" class="form-control url" id="url" value="https://yourdav.node.vifib.com/public/cribjs-storage/">
</div>
</div>
<div class="form-group">
<label for="credential" class="col-sm-2 control-label">Credential</label>
<div class="col-sm-10">
<input type="password" class="form-control credential" id="credential" placeholder="couscous:admin">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Use Dav Storage</button>
</div>
</div>
</form>
<h4>Local Storage</h4>
<form class="form-horizontal form-use-jio-local">
<div class="form-group">
<div class="col-sm-offset-2 col-sm-8">
<button class="btn btn-default" type="submit">Local is Enough</button>
</div>
</div>
</form>
<form class="crib-save-to-jio form-inline">
<h3>Export</h3>
<div class="form-group">
<label>Export:
<input class="save-path form-control" name="save-path" type="text" size="30" value=""></label>
</div>
<div class="form-group">
<label> to:
<input name="save-id" class="save-id form-control" type="text" size="30" value="cribjs"></label>
</div>
<button name="save-contents" type="submit" class="btn btn-default">Export</button>
</form>
<div><span class="info crib-save-to-jio-status"></span></div>
<form class="crib-load-from-jio form-inline">
<h3>Import</h3>
<div class="form-group">
<label>Import :
<input name="load-id" class="load-id form-control" type="text" size="30" value="cribjs"></label>
</div>
<div class="form-group">
<label> to path:
<input name="load-path" class="load-path form-control" type="text" size="30" value="cribeditor/v1.1">
</label>
</div>
<button name="load-contents" class="load-contents btn btn-default" type="submit">Import</button>
</form>
<form class="crib-save-to-zip form-inline">
<h3>Export to Zip</h3>
<div class="form-group">
<label>Export to zip:
<input class="save-zip-path form-control" name="save-zip-path" type="text" size="30" value=""></label>
</div>
<div class="form-group">
<label> to:
<input name="save-zip-id" class="save-zip-id form-control" type="text" size="30" value="cribjs.zip"></label>
</div>
<button name="save-zip-contents" type="submit" class="btn btn-default">Export to Zip</button>
</form>
<div><span class="info crib-save-to-zip-status"></span></div>
<form class="crib-load-from-zip form-inline">
<h3>Import from zip</h3>
<div class="form-group">
<label>Import from zip:
<input name="load-zip-file" class="load-zip-file form-control" type="file" size="30"></label>
</div>
<div class="form-group">
<label> to path:
<input name="load-zip-path" class="load-zip-path form-control" type="text" size="30" value="cribeditor/v1.1">
</label>
</div>
<button name="load-zip-contents" class="load-zip-contents btn btn-default" type="submit">Import from zip</button>
</form>
<div><span class="crib-load-from-zip-status"></span></div>
</div>
<div data-gadget-url="/gadget/gadget_jio.html"
data-gadget-scope="jio_gadget"
data-gadget-sandbox="public"></div>
</body>
</html>
\ No newline at end of file
This diff is collapsed.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>CribJS Header</title>
<!-- renderjs -->
<script src="/lib/rsvp.js" type="text/javascript"></script>
<script src="/lib/renderjs.js" type="text/javascript"></script>
<script src="gadget_global.js" type="text/javascript"></script>
<!-- Custom -->
<script src="gadget_cribjs_page_url_list.js" type="text/javascript"></script>
</head>
<body>
<div class="nav_content url_list container">
<form class="crib-url-list-content">
<h3>URL List</h3>
<button type="submit" name="list-contents" class="btn btn-default">Refresh</button>
<table class="table table-striped table-condensed">
<thead>
<tr>
<th>Cached</th>
<th>Url</th>
<th>Go</th>
</tr>
</thead>
<tfoot>
</tfoot>
<tbody>
</tbody>
</table>
<div>
<button type="submit" name="list-contents" class="btn btn-default">Refresh</button>
</div>
</form>
</div>
</body>
</html>
\ No newline at end of file
/*global window, rJS, loopEventListener */
/*jslint nomen: true, indent: 2, maxerr: 3*/
(function (window, rJS, loopEventListener) {
"use strict";
function displayURLList(gadget, event) {
var url_list;
return new RSVP.Queue()
.push(function () {
return gadget.crib_sw_allDocs()
})
.push(function (data) {
var promise_list = [],
url;
url_list = data.urls;
for (url in url_list) {
if (url_list.hasOwnProperty(url)) {
promise_list.push(gadget.getUrlFor({page: 'editor', url: url}));
}
}
return RSVP.all(promise_list);
})
.push(function(url_link_list) {
var contentsElement = gadget.props.element.querySelector('.crib-url-list-content tbody'),
footer_element = gadget.props.element.querySelector('.crib-url-list-content tfoot'),
url_number = 0, cached_number = 0,
url, trElement, tdElement;
// Clear out the existing items from the list.
while (contentsElement.firstChild) {
contentsElement.removeChild(contentsElement.firstChild);
}
console.log(url_list);
// Add each cached URL to the list, one by one.
for (url in url_list) {
if (url_list.hasOwnProperty(url)) {
var element;
trElement = document.createElement('tr');
tdElement = document.createElement('td');
tdElement.innerHTML = (url_list[url].cached ? "<span>&#x2713;</span>" : "")
trElement.appendChild(tdElement);
tdElement = document.createElement('td');
element = document.createElement('a');
element.setAttribute('href', url_link_list[url_number]);
element.textContent = url;
tdElement.appendChild(element);
trElement.appendChild(tdElement);
tdElement = document.createElement('td');
element = document.createElement('a');
element.textContent = "Go";
element.setAttribute('href', url);
element.setAttribute('target', "_blank");
element.setAttribute("class", "btn btn-primary btn-xs");
tdElement.appendChild(element);
trElement.appendChild(tdElement);
contentsElement.appendChild(trElement);
cached_number = url_list[url].cached ? cached_number + 1 : cached_number;
url_number += 1;
}
};
while (footer_element.firstChild) {
footer_element.removeChild(footer_element.firstChild);
}
trElement = document.createElement('tr');
tdElement = document.createElement('td');
tdElement.innerHTML = "<span>" + cached_number + " &#x2713;</span>";
trElement.appendChild(tdElement);
tdElement = document.createElement('td');
tdElement.innerHTML = url_number + " URLs";
trElement.appendChild(tdElement);
tdElement = document.createElement('td');
trElement.appendChild(tdElement);
footer_element.appendChild(trElement);
})
}
rJS(window)
.ready(function (g) {
g.props = {};
return g.getElement()
.push(function (element) {
g.props.element = element;
g.props.start_deferred = RSVP.defer();
});
})
.declareAcquiredMethod("crib_sw_allDocs", "crib_sw_allDocs")
.declareAcquiredMethod("getUrlFor", "getUrlFor")
.declareMethod('render', function (options) {
var gadget = this;
if (options === undefined)
options = {}
gadget.props.options = options;
return new RSVP.Queue()
.push(function () {
return displayURLList(gadget, undefined);
})
.push(function () {
return gadget.props.start_deferred.resolve();
})
})
.declareService(function () {
var gadget = this;
return new RSVP.Queue()
.push(function () {
return gadget.props.start_deferred.promise;
})
.push(function () {
return loopEventListener(
gadget.props.element.querySelector(".crib-url-list-content"),
'submit',
false,
function (event) {displayURLList(gadget, event)}
)
});
})
}(window, rJS, loopEventListener));
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>CribSJ Router Gadget</title>
<!-- renderjs -->
<script src="/lib/rsvp.js" type="text/javascript"></script>
<script src="/lib/renderjs.js" type="text/javascript"></script>
<!-- custom script -->
<script src="gadget_cribjs_router.js" type="text/javascript"></script>
</head>
<body>
</body>
</html>
\ No newline at end of file
/*global window, rJS */
/*jslint nomen: true, indent: 2, maxerr: 3*/
(function (window, rJS) {
"use strict";
var gadget_klass = rJS(window),
MAIN_PAGE_PREFIX = "/gadget/gadget_cribjs_",
DEFAULT_PAGE = "cribjs_home",
REDIRECT_TIMEOUT = 5000;
function listenHashChange(gadget) {
function extractHashAndDispatch(evt) {
var hash = (evt.newURL || window.location.toString()).split('#')[1],
subhashes,
subhash,
keyvalue,
index,
args = {};
if (hash !== undefined) {
subhashes = hash.split('&');
for (index in subhashes) {
if (subhashes.hasOwnProperty(index)) {
subhash = subhashes[index];
if (subhash !== '') {
keyvalue = subhash.split('=');
if (keyvalue.length === 2) {
args[decodeURIComponent(keyvalue[0])] = decodeURIComponent(keyvalue[1]);
}
}
}
}
}
return gadget.renderApplication({
args: args
});
}
var result = loopEventListener(window, 'hashchange', false,
extractHashAndDispatch),
event = document.createEvent("Event");
event.initEvent('hashchange', true, true);
event.newURL = window.location.toString();
window.dispatchEvent(event);
return result;
}
gadget_klass
.ready(function (gadget) {
gadget.props = {
start_deferred: RSVP.defer()
};
})
.declareMethod("getCommandUrlFor", function(options) {
var prefix = '',
result,
key;
result = "#";
for (key in options) {
if (options.hasOwnProperty(key) && options[key] !== undefined) {
// Don't keep empty values
result += prefix + encodeURIComponent(key) + "=" + encodeURIComponent(options[key]);
prefix = '&';
}
}
return result;
})
.declareMethod('redirect', function (options) {
if (options !== undefined && options.toExternal) {
window.location.replace(options.url);
return RSVP.timeout(REDIRECT_TIMEOUT); // timeout if not redirected
}
else {
return this.getCommandUrlFor(options)
.push(function (hash) {
window.location.replace(hash);
// prevent returning unexpected response
// wait for the hash change to occur
// fail if nothing happens
return RSVP.timeout(REDIRECT_TIMEOUT);
});
}
})
.declareMethod('route', function (options) {
var gadget = this,
args = options.args;
gadget.options = options;
if (args.jio_key === undefined || args.jio_key === '') {
if (args.page === undefined || args.page === '' || args.page === "document_list") {
args.page = DEFAULT_PAGE;
}
return {
url: MAIN_PAGE_PREFIX + "page_" + args.page + ".html",
options: args
};
}
return gadget.jio_get(args.jio_key)
.push(function (doc) {
var sub_options = {},
base_portal_type = doc.portal_type.toLowerCase().replace(/\s/g, "_");
sub_options = {
doc: doc,
jio_key: args.jio_key,
search: args.search
};
if (base_portal_type.search(/_temp$/) >= 0) {
//Remove "_temp"
base_portal_type = base_portal_type.substr(
0,
base_portal_type.length - 5
);
}
return {
url: MAIN_PAGE_PREFIX + "jio_"
+ base_portal_type
+ "_" + args.page + ".html",
options: sub_options
};
});
})
.declareAcquiredMethod('jio_get', 'jio_get')
.declareAcquiredMethod('renderApplication', 'renderApplication')
.declareMethod('start', function () {
this.props.start_deferred.resolve();
})
.declareService(function () {
var gadget = this;
return new RSVP.Queue()
.push(function () {
return gadget.props.start_deferred.promise;
})
.push(function () {
return listenHashChange(gadget);
});
});
}(window, rJS));
\ No newline at end of file
/*global window, RSVP, FileReader */
/*jslint indent: 2, maxerr: 3, unparam: true */
(function (window, RSVP, FileReader) {
"use strict";
window.loopEventListener = function (target, type, useCapture, callback,
prevent_default) {
//////////////////////////
// Infinite event listener (promise is never resolved)
// eventListener is removed when promise is cancelled/rejected
//////////////////////////
var handle_event_callback,
callback_promise;
if (prevent_default === undefined) {
prevent_default = true;
}
function cancelResolver() {
if ((callback_promise !== undefined) &&
(typeof callback_promise.cancel === "function")) {
callback_promise.cancel();
}
}
function canceller() {
if (handle_event_callback !== undefined) {
target.removeEventListener(type, handle_event_callback, useCapture);
}
cancelResolver();
}
function itsANonResolvableTrap(resolve, reject) {
var result;
handle_event_callback = function (evt) {
if (prevent_default) {
evt.stopPropagation();
evt.preventDefault();
}
cancelResolver();
try {
result = callback(evt);
} catch (e) {
result = RSVP.reject(e);
}
callback_promise = result;
new RSVP.Queue()
.push(function () {
return result;
})
.push(undefined, function (error) {
if (!(error instanceof RSVP.CancellationError)) {
canceller();
reject(error);
}
});
};
target.addEventListener(type, handle_event_callback, useCapture);
}
return new RSVP.Promise(itsANonResolvableTrap, canceller);
};
window.promiseEventListener = function (target, type, useCapture) {
//////////////////////////
// Resolve the promise as soon as the event is triggered
// eventListener is removed when promise is cancelled/resolved/rejected
//////////////////////////
var handle_event_callback;
function canceller() {
target.removeEventListener(type, handle_event_callback, useCapture);
}
function resolver(resolve) {
handle_event_callback = function (evt) {
canceller();
evt.stopPropagation();
evt.preventDefault();
resolve(evt);
return false;
};
target.addEventListener(type, handle_event_callback, useCapture);
}
return new RSVP.Promise(resolver, canceller);
};
window.promiseReadAsText = function (file) {
return new RSVP.Promise(function (resolve, reject) {
var reader = new FileReader();
reader.onload = function (evt) {
resolve(evt.target.result);
};
reader.onerror = function (evt) {
reject(evt);
};
reader.readAsText(file);
});
};
}(window, RSVP, FileReader));
\ No newline at end of file
......@@ -8,10 +8,10 @@
<title>Jio Gadget</title>
<!-- renderjs -->
<script src="../lib/rsvp.js" type="text/javascript"></script>
<script src="../lib/renderjs.js" type="text/javascript"></script>
<script src="/lib/rsvp.js" type="text/javascript"></script>
<script src="/lib/renderjs.js" type="text/javascript"></script>
<script src="../lib/jio-latest.js" type="text/javascript"></script>
<script src="/lib/jio-latest.js" type="text/javascript"></script>
<!-- custom script -->
<script src="gadget_jio.js" type="text/javascript"></script>
......
......@@ -6,8 +6,8 @@
<meta name="viewport" content="width=device-width">
<title>CribJS Loader</title>
<script src="../lib/rsvp.js"></script>
<script src="../lib/renderjs.js"></script>
<script src="/lib/rsvp.js"></script>
<script src="/lib/renderjs.js"></script>
<script src="gadget_jio_configurator.js"></script>
</head>
<body>
......
......@@ -6,15 +6,15 @@
<meta name="viewport" content="width=device-width">
<title>CribJS Loader</title>
<script src="../lib/rsvp.js"></script>
<script src="../lib/renderjs.js"></script>
<script src="/lib/rsvp.js"></script>
<script src="/lib/renderjs.js"></script>
<script src="gadget_jio_cribjs.js"></script>
</head>
<body>
<div data-gadget-url="crib-sw-gadget.html"
<div data-gadget-url="/gadget/crib-sw-gadget.html"
data-gadget-scope="crib_sw_gadget"
data-gadget-sandbox="public"></div>
<div data-gadget-url="gadget_jio.html"
<div data-gadget-url="/gadget/gadget_jio.html"
data-gadget-scope="jio_gadget"
data-gadget-sandbox="public"></div>
</body>
......
......@@ -52,9 +52,8 @@
})
.push(function(response_list) {
var promise_list = [],
i, i_len, url, index, response, location, location_len,
new_url;
location = document.location.href;
i, i_len, url, index, response, location, location_len;
location = document.location.origin;
location_len = location.length
for (i = 0, i_len = response_list.length; i < i_len; i += 1) {
url = url_list[i]
......@@ -62,13 +61,8 @@
if (index != -1)
url = url.substr(index + location_len);
console.log(path_to_load + url);
if (path_to_load.endsWith("/") && url.startsWith("/")) {
new_url = path_to_load + url.substr(1)
} else {
new_url = path_to_load + url
}
promise_list.push(
crib_sw_gadget.put(new_url, {blob: response_list[i]})
crib_sw_gadget.put(path_to_load + url, {blob: response_list[i]})
)
}
return RSVP.all(promise_list);
......
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width">
<title>CribJS Loader</title>
<script src="/lib/rsvp.js"></script>
<script src="/lib/renderjs.js"></script>
<!--script src="gadget_jio_simple_configurator.js"></script-->
</head>
<body>
<h3>Storage</h3>
<div class="row">
<div class="col-md-6">
<form class="select-dav-form">
<button class="btn btn-default btn-lg btn-block" type="submit" data-i18n="DAV Storage">DAV Storage</button>
</form>
</div>
<div class="col-md-6">
<form class="select-local-form">
<button class="btn btn-default btn-lg btn-block" type="submit" data-i18n="Local is Enough">Local is Enough</button>
</form>
</div>
</div>
</body>
</html>
\ No newline at end of file
/*jslint nomen: true, indent: 2, maxerr: 3 */
/*global window, rJS */
(function (window, rJS) {
"use strict";
rJS(window)
.declareAcquiredMethod("saveContent", "editor_saveContent")
.declareMethod('render', function (options) {
if (options && options.hasOwnProperty("value"))
this.props.element.querySelector("textarea").value = options.value || "";
})
.declareMethod('getContent', function () {
return this.props.element.querySelector("textarea").value;
})
.ready(function (g) {
g.props = {};
return g.getElement()
.push(function (element) {
g.props.element = element;
});
});
}(window, rJS));
\ No newline at end of file
(function (global, factory) {
if (typeof define === "function" && define.amd) {
define([], factory);
} else if (typeof exports !== "undefined") {
factory();
} else {
var mod = {
exports: {}
};
factory();
global.FileSaver = mod.exports;
}
})(this, function () {
"use strict";
/*
* FileSaver.js
* A saveAs() FileSaver implementation.
*
* By Eli Grey, http://eligrey.com
*
* License : https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md (MIT)
* source : http://purl.eligrey.com/github/FileSaver.js
*/
// The one and only way of getting global scope in all environments
// https://stackoverflow.com/q/3277182/1008999
var _global = typeof window === 'object' && window.window === window ? window : typeof self === 'object' && self.self === self ? self : typeof global === 'object' && global.global === global ? global : void 0;
function bom(blob, opts) {
if (typeof opts === 'undefined') opts = {
autoBom: false
};else if (typeof opts !== 'object') {
console.warn('Deprecated: Expected third argument to be a object');
opts = {
autoBom: !opts
};
} // prepend BOM for UTF-8 XML and text/* types (including HTML)
// note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
if (opts.autoBom && /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
return new Blob([String.fromCharCode(0xFEFF), blob], {
type: blob.type
});
}
return blob;
}
function download(url, name, opts) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.onload = function () {
saveAs(xhr.response, name, opts);
};
xhr.onerror = function () {
console.error('could not download file');
};
xhr.send();
}
function corsEnabled(url) {
var xhr = new XMLHttpRequest(); // use sync to avoid popup blocker
xhr.open('HEAD', url, false);
try {
xhr.send();
} catch (e) {}
return xhr.status >= 200 && xhr.status <= 299;
} // `a.click()` doesn't work for all browsers (#465)
function click(node) {
try {
node.dispatchEvent(new MouseEvent('click'));
} catch (e) {
var evt = document.createEvent('MouseEvents');
evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null);
node.dispatchEvent(evt);
}
} // Detect WebView inside a native macOS app by ruling out all browsers
// We just need to check for 'Safari' because all other browsers (besides Firefox) include that too
// https://www.whatismybrowser.com/guides/the-latest-user-agent/macos
var isMacOSWebView = /Macintosh/.test(navigator.userAgent) && /AppleWebKit/.test(navigator.userAgent) && !/Safari/.test(navigator.userAgent);
var saveAs = _global.saveAs || ( // probably in some web worker
typeof window !== 'object' || window !== _global ? function saveAs() {}
/* noop */
// Use download attribute first if possible (#193 Lumia mobile) unless this is a macOS WebView
: 'download' in HTMLAnchorElement.prototype && !isMacOSWebView ? function saveAs(blob, name, opts) {
var URL = _global.URL || _global.webkitURL;
var a = document.createElement('a');
name = name || blob.name || 'download';
a.download = name;
a.rel = 'noopener'; // tabnabbing
// TODO: detect chrome extensions & packaged apps
// a.target = '_blank'
if (typeof blob === 'string') {
// Support regular links
a.href = blob;
if (a.origin !== location.origin) {
corsEnabled(a.href) ? download(blob, name, opts) : click(a, a.target = '_blank');
} else {
click(a);
}
} else {
// Support blobs
a.href = URL.createObjectURL(blob);
setTimeout(function () {
URL.revokeObjectURL(a.href);
}, 4E4); // 40s
setTimeout(function () {
click(a);
}, 0);
}
} // Use msSaveOrOpenBlob as a second approach
: 'msSaveOrOpenBlob' in navigator ? function saveAs(blob, name, opts) {
name = name || blob.name || 'download';
if (typeof blob === 'string') {
if (corsEnabled(blob)) {
download(blob, name, opts);
} else {
var a = document.createElement('a');
a.href = blob;
a.target = '_blank';
setTimeout(function () {
click(a);
});
}
} else {
navigator.msSaveOrOpenBlob(bom(blob, opts), name);
}
} // Fallback to using FileReader and a popup
: function saveAs(blob, name, opts, popup) {
// Open a popup immediately do go around popup blocker
// Mostly only available on user interaction and the fileReader is async so...
popup = popup || open('', '_blank');
if (popup) {
popup.document.title = popup.document.body.innerText = 'downloading...';
}
if (typeof blob === 'string') return download(blob, name, opts);
var force = blob.type === 'application/octet-stream';
var isSafari = /constructor/i.test(_global.HTMLElement) || _global.safari;
var isChromeIOS = /CriOS\/[\d]+/.test(navigator.userAgent);
if ((isChromeIOS || force && isSafari || isMacOSWebView) && typeof FileReader !== 'undefined') {
// Safari doesn't allow downloading of blob URLs
var reader = new FileReader();
reader.onloadend = function () {
var url = reader.result;
url = isChromeIOS ? url : url.replace(/^data:[^;]*;/, 'data:attachment/file;');
if (popup) popup.location.href = url;else location = url;
popup = null; // reverse-tabnabbing #460
};
reader.readAsDataURL(blob);
} else {
var URL = _global.URL || _global.webkitURL;
var url = URL.createObjectURL(blob);
if (popup) popup.location = url;else location.href = url;
popup = null; // reverse-tabnabbing #460
setTimeout(function () {
URL.revokeObjectURL(url);
}, 4E4); // 40s
}
});
_global.saveAs = saveAs.saveAs = saveAs;
if (typeof module !== 'undefined') {
module.exports = saveAs;
}
});
\ No newline at end of file
......@@ -41,21 +41,19 @@
/* CURSOR */
.CodeMirror-cursor {
.CodeMirror div.CodeMirror-cursor {
border-left: 1px solid black;
border-right: none;
width: 0;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.cm-fat-cursor .CodeMirror-cursor {
.CodeMirror.cm-fat-cursor div.CodeMirror-cursor {
width: auto;
border: 0;
background: #7e7;
}
.cm-fat-cursor div.CodeMirror-cursors {
.CodeMirror.cm-fat-cursor div.CodeMirror-cursors {
z-index: 1;
}
......@@ -84,7 +82,7 @@
}
/* Can style cursor different in overwrite (non-insert) mode */
.CodeMirror-overwrite .CodeMirror-cursor {}
div.CodeMirror-overwrite div.CodeMirror-cursor {}
.cm-tab { display: inline-block; text-decoration: inherit; }
......@@ -165,7 +163,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actual scrolling happens, thus preventing shaking and
before actuall scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute;
......@@ -286,19 +284,19 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
overflow: hidden;
visibility: hidden;
}
.CodeMirror-cursor { position: absolute; }
.CodeMirror-measure pre { position: static; }
.CodeMirror div.CodeMirror-cursor {
position: absolute;
border-right: none;
width: 0;
}
div.CodeMirror-cursors {
visibility: hidden;
position: relative;
z-index: 3;
}
div.CodeMirror-dragcursors {
visibility: visible;
}
.CodeMirror-focused div.CodeMirror-cursors {
visibility: visible;
}
......
This diff is collapsed.
......@@ -51,7 +51,7 @@
Annotation.prototype.computeScale = function() {
var cm = this.cm;
var hScale = (cm.getWrapperElement().clientHeight - cm.display.barHeight - this.buttonHeight * 2) /
cm.getScrollerElement().scrollHeight
cm.heightAtLine(cm.lastLine() + 1, "local");
if (hScale != this.hScale) {
this.hScale = hScale;
return true;
......@@ -100,9 +100,6 @@
elt.style.cssText = "position: absolute; right: 0px; width: " + Math.max(cm.display.barWidth - 1, 2) + "px; top: "
+ (top + this.buttonHeight) + "px; height: " + height + "px";
elt.className = this.options.className;
if (ann.id) {
elt.setAttribute("annotation-id", ann.id);
}
}
this.div.textContent = "";
this.div.appendChild(frag);
......
......@@ -29,7 +29,7 @@
query.lastIndex = stream.pos;
var match = query.exec(stream.string);
if (match && match.index == stream.pos) {
stream.pos += match[0].length || 1;
stream.pos += match[0].length;
return "searching";
} else if (match) {
stream.pos = match.index;
......@@ -76,21 +76,11 @@
else if (confirm(shortText)) fs[0]();
}
function parseString(string) {
return string.replace(/\\(.)/g, function(_, ch) {
if (ch == "n") return "\n"
if (ch == "r") return "\r"
return ch
})
}
function parseQuery(query) {
var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
if (isRE) {
try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); }
catch(e) {} // Not a regular expression after all, do a string search
} else {
query = parseString(query)
}
if (typeof query == "string" ? query == "" : query.test(""))
query = /x^/;
......@@ -117,19 +107,11 @@
if (state.query) return findNext(cm, rev);
var q = cm.getSelection() || state.lastQuery;
if (persistent && cm.openDialog) {
var hiding = null
persistentDialog(cm, queryDialog, q, function(query, event) {
CodeMirror.e_stop(event);
if (!query) return;
if (query != state.queryText) startSearch(cm, state, query);
if (hiding) hiding.style.opacity = 1
findNext(cm, event.shiftKey, function(_, to) {
var dialog
if (to.line < 3 && document.querySelector &&
(dialog = cm.display.wrapper.querySelector(".CodeMirror-dialog")) &&
dialog.getBoundingClientRect().bottom - 4 > cm.cursorCoords(to, "window").top)
(hiding = dialog).style.opacity = .4
})
findNext(cm, event.shiftKey);
});
} else {
dialog(cm, queryDialog, "Search for:", q, function(query) {
......@@ -142,7 +124,7 @@
}
}
function findNext(cm, rev, callback) {cm.operation(function() {
function findNext(cm, rev) {cm.operation(function() {
var state = getSearchState(cm);
var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
if (!cursor.find(rev)) {
......@@ -152,7 +134,6 @@
cm.setSelection(cursor.from(), cursor.to());
cm.scrollIntoView({from: cursor.from(), to: cursor.to()}, 20);
state.posFrom = cursor.from(); state.posTo = cursor.to();
if (callback) callback(cursor.from(), cursor.to())
});}
function clearSearch(cm) {cm.operation(function() {
......@@ -165,11 +146,18 @@
});}
var replaceQueryDialog =
' <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
'Replace: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
var replacementQueryDialog = 'With: <input type="text" style="width: 10em" class="CodeMirror-search-field"/>';
var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>All</button> <button>Stop</button>";
var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
function replaceAll(cm, query, text) {
function replace(cm, all) {
if (cm.getOption("readOnly")) return;
var query = cm.getSelection() || getSearchState(cm).lastQuery;
dialog(cm, replaceQueryDialog, "Replace:", query, function(query) {
if (!query) return;
query = parseQuery(query);
dialog(cm, replacementQueryDialog, "Replace with:", "", function(text) {
if (all) {
cm.operation(function() {
for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
if (typeof query != "string") {
......@@ -178,19 +166,6 @@
} else cursor.replace(text);
}
});
}
function replace(cm, all) {
if (cm.getOption("readOnly")) return;
var query = cm.getSelection() || getSearchState(cm).lastQuery;
var dialogText = all ? "Replace all:" : "Replace:"
dialog(cm, dialogText + replaceQueryDialog, dialogText, query, function(query) {
if (!query) return;
query = parseQuery(query);
dialog(cm, replacementQueryDialog, "Replace with:", "", function(text) {
text = parseString(text)
if (all) {
replaceAll(cm, query, text)
} else {
clearSearch(cm);
var cursor = getSearchCursor(cm, query, cm.getCursor());
......@@ -204,8 +179,7 @@
cm.setSelection(cursor.from(), cursor.to());
cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
confirmDialog(cm, doReplaceConfirm, "Replace?",
[function() {doReplace(match);}, advance,
function() {replaceAll(cm, query, text)}]);
[function() {doReplace(match);}, advance]);
};
var doReplace = function(match) {
cursor.replace(typeof query == "string" ? text :
......
This diff is collapsed.
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
var htmlMode = CodeMirror.getMode(config, {name: "xml",
htmlMode: true,
multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag});
var cssMode = CodeMirror.getMode(config, "css");
var scriptTypes = [], scriptTypesConf = parserConfig && parserConfig.scriptTypes;
scriptTypes.push({matches: /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i,
mode: CodeMirror.getMode(config, "javascript")});
if (scriptTypesConf) for (var i = 0; i < scriptTypesConf.length; ++i) {
var conf = scriptTypesConf[i];
scriptTypes.push({matches: conf.matches, mode: conf.mode && CodeMirror.getMode(config, conf.mode)});
}
scriptTypes.push({matches: /./,
mode: CodeMirror.getMode(config, "text/plain")});
function html(stream, state) {
var tagName = state.htmlState.tagName;
if (tagName) tagName = tagName.toLowerCase();
var style = htmlMode.token(stream, state.htmlState);
if (tagName == "script" && /\btag\b/.test(style) && stream.current() == ">") {
// Script block: mode to change to depends on type attribute
var scriptType = stream.string.slice(Math.max(0, stream.pos - 100), stream.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i);
scriptType = scriptType ? scriptType[1] : "";
if (scriptType && /[\"\']/.test(scriptType.charAt(0))) scriptType = scriptType.slice(1, scriptType.length - 1);
for (var i = 0; i < scriptTypes.length; ++i) {
var tp = scriptTypes[i];
if (typeof tp.matches == "string" ? scriptType == tp.matches : tp.matches.test(scriptType)) {
if (tp.mode) {
state.token = script;
state.localMode = tp.mode;
state.localState = tp.mode.startState && tp.mode.startState(htmlMode.indent(state.htmlState, ""));
}
break;
}
}
} else if (tagName == "style" && /\btag\b/.test(style) && stream.current() == ">") {
state.token = css;
state.localMode = cssMode;
state.localState = cssMode.startState(htmlMode.indent(state.htmlState, ""));
}
return style;
}
function maybeBackup(stream, pat, style) {
var cur = stream.current();
var close = cur.search(pat);
if (close > -1) stream.backUp(cur.length - close);
else if (cur.match(/<\/?$/)) {
stream.backUp(cur.length);
if (!stream.match(pat, false)) stream.match(cur);
}
return style;
}
function script(stream, state) {
if (stream.match(/^<\/\s*script\s*>/i, false)) {
state.token = html;
state.localState = state.localMode = null;
return null;
}
return maybeBackup(stream, /<\/\s*script\s*>/,
state.localMode.token(stream, state.localState));
}
function css(stream, state) {
if (stream.match(/^<\/\s*style\s*>/i, false)) {
state.token = html;
state.localState = state.localMode = null;
return null;
}
return maybeBackup(stream, /<\/\s*style\s*>/,
cssMode.token(stream, state.localState));
}
return {
startState: function() {
var state = htmlMode.startState();
return {token: html, localMode: null, localState: null, htmlState: state};
},
copyState: function(state) {
if (state.localState)
var local = CodeMirror.copyState(state.localMode, state.localState);
return {token: state.token, localMode: state.localMode, localState: local,
htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
},
token: function(stream, state) {
return state.token(stream, state);
},
indent: function(state, textAfter) {
if (!state.localMode || /^\s*<\//.test(textAfter))
return htmlMode.indent(state.htmlState, textAfter);
else if (state.localMode.indent)
return state.localMode.indent(state.localState, textAfter);
else
return CodeMirror.Pass;
},
innerMode: function(state) {
return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
}
};
}, "xml", "javascript", "css");
CodeMirror.defineMIME("text/html", "htmlmixed");
});
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*global window, RSVP, FileReader */
/*jslint indent: 2, maxerr: 3, unparam: true */
(function (window, RSVP, FileReader) {
"use strict";
window.loopEventListener = function (target, type, useCapture, callback,
prevent_default) {
//////////////////////////
// Infinite event listener (promise is never resolved)
// eventListener is removed when promise is cancelled/rejected
//////////////////////////
var handle_event_callback,
callback_promise;
if (prevent_default === undefined) {
prevent_default = true;
}
function cancelResolver() {
if ((callback_promise !== undefined) &&
(typeof callback_promise.cancel === "function")) {
callback_promise.cancel();
}
}
function canceller() {
if (handle_event_callback !== undefined) {
target.removeEventListener(type, handle_event_callback, useCapture);
}
cancelResolver();
}
function itsANonResolvableTrap(resolve, reject) {
var result;
handle_event_callback = function (evt) {
if (prevent_default) {
evt.stopPropagation();
evt.preventDefault();
}
cancelResolver();
try {
result = callback(evt);
} catch (e) {
result = RSVP.reject(e);
}
callback_promise = result;
new RSVP.Queue()
.push(function () {
return result;
})
.push(undefined, function (error) {
if (!(error instanceof RSVP.CancellationError)) {
canceller();
reject(error);
}
});
};
target.addEventListener(type, handle_event_callback, useCapture);
}
return new RSVP.Promise(itsANonResolvableTrap, canceller);
};
window.promiseEventListener = function (target, type, useCapture) {
//////////////////////////
// Resolve the promise as soon as the event is triggered
// eventListener is removed when promise is cancelled/resolved/rejected
//////////////////////////
var handle_event_callback;
function canceller() {
target.removeEventListener(type, handle_event_callback, useCapture);
}
function resolver(resolve) {
handle_event_callback = function (evt) {
canceller();
evt.stopPropagation();
evt.preventDefault();
resolve(evt);
return false;
};
target.addEventListener(type, handle_event_callback, useCapture);
}
return new RSVP.Promise(resolver, canceller);
};
window.promiseReadAsText = function (file) {
return new RSVP.Promise(function (resolve, reject) {
var reader = new FileReader();
reader.onload = function (evt) {
resolve(evt.target.result);
};
reader.onerror = function (evt) {
reject(evt);
};
reader.readAsText(file);
});
};
}(window, RSVP, FileReader));
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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