vumix/commit

add editable title field

authorMichiel Hildebrand
Thu Mar 22 15:28:48 2012 +0100
committerMichiel Hildebrand
Thu Mar 22 15:28:48 2012 +0100
commitac13796633d18df9339d54b611b8bbaa998b977b
tree15b2f61538276f2406ece24d6c903fa08914b305
parent5be29de9bff80e21d3f39eb74ff5777955d11307
Diff style: patch stat
diff --git a/applications/vumix.pl b/applications/vumix.pl
index 438730c..d970d83 100644
--- a/applications/vumix.pl
+++ b/applications/vumix.pl
@@ -72,9 +72,9 @@ http_vumix(Request) :-
 %	HTML page
 
 html_page(Target, Fields) :-
-	rdf_display_label(Target, Title),
+	rdf_global_id(_:Id, Target),
 	reply_html_page(
-	    [ title(['Annotate -- ', Title])
+	    [ title(['Annotate -- ', Id])
 	    ],
 	    [ \html_requires(yui3('cssgrids/grids-min.css')),
 	      \html_requires(css('annotation.css')),
@@ -86,8 +86,7 @@ html_page(Target, Fields) :-
 			    [ div([id(fields), class('yui3-u')],
 				  \html_annotation_fields(Fields)),
 			      div([id(media), class('yui3-u')],
-				  [ div([id(title),class(title)],
-					h3(Title)),
+				  [ div(id(title), []),
 				    div(id(video), [])
 				  ])
 			    ])
@@ -150,12 +149,17 @@ yui_script(Target, Fields) -->
 	yui3([json([modules(json(Modules))])],
 	     ['recordset-base'|Includes],
 	     [\js_video(Target),
+	      \js_title_edit(Target),
 	      \js_annotation_fields(Fields, Target)]).
 
 js_module('videoplayer', json([fullpath(Path),
 			       requires([node,event,widget])
 			      ])) :-
 	http_absolute_location(js('videoplayer/videoplayer.js'), Path, []).
+js_module('textedit', json([fullpath(Path),
+			    requires([node,event,io,plugin,'querystring-stringify-simple'])
+			      ])) :-
+	http_absolute_location(js('textedit.js'), Path, []).
 js_module('annotation', json([fullpath(Path),
 			      requires(['recordset-base',
 					autocomplete,
@@ -167,6 +171,25 @@ js_module('annotation', json([fullpath(Path),
 	http_absolute_location(js('annotation.js'), Path, []).
 
 
+js_title_edit(Target) -->
+	{ http_location_by_id(http_update_annotation, Update),
+	  rdf_equal(dcterms:title, Field),
+	  (   annotation_in_field(Target, Field, Annotation, _Body, Text)
+	  ->  true
+	  ;   Annotation = @null,
+	      Text = @null
+	  )
+	},
+	yui3_plug(one(id(title)),
+		  'Y.Plugin.TextEdit',
+		  {target:Target,
+		   field:Field,
+		   annotation:Annotation,
+		   text:Text,
+		   store:{update:Update
+			 }
+		  }).
+
 js_video(Target) -->
 	{ http_absolute_location(js('videoplayer/'), FilePath, []),
 	  video_source(Target, Src)
@@ -175,8 +198,8 @@ js_video(Target) -->
 		 'Y.VideoPlayer',
 		 {filepath:FilePath,
 		  src:Src,
-		  width:710,
-		  height:450,
+		  width:730,
+		  height:460,
 		  autoplay:symbol(false),
 		  controls:symbol(true)
 		 }),
@@ -222,7 +245,7 @@ annotation_in_field(Target, FieldURI, Annotation, Body, Label) :-
 	rdf(Annotation, oac:hasTarget, Target, Graph),
 	rdf(Annotation, an:annotationField, FieldURI, Graph),
 	rdf(Annotation, oac:hasBody, Body, Graph),
-	rdf(Annotation, dc:title, Lit, Graph),
+	rdf(Annotation, dcterms:title, Lit, Graph),
 	literal_text(Lit, Label).
 
 
diff --git a/applications/vumix.pl~ b/applications/vumix.pl~
deleted file mode 100644
index 4ae4c12..0000000
--- a/applications/vumix.pl~
+++ /dev/null
@@ -1,228 +0,0 @@
-:- module(vumix,
-	[]).
-
-
-% semweb
-:- use_module(library('semweb/rdf_db')).
-:- use_module(library('semweb/rdfs')).
-:- use_module(library('semweb/rdf_label')).
-:- use_module(library(yui3_beta)).
-
-% http libraries
-:- use_module(library('http/http_dispatch')).
-:- use_module(library('http/http_parameters')).
-:- use_module(library('http/html_write')).
-:- use_module(library('http/html_head')).
-:- use_module(library('http/http_path')).
-:- use_module(library('http/http_json')).
-:- use_module(components(label)).
-:- use_module(library(settings)).
-:- use_module(user(user_db)).
-:- use_module(library(instance_search)).
-:- use_module(library(graph_version)).
-
-
-/***************************************************
-* http handlers
-***************************************************/
-
-:- http_handler(cliopatria(vumix), http_vumix, []).
-
-
-/***************************************************
-* settings
-***************************************************/
-
-:- setting(login, boolean, true, 'Require login').
-:- setting(min_query_length, integer, 3,
-	   'Minimum number of characters that must be entered before a query event will be fired. A value of 0 allows empty queries; a negative value will effectively disable all query events and turn AutoComplete off. ').
-
-
-/***************************************************
-* http replies
-***************************************************/
-
-%%	http_vumix(+Request)
-%
-%	Generate page to annotate a vumix.
-
-http_vumix(Request) :-
-	http_parameters(Request,
-		[ target(Target,
-		     [uri,
-		      description('URI of the object to be annotated')
-		     ]),
-		  field(Fields,
-			[zero_or_more,
-			 description('URI of annotation field')
-			])
-		]),
-	(   setting(login, true)
-        ->  authorized(write(_,_))
-        ;   true
-        ),
-	html_page(Target, Fields).
-
-/***************************************************
-* annotation page
-***************************************************/
-
-%%	html_page(+Target, +Fields)
-%
-%	HTML page
-
-html_page(Target, Fields) :-
-	rdf_display_label(Target, Title),
-	reply_html_page(
-	    [ title(['Annotate -- ', Title])
-	    ],
-	    [ \html_requires(yui3('cssgrids/grids-min.css')),
-	      \html_requires(css('annotation.css')),
-	      \html_requires(css('vumix.css')),
-	      div(class('yui3-skin-sam yui-skin-sam'),
-		  [ div(id(hd), []),
-		    div(id(bd),
-			div([id(layout), class('yui3-g')],
-			    [ div([id(fields), class('yui3-u')],
-				  \html_annotation_fields(Fields)),
-			      div([id(media), class('yui3-u')],
-				  [ div(id(video), []),
-				    div([id(title),class(title)],
-					h3(Title))
-				  ])
-			    ])
-		       ),
-		    div(id(ft), [])
-		  ]),
-	      script(type('text/javascript'),
-		     \yui_script(Target, Fields))
-	    ]).
-
-% hack
-video_source(R, Video) :-
-	rdf_has(R, pprime:source, Video).
-
-
-%%	html_annotation_fields(+FieldURIs)
-%
-%	Write html for annotation fields.
-
-html_annotation_fields([]) --> !.
-html_annotation_fields([URI|T]) -->
-	html(div(class('annotate-field'),
-		 \html_annotation_field(URI))),
-	html_annotation_fields(T).
-
-html_annotation_field(URI) -->
-	{ rdf_global_id(_:Id, URI),
-	  rdf_label(URI, L),
-	  literal_text(L, Label)
-	},
-	html([ div(class('annotate-header'),
-		   [ h3(Label),
-		     \html_annotation_field_desc(URI)
-		   ]),
-	       input([id(Id), type(text)])
-	     ]).
-
-html_annotation_field_desc(URI) -->
-	{ rdf(URI, dc:comment, D),
-	  literal_text(D, Desc)
-	},
-	!,
-	html(div([class('annotate-description')], Desc)).
-html_annotation_field_desc(_URI) --> !.
-
-
-
-		 /*******************************
-		 *	     JavaScript		*
-		 *******************************/
-
-%%	yui_script(+Graph)
-%
-%	Emit YUI object.
-
-yui_script(Target, Fields) -->
-	{ findall(M-C, js_module(M,C), Modules),
-	  pairs_keys(Modules, Includes)
-	},
-	yui3([json([modules(json(Modules))])],
-	     ['recordset-base'|Includes],
-	     [\js_video(Target),
-	      \js_annotation_fields(Fields, Target)]).
-
-js_module('videoplayer', json([fullpath(Path),
-			       requires([node,event,widget])
-			      ])) :-
-	http_absolute_location(js('videoplayer/videoplayer.js'), Path, []).
-js_module('annotation', json([fullpath(Path),
-			      requires(['recordset-base',
-					autocomplete,
-					'autocomplete-highlighters',
-					'io','json-parse',
-					'querystring-stringify-simple'
-				       ])
-			     ])) :-
-	http_absolute_location(js('annotation.js'), Path, []).
-
-
-js_video(Target) -->
-	{ http_absolute_location(js('videoplayer/'), FilePath, []),
-	  video_source(Target, Src)
-	},
-	yui3_new(videoPlayer,
-		 'Y.VideoPlayer',
-		 {filepath:FilePath,
-		  src:Src,
-		  width:710,
-		  height:450,
-		  autoplay:symbol(false),
-		  controls:symbol(true)
-		 }),
-	yui3_render(videoPlayer, one(id(video))).
-
-%%	js_annotation_fields(+FieldURIs, +AnnotationTarget)
-%
-%	Write JavaScript to init annotation fields
-
-js_annotation_fields([], _) --> !.
-js_annotation_fields([URI|T], Target) -->
-	js_annotation_field(URI, Target),
-	js_annotation_fields(T, Target).
-
-js_annotation_field(FieldURI, Target) -->
-	{ http_location_by_id(http_add_annotation, Add),
-	  http_location_by_id(http_remove_annotation, Remove),
-	  rdf_global_id(_:Id, FieldURI),
-	  setting(min_query_length, MinQueryLength),
-	  rdf(FieldURI, an:source, literal(Source)),
-	  findall({annotation:A, uri:R, label:L},
-		  annotation_in_field(Target, FieldURI, A, R, L),
-		  Tags)
-	},
-	yui3_plug(one(id(Id)),
-		  'Y.Plugin.Annotation',
-		  {target:Target,
-		   field:FieldURI,
-		   source:Source,
-		   store:{add:Add,
-			  remove:Remove
-			 },
-		   tags:Tags,
-		   minQueryLength:MinQueryLength,
-		   resultListLocator: results,
-		   resultTextLocator: label,
-		   resultHighlighter: phraseMatch}).
-
-
-annotation_in_field(Target, FieldURI, Annotation, Body, Label) :-
-	gv_resource_head(Target, Commit),
-	gv_resource_graph(Commit, Graph),
-	rdf(Annotation, oac:hasTarget, Target, Graph),
-	rdf(Annotation, an:annotationField, FieldURI, Graph),
-	rdf(Annotation, oac:hasBody, Body, Graph),
-	rdf(Annotation, dc:title, Lit, Graph),
-	literal_text(Lit, Label).
-
-
diff --git a/config-available/load_mbh_example.pl b/config-available/load_mbh_example.pl
index d5db651..f50c797 100644
--- a/config-available/load_mbh_example.pl
+++ b/config-available/load_mbh_example.pl
@@ -4,16 +4,16 @@
 :- use_module(library('semweb/rdf_db')).
 :- use_module(library(http/http_dispatch)).
 
-:- rdf_load(rdf('mbh_example.ttl')). % load example video and config file
-:- rdf_attach_library(vocs).
-:- rdf_load_library(gtaa).
-
-:- http_link_to_id(http_vumix, [target('http://semanticweb.cs.vu.nl/prestoprime/video18702'),
-				field('http://semanticweb.cs.vu.nl/prestoprime/personAnnotation'),
-				field('http://semanticweb.cs.vu.nl/prestoprime/placeAnnotation'),
-				field('http://semanticweb.cs.vu.nl/prestoprime/subjectAnnotation')
-			       ],
-		   Location),
+load_mbh_example :-
+	rdf_load(rdf('mbh_example.ttl')), % load example video and config file
+        rdf_attach_library(vocs),
+	rdf_load_library(gtaa),
+	http_link_to_id(http_vumix, [target('http://semanticweb.cs.vu.nl/prestoprime/video18702'),
+				     field('http://semanticweb.cs.vu.nl/prestoprime/personAnnotation'),
+				     field('http://semanticweb.cs.vu.nl/prestoprime/placeAnnotation'),
+				     field('http://semanticweb.cs.vu.nl/prestoprime/subjectAnnotation')
+				    ],
+			Location),
 	http_handler(cliopatria(p0),
 		     http_redirect(moved, Location),
 		     []).
diff --git a/config-available/vumix.pl b/config-available/vumix.pl
index edd1bd1..2e45d22 100644
--- a/config-available/vumix.pl
+++ b/config-available/vumix.pl
@@ -3,3 +3,9 @@
 /** <module> Video annotation prototype
 */
 
+:- use_module(library('semweb/rdf_db')).
+
+% hack namespace
+ :- rdf_register_ns(pprime, 'http://semanticweb.cs.vu.nl/prestoprime/').
+
+:- use_module(applications(vumix)).
diff --git a/web/css/vumix.css b/web/css/vumix.css
index 7919957..fe92cd5 100644
--- a/web/css/vumix.css
+++ b/web/css/vumix.css
@@ -1,5 +1,35 @@
 #title {
 	background-color: #EEE;
-	padding: 5px 5px;
-	margin: 10px 0;
+	padding: 5px;
+	margin: 0 0 10px;
+}
+#title .text {
+	font-size: 125%;
+	font-weight: bold;
+	padding: 5px 0;
+}
+.textedit .inputField {
+	display: none;
+}
+.textedit .inputLabel {
+	font-weight: bold;
+}
+.textedit .text:hover {
+	background-color: #F5F46C;
+}
+.textedit textarea {
+	width: 100%;
+}
+.textedit .info {
+	display: none;
+}
+.textedit:hover .info {
+	display: block;
+}
+.textedit.edit .text,
+.textedit.edit:hover .info {
+	display: none;
+}
+.textedit.edit .inputField {
+	display: block;
 }
\ No newline at end of file
diff --git a/web/js/textedit.js b/web/js/textedit.js
new file mode 100644
index 0000000..843d30a
--- /dev/null
+++ b/web/js/textedit.js
@@ -0,0 +1,113 @@
+YUI.add('textedit', function(Y) {
+
+	var Node = Y.Node;
+	
+	function TextEdit(config) {
+		TextEdit.superclass.constructor.apply(this, arguments);
+	}
+	TextEdit.NAME = "TextEdit";
+	TextEdit.NS = "TextEdit";  
+	TextEdit.ATTRS = {
+		text: {
+			value: null
+		},
+		inputLabel: {
+			value: "Title"
+		},
+		infoText: {
+			value: "click to edit title"
+		},
+		target: {
+			value: null
+		},
+		field: {
+			value: null
+		},
+		annotation: {
+			value: null
+		},
+		store: {
+			value: null
+		}
+	};
+
+	Y.extend(TextEdit, Y.Plugin.Base, {
+
+		initializer: function(args) {
+			var parentNode = this.get("host"),
+				text = this.get("text");
+			
+			parentNode.addClass("textedit");
+			var textNode = parentNode.appendChild(Node.create('<div class="text"></div>')),
+				infoNode = parentNode.appendChild(Node.create('<div class="info">'+
+					this.get("infoText")+'</div>'))
+				inputNode = parentNode.appendChild(Node.create('<div class="inputField"></div>')),
+				inputLabel = inputNode.appendChild(Node.create('<div class="inputLabel">'
+					+this.get('inputLabel')+'</div>')),
+				inputField = inputNode.appendChild(Node.create('<textarea></textarea>')),
+				submitButton = inputNode.appendChild(Node.create('<button>save</button>'));
+			
+			this._setText({newVal:text});
+			this.on("textChange", this._setText, this);
+			textNode.on("click", this._enableEdit, this);
+			submitButton.on("click", this._submitText, this);
+		},
+		
+		_setText : function(e) {
+			var host = this.get("host"),
+				text = e.newVal;
+			if(text) {
+				host.one('.text').setContent(text);
+				host.removeClass("edit");
+			} else {
+				this._enableEdit();
+			}
+		},
+		
+		_enableEdit : function(e) {
+			var host = this.get("host"),
+				text = this.get("text"),
+				input = host.one('textarea');
+			input.set("value", text);
+			host.addClass("edit");
+			input.focus();
+		},
+		
+		_submitText : function(e) {
+			var oSelf = this,
+				oldText = this.get("text"),
+				newText = this.get("host").one('textarea').get("value"),
+				updateService = this.get("store").update;
+				
+			var data = 	{
+				target:this.get("target"),
+				field:this.get("field"),
+				body:newText
+			};
+			if(this.get("annotation")) {
+				data.annotation = this.get("annotation");
+			}
+			if(oldText!==newText) {
+				Y.io(updateService, {
+					data:data,
+					on:{success: function(e,o) { 
+						var r = Y.JSON.parse(o.responseText);
+						console.log(r.annotation);
+						oSelf.set("annotation", r.annotation);
+						oSelf.set("text", newText) }
+					}
+				});
+			} else {
+				this.get("host").removeClass("edit");
+			}
+		}
+		
+		
+	});
+
+	Y.Plugin.TextEdit = TextEdit;
+
+}, '0.0.1', { requires: [
+	'node','event','plugin','io-base','querystring-stringify-simple'
+	]
+});