Commit 403dada0 authored by Thibaut Frain's avatar Thibaut Frain

Added presentation editor

parent ddea4d9c
/*global window, rJS, jQuery */
(function (window, $, rJS) { (function (window, $, rJS) {
"use strict"; "use strict";
...@@ -27,6 +29,11 @@ ...@@ -27,6 +29,11 @@
"title" : "Aloha Editor Gadget", "title" : "Aloha Editor Gadget",
"interface" : "http://www.renderjs.org/interface/editor" "interface" : "http://www.renderjs.org/interface/editor"
}, },
editor_5_dict = {
"path" : "./presentation-editor.html",
"title" : "Presentation Editor Gadget",
"interface" : "http://www.renderjs.org/interface/editor"
},
catalog_list = [ catalog_list = [
{ {
"path" : "./officejs.html", "path" : "./officejs.html",
...@@ -40,6 +47,7 @@ ...@@ -40,6 +47,7 @@
catalog_list.push(editor_2_dict); catalog_list.push(editor_2_dict);
catalog_list.push(editor_3_dict); catalog_list.push(editor_3_dict);
catalog_list.push(editor_4_dict); catalog_list.push(editor_4_dict);
catalog_list.push(editor_5_dict);
gk.declareMethod('allDocs', function (filter) { gk.declareMethod('allDocs', function (filter) {
var deferred = $.Deferred(); var deferred = $.Deferred();
...@@ -50,7 +58,7 @@ ...@@ -50,7 +58,7 @@
deferred.resolve([io_dict]); deferred.resolve([io_dict]);
} else if (filter.query === } else if (filter.query ===
'interface: "http://www.renderjs.org/interface/editor"') { 'interface: "http://www.renderjs.org/interface/editor"') {
deferred.resolve([editor_1_dict, editor_2_dict, editor_3_dict, editor_4_dict]); deferred.resolve([editor_1_dict, editor_2_dict, editor_3_dict, editor_4_dict, editor_5_dict]);
} else { } else {
deferred.reject("Unsupported filter"); deferred.reject("Unsupported filter");
} }
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Presentation editor</title>
<script src="presentation-editor/lib/jquery.min.js"></script>
<script src="presentation-editor/lib/jquery-ui.min.js"></script>
<script src="presentation-editor/lib/jquery.mobile.min.js"></script>
<script src="presentation-editor/lib/beautify-html.js"></script>
<script src="presentation-editor/lib/rsvp.min.js"></script>
<script src="presentation-editor/lib/jschannel.js"></script>
<script src="presentation-editor/lib/renderjs.js"></script>
<script src="presentation-editor/presentation-editor.js"></script>
<script src="presentation-editor.js"></script>
<link rel="stylesheet" href="presentation-editor/css/jquery-ui.min.css">
<link rel="stylesheet" href="presentation-editor/css/jquery.mobile.min.css">
<link rel="stylesheet" href="presentation-editor/css/presentation-editor.css">
</head>
<body>
<div data-role="page">
<input type="button" value="Add slide" id="add-slide" data-inline="true"></input>
<form id="slide-form" style="display:none;">
<div data-role="fieldcontain">
<label for="title" >Title:</label>
<input type="text" name="title" id="title" value="" />
</div>
<div data-role="fieldcontain">
<select name="Type" id="type" data-inline="true">
<option value="chapter">chapter</option>
<option value="illustration">illustration</option>
</select>
</div>
<div data-role="fieldcontain">
<label for="content">Content:</label>
<textarea name="content" id="content"></textarea>
</div>
<input data-inline="true" type="submit" id="submit" value="Add slide">
</form>
<div id="slide-list"></div>
<template id="slide-html">
<section>
<button class="edit ui-shadow ui-mini ui-corner-all ui-btn ui-btn-inline"
data-inline="true">
Edit
</button>
<button class="delete ui-shadow ui-mini ui-corner-all ui-btn ui-btn-inline"
data-inline="true">
Delete
</button>
<div class="slide ui-shadow ui-corner-all">
<h1></h1>
<div class="content"></div>
</div>
</section>
</template>
<template id="slide-data">
<section>
<h1></h1>
</section>
</template>
</div>
</body>
</html>
/*global window, rJS, jQuery */
(function (window, rJS, $) {
"use strict";
rJS(window)
.declareMethod('setContent', function (content) {
rJS(this).editor.setContent(content);
})
.declareMethod('getContent', function () {
return rJS(this).editor.getContent();
})
.ready(function (g) {
g.editor = $('#slide-list').presentation();
});
}(window, rJS, jQuery));
{
"name": "prezedit",
"version": "0.0.0",
"authors": [
"Thibaut Frain <thibaut.frain@tiolive.com>"
],
"license": "MIT",
"private": true,
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"jquery": "2.0.3",
"jquery-mobile": "1.4.0",
"jquery-ui": "1.10.3",
"js-beautify": "1.4.2"
}
}
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
#templates {
display: none;
}
#slide-list {
margin: 50px;
}
#slide-list section {
display: block;
float: left;
margin: 2%;
position: relative;
padding: 5px;
cursor: pointer;
}
section > button#edit-button {
display: inline-block;
}
section > h1 {
text-align: center;
}
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Presentation editor</title>
<script src="lib/jquery.min.js"></script>
<script src="lib/jquery-ui.min.js"></script>
<script src="lib/jquery.mobile.min.js"></script>
<script src="lib/beautify-html.js"></script>
<script src="lib/rsvp.min.js"></script>
<script src="lib/jschannel.js"></script>
<script src="lib/renderjs.js"></script>
<script src="presentation-editor.js"></script>
<link rel="stylesheet" href="css/jquery-ui.min.css">
<link rel="stylesheet" href="css/jquery.mobile.min.css">
<link rel="stylesheet" href="presentation-editor.css">
</head>
<body>
<div data-role="page">
<input type="button" value="Add slide" id="add-slide" data-inline="true"></input>
<form id="slide-form" style="display:none;">
<div data-role="fieldcontain">
<label for="title" >Title:</label>
<input type="text" name="title" id="title" value="" />
</div>
<div data-role="fieldcontain">
<select name="Type" id="type" data-inline="true">
<option value="chapter">chapter</option>
<option value="illustration">illustration</option>
</select>
</div>
<div data-role="fieldcontain">
<label for="content">Content:</label>
<textarea name="content" id="content"></textarea>
</div>
<input data-inline="true" type="submit" id="submit" value="Add slide">
</form>
<div id="slide-list"></div>
<template id="slide-html">
<section>
<button class="edit ui-shadow ui-mini ui-corner-all ui-btn ui-btn-inline"
data-inline="true">
Edit
</button>
<button class="delete ui-shadow ui-mini ui-corner-all ui-btn ui-btn-inline"
data-inline="true">
Delete
</button>
<div class="slide ui-shadow ui-corner-all">
<h1></h1>
<div class="content"></div>
</div>
</section>
</template>
<template id="slide-data">
<section>
<h1></h1>
</section>
</template>
</div>
</body>
</html>
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
!function(){var a,b;!function(){var c={},d={};a=function(a,b,d){c[a]={deps:b,callback:d}},b=function(a){if(d[a])return d[a];d[a]={};var e=c[a];if(!e)throw new Error("Module '"+a+"' not found.");for(var f,g=e.deps,h=e.callback,i=[],j=0,k=g.length;k>j;j++)i.push("exports"===g[j]?f={}:b(g[j]));var l=h.apply(this,i);return d[a]=f||l}}(),a("rsvp/all",["rsvp/promise","exports"],function(a,b){"use strict";function c(a,b){function c(){for(var a,c=0;c<b.length;c++)a=b[c],a&&"function"==typeof a.then&&"function"==typeof a.cancel&&a.cancel()}if("[object Array]"!==Object.prototype.toString.call(b))throw new TypeError("You must pass an array to all.");return new f(function(d,e,f){function g(a){return function(b){h(a,b)}}function h(a,b){l[a]=b,--m===n&&(0===n?d(l):(d(b),c()))}function i(a){return function(b){f({index:a,value:b})}}function j(a){e(a),c()}var k,l=[],m=b.length,n=b.length-a;0===m&&(1===a?d():d([]));for(var o=0;o<b.length;o++)k=b[o],k&&"function"==typeof k.then?k.then(g(o),j,i(o)):h(o,k)},c)}function d(a){return c(a.length,a)}function e(a){return c(1,a)}var f=a.Promise;b.all=d,b.any=e}),a("rsvp/async",["exports"],function(a){"use strict";function b(){return function(a,b){process.nextTick(function(){a(b)})}}function c(){return function(a,b){setImmediate(function(){a(b)})}}function d(){var a=[],b=new h(function(){var b=a.slice();a=[],b.forEach(function(a){var b=a[0],c=a[1];b(c)})}),c=document.createElement("div");return b.observe(c,{attributes:!0}),window.addEventListener("unload",function(){b.disconnect(),b=null},!1),function(b,d){a.push([b,d]),c.setAttribute("drainQueue","drainQueue")}}function e(){return function(a,b){i.setTimeout(function(){a(b)},1)}}var f,g="undefined"!=typeof window?window:{},h=g.MutationObserver||g.WebKitMutationObserver,i="undefined"!=typeof global?global:this;f="function"==typeof setImmediate?c():"undefined"!=typeof process&&"[object process]"==={}.toString.call(process)?b():h?d():e(),a.async=f}),a("rsvp/cancellation_error",["exports"],function(a){"use strict";function b(a){if(this.name="cancel",void 0!==a&&"string"!=typeof a)throw new TypeError("You must pass a string.");this.message=a||"Default Message"}b.prototype=new Error,b.prototype.constructor=b,a.CancellationError=b}),a("rsvp/config",["rsvp/async","exports"],function(a,b){"use strict";var c=a.async,d={};d.async=c,b.config=d}),a("rsvp/defer",["rsvp/promise","exports"],function(a,b){"use strict";function c(){var a={resolve:void 0,reject:void 0,promise:void 0};return a.promise=new d(function(b,c){a.resolve=b,a.reject=c}),a}var d=a.Promise;b.defer=c}),a("rsvp/events",["exports"],function(a){"use strict";var b=function(a,b){this.type=a;for(var c in b)b.hasOwnProperty(c)&&(this[c]=b[c])},c=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c][0]===b)return c;return-1},d=function(a){var b=a._promiseCallbacks;return b||(b=a._promiseCallbacks={}),b},e={mixin:function(a){return a.on=this.on,a.off=this.off,a.trigger=this.trigger,a},on:function(a,b,e){var f,g,h=d(this);for(a=a.split(/\s+/),e=e||this;g=a.shift();)f=h[g],f||(f=h[g]=[]),-1===c(f,b)&&f.push([b,e])},off:function(a,b){var e,f,g,h=d(this);for(a=a.split(/\s+/);f=a.shift();)b?(e=h[f],g=c(e,b),-1!==g&&e.splice(g,1)):h[f]=[]},trigger:function(a,c){var e,f,g,h,i,j=d(this);if(e=j[a])for(var k=0;k<e.length;k++)f=e[k],g=f[0],h=f[1],"object"!=typeof c&&(c={detail:c}),i=new b(a,c),g.call(h,i)}};a.EventTarget=e}),a("rsvp/hash",["rsvp/defer","exports"],function(a,b){"use strict";function c(a){var b=0;for(var c in a)b++;return b}function d(a){var b={},d=e(),f=c(a);0===f&&d.resolve({});var g=function(a){return function(b){h(a,b)}},h=function(a,c){b[a]=c,0===--f&&d.resolve(b)},i=function(a){d.reject(a)};for(var j in a)a[j]&&"function"==typeof a[j].then?a[j].then(g(j),i):h(j,a[j]);return d.promise}var e=a.defer;b.hash=d}),a("rsvp/node",["rsvp/promise","rsvp/all","exports"],function(a,b,c){"use strict";function d(a,b){return function(c,d){c?b(c):a(arguments.length>2?Array.prototype.slice.call(arguments,1):d)}}function e(a){return function(){var b,c,e=Array.prototype.slice.call(arguments),h=this,i=new f(function(a,d){b=a,c=d});return g(e).then(function(e){e.push(d(b,c));try{a.apply(h,e)}catch(f){c(f)}}),i}}var f=a.Promise,g=b.all;c.denodeify=e}),a("rsvp/promise",["rsvp/config","rsvp/events","rsvp/cancellation_error","exports"],function(a,b,c,d){"use strict";function e(a){return f(a)||"object"==typeof a&&null!==a}function f(a){return"function"==typeof a}function g(a){m.onerror&&m.onerror(a.detail)}function h(a,b){a===b?j(a,b):i(a,b)||j(a,b)}function i(a,b){var c,d=null;try{if(a===b)throw new TypeError("A promises callback cannot return that same promise.");if(e(b)&&(d=b.then,f(d)))return a.on("promise:cancelled",function(){f(b.cancel)&&b.cancel()}),d.call(b,function(d){return c?!0:(c=!0,void(b!==d?h(a,d):j(a,d)))},function(b){return c?!0:(c=!0,void k(a,b))}),!0}catch(g){return k(a,g),!0}return!1}function j(a,b){m.async(function(){a.isFulfilled||a.isRejected||(a.trigger("promise:resolved",{detail:b}),a.isFulfilled=!0,a.fulfillmentValue=b)})}function k(a,b){m.async(function(){a.isFulfilled||a.isRejected||(a.trigger("promise:failed",{detail:b}),a.isRejected=!0,a.rejectedReason=b)})}function l(a,b){m.async(function(){a.trigger("promise:notified",{detail:b})})}var m=a.config,n=b.EventTarget,o=c.CancellationError,p=function(a,b){var c=this,d=!1;if("function"!=typeof a)throw new TypeError("You must pass a resolver function as the sole argument to the promise constructor");if(void 0!==b&&"function"!=typeof b)throw new TypeError("You can only pass a canceller function as the second argument to the promise constructor");if(!(c instanceof p))return new p(a,b);var e=function(a){d||(d=!0,h(c,a))},f=function(a){d||(d=!0,k(c,a))},i=function(a){d||l(c,a)};this.on("promise:failed",function(a){this.trigger("error",{detail:a.detail})},this),this.on("error",g),this.cancel=function(){if(!d){if(void 0!==b)try{b()}catch(a){return void f(a)}f(new o)}};try{a(e,f,i)}catch(j){f(j)}},q=function(a,b,c,d){var e,g,j,l,m=f(c);if(!b.isFulfilled&&!b.isRejected){if(m)try{e=c(d.detail),j=!0}catch(n){l=!0,g=n}else e=d.detail,j=!0;i(b,e)||(m&&j?h(b,e):l?k(b,g):"resolve"===a?h(b,e):"reject"===a&&k(b,e))}},r=function(a,b,c){var d;if("function"==typeof b){try{d=b(c.detail)}catch(e){return}l(a,d)}else l(a,c.detail)};p.prototype={constructor:p,isRejected:void 0,isFulfilled:void 0,rejectedReason:void 0,fulfillmentValue:void 0,then:function(a,b,c){this.off("error",g);var d=new this.constructor(function(){},function(){d.trigger("promise:cancelled",{})});return this.isFulfilled&&m.async(function(b){q("resolve",d,a,{detail:b.fulfillmentValue})},this),this.isRejected&&m.async(function(a){q("reject",d,b,{detail:a.rejectedReason})},this),this.on("promise:resolved",function(b){q("resolve",d,a,b)}),this.on("promise:failed",function(a){q("reject",d,b,a)}),this.on("promise:notified",function(a){r(d,c,a)}),d},fail:function(a){return this.then(null,a)},always:function(a){return this.then(a,a)}},n.mixin(p.prototype),d.Promise=p}),a("rsvp/queue",["rsvp/promise","rsvp/timeout","exports"],function(a,b,c){"use strict";function d(a){if(this.name="resolved",void 0!==a&&"string"!=typeof a)throw new TypeError("You must pass a string.");this.message=a||"Default Message"}var e=a.Promise,f=b.delay;d.prototype=new Error,d.prototype.constructor=d;var g=function(){function a(){for(var a=0;2>a;a++)k[a].cancel()}var b,c,h,i,j=this,k=[];return this instanceof g?(b=new e(function(a,b){c=function(b){return i?void 0:(j.isFulfilled=!0,j.fulfillmentValue=b,i=!0,a(b))},h=function(a){return i?void 0:(j.isRejected=!0,j.rejectedReason=a,i=!0,b(a))}},a),k.push(f()),k.push(k[0].then(function(){k.splice(0,2),0===k.length&&c()})),j.cancel=function(){i||(i=!0,b.cancel(),b.fail(function(a){j.isRejected=!0,j.rejectedReason=a}))},j.then=function(){return b.then.apply(b,arguments)},void(j.push=function(a,b){var e,f=k[k.length-1];if(i)throw new d;return e=f.then(a,b),k.push(e),k.push(e.then(function(a){return k.splice(0,2),0!==k.length?a:void c(a)},function(a){if(k.splice(0,2),0!==k.length)throw a;h(a)})),this})):new g};g.prototype=Object.create(e.prototype),g.prototype.constructor=g,c.Queue=g,c.ResolvedQueueError=d}),a("rsvp/reject",["rsvp/promise","exports"],function(a,b){"use strict";function c(a){return new d(function(b,c){c(a)})}var d=a.Promise;b.reject=c}),a("rsvp/resolve",["rsvp/promise","exports"],function(a,b){"use strict";function c(a){return new d(function(b,c){if("object"==typeof a&&null!==a){var d=a.then;if(void 0!==d&&"function"==typeof d)return d.apply(a,[b,c])}return b(a)},function(){void 0!==a&&void 0!==a.cancel&&a.cancel()})}var d=a.Promise;b.resolve=c}),a("rsvp/rethrow",["exports"],function(a){"use strict";function b(a){throw c.setTimeout(function(){throw a}),a}var c="undefined"==typeof global?this:global;a.rethrow=b}),a("rsvp/timeout",["rsvp/promise","exports"],function(a,b){"use strict";function c(a,b,c){function d(d,e){g=setTimeout(function(){b?e(c):d(c)},a)}function e(){clearTimeout(g)}var g;return new f(d,e)}function d(a,b){return c(a,!1,b)}function e(a){return c(a,!0,"Timed out after "+a+" ms")}var f=a.Promise;f.prototype.delay=function(a){return this.then(function(b){return d(a,b)})},b.delay=d,b.timeout=e}),a("rsvp",["rsvp/events","rsvp/cancellation_error","rsvp/promise","rsvp/node","rsvp/all","rsvp/queue","rsvp/timeout","rsvp/hash","rsvp/rethrow","rsvp/defer","rsvp/config","rsvp/resolve","rsvp/reject","exports"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n){"use strict";function o(a,b){C[a]=b}var p=a.EventTarget,q=b.CancellationError,r=c.Promise,s=d.denodeify,t=e.all,u=e.any,v=f.Queue,w=f.ResolvedQueueError,x=g.delay,y=g.timeout,z=h.hash,A=i.rethrow,B=j.defer,C=k.config,D=l.resolve,E=m.reject;n.CancellationError=q,n.Promise=r,n.EventTarget=p,n.all=t,n.any=u,n.Queue=v,n.ResolvedQueueError=w,n.delay=x,n.timeout=y,n.hash=z,n.rethrow=A,n.defer=B,n.denodeify=s,n.configure=o,n.resolve=D,n.reject=E}),window.RSVP=b("rsvp")}(window);
\ No newline at end of file
{
"name": "prezedit",
"version": "0.0.0",
"description": "A renderjs gadget to edit presentations",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
/*globals window, document, $, html_beautify */
/*jslint unparam: true */
$(function () {
"use strict";
var presentation=null, slideForm;
function blindForm() {
$('#slide-form').toggle("blind");
}
function Slide (params) {
var that = this;
this.html = document.importNode(this.htmlTemplate, true);
if (params.section) {
this.update({
title: params.section.querySelector('h1').textContent,
type: params.section.className,
content: params.section.childNodes[2].textContent
});
}else{
this.update(params);
}
$(this.htmlEditButton()).click(function (e) {
slideForm.bindToEdit(that);
blindForm();
e.preventDefault();
});
$(this.htmlDeleteButton()).click(function (e) {
presentation.deleteSlide(that);
e.preventDefault();
});
}
Slide.prototype = {
dataTemplate: document.querySelector('template#slide-data').content.firstElementChild,
htmlTemplate: document.querySelector('template#slide-html').content.firstElementChild,
htmlEditButton: function () {
return this.html.querySelector("button.edit");
},
htmlDeleteButton: function () {
return this.html.querySelector("button.delete");
},
htmlContent: function () {
return this.html.querySelector(".content");
},
htmlTitle: function () {
return this.html.querySelector("h1");
},
data: function () {
var res = document.importNode(this.dataTemplate, true);
res.className = this.type;
res.querySelector('h1').textContent = this.title;
res.appendChild(document.createTextNode(this.content));
return res;
},
update: function (params) {
$.extend(this, params);
this.htmlTitle().textContent = this.title;
this.htmlContent().innerHTML = this.content;
}
};
function SlideForm () {
this.elt = document.querySelector("#slide-form");
this.bindToAdd();
}
SlideForm.prototype = {
reset: function() {
this.elt.querySelector('#title').value = "";
this.elt.querySelector('#type').value = "";
this.elt.querySelector('#content').value = "";
},
bindToEdit: function (slide) {
var that = this;
$(this.elt).off();
this.elt.querySelector('#title').value = slide.title;
this.elt.querySelector('#type').value = slide.type;
this.elt.querySelector('#content').value = slide.content;
$(this.elt).submit(function (e) {
slide.update({
title: that.elt.querySelector('#title').value,
type: that.elt.querySelector('#type').value,
content: that.elt.querySelector('#content').value
});
blindForm();
e.preventDefault();
slideForm.bindToAdd();
});
},
bindToAdd: function () {
var that = this;
$(this.elt).off();
this.reset();
$(this.elt).submit(function (e) {
presentation.addSlide(new Slide({
title: that.elt.querySelector('#title').value,
type: that.elt.querySelector('#type').value,
content: that.elt.querySelector('#content').value
}));
blindForm();
this.reset();
e.preventDefault();
});
}
};
function Presentation (DOMElement) {
this.html = DOMElement;
slideForm = new SlideForm();
this.slides = [];
$("#add-slide").click(blindForm);
$(this.html).sortable({
update: function (event, ui) {
presentation.updateOrder(ui.item);
}
});
}
Presentation.prototype = {
addSlide: function (slide) {
this.slides.push(slide);
this.html.appendChild(slide.html);
return slide;
},
deleteSlide: function (slide) {
var index = this.slides.indexOf(slide);
this.slides.splice(index,1);
slide.html.remove();
return index;
},
updateOrder: function (DOMElement) {
var newIndex = $(this.html.children).index(DOMElement),
oldIndex, i, tmp;
for (i=0; i<this.slides.length; i++) {
if (this.slides[i].html === DOMElement[0]) {
oldIndex = i;
break;
}
}
tmp = this.slides.splice(oldIndex,1)[0];
this.slides.splice(newIndex,0,tmp);
},
getContent: function () {
var i, container = document.createElement('div');
for (i=0; i<this.slides.length; i++) {
container.appendChild(this.slides[i].data());
}
return html_beautify(container.innerHTML);
},
setContent: function (content) {
var i, sections, container = document.createElement('div');
container.innerHTML = content;
sections = container.children;
for (i=0; i<sections.length; i++) {
this.addSlide(new Slide({section: sections[i]}));
}
}
};
$.fn.extend({
presentation: function () {
presentation = new Presentation(this[0]);
return presentation;
}
});
});
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