Mercurial > hg > audiodb
view examples/browser/web/js/jOWL_UI.js @ 659:536cfa209e7f
Sampling enhancements
Allow specification of a key with -k for doing sampling between a single
datum and the rest of the database. (The implementation is slightly
icky, as mentioned in the previous commit message; hopefully this
situation will not remain for too long).
While we're at it, allow -r/--resultlength as a synonym for --nsamples
(if --nsamples is not given) in order better to reflect the analogy
between querying and sampling.
author | mas01cr |
---|---|
date | Tue, 05 Jan 2010 16:44:06 +0000 |
parents | 901803e1305f |
children |
line wrap: on
line source
/* * jOWL_UI, User Interface Elements for jOWL, semantic javascript library * Creator - David Decraene * Version 1.0 * Website: http://Ontologyonline.org * Licensed under the MIT license * Verified with JSLint http://www.jslint.com/ */ (function($){ jOWL.UI = { broadcaster : function(){ var listeners = []; this.addListener = function(obj){ function add(obj){if(obj.propertyChange) { listeners.push(obj); } } if(obj.constructor == Array){for(var i=0;i<obj.length;i++){ add(obj[i]); } } else { add(obj); } return this; }; this.broadcast = function(item){ for(var i=0;i<listeners.length;i++){ listeners[i].propertyChange.call(item, item); } }; if(!this.propertyChange){ this.propertyChange = function(item){}; } }, asBroadcaster : function(ui_elem){ ui_elem.broadcaster = jOWL.UI.broadcaster; ui_elem.broadcaster(); }, defaults : { contentClass: "jowl-content", focusClass: "ui-state-hover", wrapperClass : "ui-widget-content" } }; /** WIDGETS all widgets: addListener : add an object with a propertyChange function, will be triggered on select propertyChange: update the widget with a new jowl object Events: onSelect: (look into propertylens click), return false to suppress the event, this = jquery element, first argument = jOWL object CSS: wrapperClass: css class(es) for main element, the el itself contentClass: css class(es) for main content element, accessible by el.content focusClass: css class(es) for element in focus, */ $.fn.extend({ /* owl_navbar options: onSelect : this element refers to jquery node, first argument = jOWL object */ owl_navbar: function(options){ options = $.extend({ contentClass : jOWL.UI.defaults.contentClass, focusClass : jOWL.UI.defaults.focusClass, onSelect : function(item){}, onPropertyChange : function(item){} }, options); var self = this; this.addClass("jowl-navbar"); this.content = $("."+options.contentClass, this).empty(); if(!this.content.length) { this.content = $("<div/>").addClass(options.contentClass).appendTo(this); } this.parents = $('<div/>').appendTo(this.content); this.focus = $('<div/>').addClass(options.focusClass).appendTo(this.content); this.children = $('<div/>').appendTo(this.content); var listnode = $('<span/>').click(function(){ var node = $(this); var res = jOWL(node.attr('title')); if(options.onSelect.call(node, res) === false) { return; } if(res && res.isClass) { self.propertyChange.call(res, res); self.broadcast(res); } }); jOWL.UI.asBroadcaster(this); this.propertyChange = function(item){ if(options.onPropertyChange.call(this, item) === false) { return; } if(item.isClass){ item.bind(self.focus); if(jOWL.options.reason) { item.hierarchy();} self.parents.empty().append(item.parents().bind(listnode)); self.children.empty().append(item.children().bind(listnode)); } }; return this; }, /** autocomplete field. */ owl_autocomplete : function(options){ options = $.extend({ time:500, //responsetime to check for new keystrokes, default 500 chars:3, //number of characters needed before autocomplete starts searching focus:false, //put cursor on the input field when loading limit:10, //limit size of result list to given amount contentClass : "ui-widget-content", focusClass : jOWL.UI.defaults.focusClass, hintClass : "ui-autocomplete-hint", hint: false, //Message (if any) to show when unfocused. onSelect : function(item){}, //function that can be overridden formatListItem : function(listitem, type, identifier, termarray){ //formatting of results, can be overridden if(type){ listitem.append($('<div class="type"/>').text(type)); } listitem.append($('<div class="name"/>').text(identifier)); if(termarray.length) { listitem.append($('<div class="terms"/>').text(termarray.join(', ')) .prepend($('<span/>').addClass('termlabel').text("Terms: "))); } }}, options); jOWL.UI.asBroadcaster(this); this.showHint = function(){ this.hinted = true; if(options.hint){ this.addClass(options.hintClass).val(options.hint); } else {this.val(''); } }; this.showHint(); var self = this; var old = ''; var open = false; self.val(''); var results = $('<ul/>').addClass(options.contentClass).addClass("jowl_autocomplete_results"); var div = $("<div/>").addClass(options.wrapperClass).append(results); this.after(div); results.cache = {}; results.isEmpty = function(){ for(x in results.cache) { return false; } return true; }; results.close = function(){this.hide();}; results.open = function(q, cache){ this.show(); if(q){ if(!cache || results.isEmpty()) { results.cache = jOWL.query(q, options); } else { var newcache = {}; for(x in results.cache){ var entry = results.cache[x]; var found = false; var newentries = []; if(x.searchMatch(q) > -1) { found = true; } for(var i = 0;i<entry.length;i++){ if(entry[i].term.searchMatch(q) > -1) { found = true; newentries.push(entry[i]); } } if(found) { newcache[x] = newentries; } } results.cache = newcache; } this.populate(results.cache); } }; results.populate = function(data){ var res = this; this.empty(); var count =0; var clickFunction = function(){ var node = $(this), res = jOWL(node.data("jowltype")); if(options.onSelect.call(node, res) === false) { return; } self.broadcast(res); }; var onHover = function(){ $(this).addClass(options.focusClass); }; var offHover = function(){$(this).removeClass(options.focusClass);}; for(x in data){ if(count < options.limit){ var item = data[x]; var v = jOWL.isExternal(x); v = v ? v[1] : x; var list = $('<li/>').data("jowltype", x) .click(clickFunction).hover(onHover, offHover) .appendTo(res); var terms = []; for(var l = 0;l<item.length;l++){ var found = false; var newterm = item[l].term; for(var y=0; y < terms.length;y++){ if(terms[y].toLowerCase() == newterm.toLowerCase()) { found = true; } } if(!found) { terms.push(newterm); } } options.formatListItem.call(list, list, item[0].type, v, terms); } count++; } }; setInterval(function(){ var newvalue = self.val(); var cache = true; if(old != newvalue){ var longervalue = newvalue.length > old.length && newvalue.indexOf(old) === 0; if(!old) { cache = false; } old = newvalue; if(newvalue.length < options.chars && open){ results.close();open = false;} else if(newvalue.length >=options.chars && newvalue.length > 0){ if(cache) { cache = longervalue && newvalue.length > options.chars; } results.open(newvalue, cache); open = true; } } }, options.time); self.bind('keyup', function(){ if(!this.value.length){ results.close(); open = false; } }); self.bind('blur', function(){ if(open){setTimeout(function(){results.close();}, 200);open = false;} if(!self.val().length){self.showHint();} }); //timeout for registering clicks on results. self.bind('focus', function(){ if(self.hinted){ self.hinted = false; $(this).removeClass(options.hintClass).val(''); } if(self.val().length && !open){results.open('', open);open = true;}}); //reopen, but do not get results return this; }, /** Tree View */ owl_treeview : function(options){ options = $.extend({ contentClass : jOWL.UI.defaults.contentClass, focusClass: "focus", nameClass: "name", treeClass: "jowl-treeview", rootClass: "root", onSelect : function(item){}, //function that can be overwritten to specfy behavior when something is selected rootThing : false, //if true then topnode is (owl) 'Thing' isStatic : false, // if static then selections will refresh the entire tree addChildren : false //add a given objects children to the treeview as well }, options); /** construct the hierarchy & make a tree of it */ function TreeModel(owlobject){ function clear(el){ //reset invParents, for later use. if(el.parents) { el.parents().each(function(){ this.invParents = null; clear(this); }); } } function leaf(node){ node.jnode.addClass(options.focusClass); if(options.addChildren){ var entry = jOWL(node.$name.attr('title')); if(entry && entry.children){ entry.children().each(function(){ node.add(this); }); } } } function traverse(itemarray, appendto){ if(!itemarray) { return; } itemarray.each(function(){ var node = appendto.add(this); if(this.invParents){ traverse(this.invParents, node); } else { leaf(node); } }); } var h = owlobject.hierarchy(true); if(options.rootThing) { traverse(h, tree.root(jOWL("Thing"))); } else { var root = tree.root(h); for(var i=0;i<root.length;i++){ traverse(root[i].invParents, root[i]); if(!root[i].invParents) { leaf(root[i]); } } } clear(owlobject); } /** var tree = $(selector).owl_treeview(); var root = tree.root("node"); root.add("node2").add("child"); */ function Tree(node, treemodel, options){ var rack = $('<ul/>').addClass(options.treeClass).appendTo(node); var tree = this; /**item can be text, a jOWL object, or a jOWL array */ this.root = function(item){ var rt = null; //root rack.empty(); if(item && item.each) { rt = []; item.each(function(it){ var x = new fn.node(it, true); x.wrapper.addClass("tv"); x.jnode.appendTo(rack); x.invParents = it.invParents; it.invParents = null; //reset for later use rt.push(x); }); return rt; } rt = new fn.node(item, true); rt.wrapper.addClass("tv"); rt.jnode.appendTo(rack); return rt; }; var fn = {}; fn.node = function(text, isRoot){ //creates a new node this.jnode = isRoot ? $('<li/>').addClass(options.rootClass) : $('<li class="tvi"/>'); this.$name = null; if(text){ this.$name = $('<span/>').addClass(options.nameClass); if(typeof text == "string") { this.$name.html(text); } else if(text.bind) { text.bind(this.$name); } var n = this.$name; this.$name.appendTo(this.jnode).click(function(){ var entry = jOWL(n.attr('title')); if(entry && options.onSelect.call(n, entry) === false) { return; } tree.broadcast(entry); if(options.isStatic) { tree.propertyChange(entry); } return false;}); } this.wrapper = $('<ul/>').appendTo(this.jnode); var self = this; self.jnode.click(function(){toggle(); return false;}); this.add = function(text){ var nn = new fn.node(text); if(!self.wrapper.children().length) { toNode(); } else { var lastchild = self.wrapper.children(':last'); lastchild.swapClass("tvilc", "tvic"); lastchild.swapClass("tvile", "tvie"); lastchild.swapClass("tvil", "tvi"); }//children - change end of list self.wrapper.append(nn.jnode.swapClass('tvi', 'tvil')); return nn; }; function toggle(){ var t = self.jnode.hasClass("tvic") || self.jnode.hasClass("tvie") || self.jnode.hasClass("tvilc") || self.jnode.hasClass("tvile"); if(!t) { return; } self.jnode.swapClass('tvic', 'tvie'); self.jnode.swapClass('tvilc', 'tvile'); self.wrapper.slideToggle(); } function toNode(){ self.jnode.swapClass('tvil', 'tvilc'); self.jnode.swapClass('tvi', 'tvic'); } }; return this; }// end Tree this.addClass("jowl-tree"); this.content = $("."+options.contentClass, this).empty(); if(!this.content.length){ this.content = $('<div/>').addClass(options.contentClass).appendTo(this); } var tree = new Tree(this.content, null, options); jOWL.UI.asBroadcaster(tree); tree.propertyChange = function(item){ if(item.isClass) { var m = new TreeModel(item); } }; return tree; }, /** Uses templating options: onChange: owl:Class, owl:Thing, etc..., tell the widget what to do with the different kinds of Ontology Objects. "data-jowl" : {split: ", ", "somevariable" : function_triggered_for_each_result } example: "rdfs:label" : {split: ", ", "rdfs:label" : function(){ //'this' keyword refers to HTML element}} ) example: "sparql-dl:PropertyValue(owl:Class, ?p, ?x)" : {"?p": function(){ //'this' keyword refers to HTML element }} //prefil: for sparql-dl queries //onComplete: function to trigger when the specific propertybox query is completed, this refers to the HTML element for propertybox //sort: sort results on specified parameter, for sparql-dl results. onUpdate: called when the widget updates itself */ owl_propertyLens : function(options){ var self = this; self.options = $.extend({ backlinkClass : "backlink", split: {}, disable : {}, click : {}}, options); self.resourcetype = this.attr('data-jowl') || "owl:Class"; var propertyboxes = []; $('.propertybox', this).each(function(){ var node = new jOWL.UI.PropertyBox($(this), self); propertyboxes.push(node); node.el.hide(); }); var backlink = $('.backlink', this).hide(); if(!backlink.length) { backlink = $('<div class="jowl_link"/>').addClass(self.options.backlinkClass).text("Back").hide().appendTo(this); } jOWL.UI.asBroadcaster(this); /** fn: optional function to execute*/ this.link = function(source, target, htmlel, fn){ htmlel.addClass("jowl_link").click(function(){ if(fn) { fn(); } self.broadcast(target); self.propertyChange(target); backlink.source = source.name; backlink.show().unbind('click').click(function(){ self.broadcast(source); self.propertyChange(source); backlink.hide(); }); }); }; var action = { "rdfs:label": function(item){ return [{"rdfs:label": item.label() }]; }, "rdf:ID" : function(item){ return [{"rdf:ID": [item.name, item] }]; }, "rdfs:comment" : function(item){ return $.map(item.description(), function(n){return {"rdfs:comment":n }; }); }, "rdf:type" : function(item){ if(item.owlClass) { return [{"rdf:type": item.owlClass() }]; } return [{"rdf:type": item.type }]; }, "term" : function(item){ return $.map(item.terms(), function(n, i){ return { "term" : n[0] }; }); }, "rdfs:range": function(item){if(item.range) { return [{"rdfs:range": item.range }]; } }, "rdfs:domain": function(item){if(item.domain) { return [{"rdfs:domain": item.domain }]; } }, "permalink": function(item){ var href = jOWL.permalink(item); return [{"permalink": "<a href='"+href+"'>Permalink</a>" }]; }, "owl:disjointWith": function(item){ if(!(item.isClass)) { return; } return $.map( jOWL.Xpath('*', item.jnode) .filter(function(){return this.nodeName == "owl:disjointWith"; }), function(n, i){ return {"owl:disjointWith": jOWL($(n).RDF_Resource())}; }); }, "default" : function(item){ var type = this.attr("data-jowl"); return $.map( jOWL.Xpath('*', item.jnode).filter(function(){return this.nodeName == type; }), function(n, i){ var x = {}; x[type] = $(n).text(); return x; } ); } }; this.propertyChange = function(item){ if(!item) { return; } self.property = item; if(backlink.source != item.name) { backlink.hide(); } else { backlink.source = false; } if(item.type != self.resourcetype){ if(item.isDatatypeProperty && self.resourcetype == "rdf:Property") {} else if(item.isObjectProperty && self.resourcetype == "rdf:Property"){} else { return; } } for(var i = 0;i<propertyboxes.length;i++){ var pbox = propertyboxes[i]; pbox.clear(); if(!pbox.actiontype){return; } var actiontype = pbox.actiontype; if(self.options.disable[actiontype]) { return; } if(!self.options[actiontype]) { self.options[actiontype] = {}; } if(actiontype.indexOf("sparql-dl:") === 0){ var query = actiontype.split("sparql-dl:", 2)[1]; var fill = {}; fill[self.resourcetype] = item; if(self.options[actiontype].prefill) { $.extend(fill, self.options[actiontype].prefill); } var qr = new jOWL.SPARQL_DL(query, fill).execute({onComplete : function(r){ if(self.options[actiontype].sort) { r.sort(self.options[actiontype].sort); } pbox.setResults(r.results, item); }}); } else { var choice = (action[actiontype]) ? actiontype : "default"; var results = action[choice].call(pbox.valuebox, item); pbox.setResults(results, item); } } if(self.options.onUpdate) { self.options.onUpdate.call(this, item); } }; //end property change if(self.options.tooltip){ var lens = this.remove(); this.display = function(element, htmlel){ htmlel.tooltip({ title: element.label(), html: function(){ lens.propertyChange(element); backlink.hide(); return lens.get(0); } }); }; } return this; }, /** Use propertyChange to set the class Use addField to add property refinements Use serialize to serialize input */ owl_datafield: function(options){ options = $.extend({ selectorClass : "jowl-datafield-selector", messageClass : "jowl-datafield-message", labelClass : "jowl-datafield-property-label" }, options); var self = this; var pArray = {}; //associative array for properties. this.messages = {}; this.messages[jOWL.NS.xsd()+"positiveInteger"] = "Allowed values: positive numbers or comparisons like '>5 && <15' "; this.addClass("owl_UI"); jOWL.UI.asBroadcaster(this); this.property = null; this.propertyChange = function(item){ if(item.isClass){ this.property = item; for(x in pArray){//reset all properties if(pArray[x].remove){ pArray[x].remove(); delete pArray[x]; } } } }; /** Sets up a new field */ this.addField = function(property){ if(pArray[property.URI]){ //allow for multiple fields? return; } var $content = $("<div/>"); pArray[property.URI] = $content; var $title = property.bind($("<div/>")).addClass(options.labelClass).appendTo($content).click(function(){ $content.remove(); delete pArray[property.URI]; }); if(property.isObjectProperty){ var sp = new jOWL.SPARQL_DL("Type(?t, ?c),PropertyValue(concept, property, ?c)", {concept : self.property, property : property }).execute({ onComplete : function(obj){ if(!obj.results.length){ return; } //modify to deal with non value results obj.sort("?t"); $select = $("<select class='"+options.selectorClass+"'/>").appendTo($content); for(var i=0;i<obj.results.length;i++){ obj.results[i]['?t'].bind($("<option/>")).appendTo($select); } $content.appendTo(self); }}); } else if(property.isDatatypeProperty){ var msg =""; if(self.messages[property.range]){ msg = self.messages[property.range]; } var $input = $('<div/>').addClass(options.selectorClass).attr("title", property.range).append($('<input type="text" style="font-size:11px;width:100px;"/>')); var $message = $('<div/>').addClass(options.messageClass).text(msg).appendTo($input); $content.append($input).appendTo(self); $('input', $content).focus(function(){ $message.animate({opacity: 1.0}, 1500).fadeOut(); }); } }; this.serialize = function(){ var q = { "Type": self.property, "PropertyValue" : [] }; $('.'+options.selectorClass, self).each(function(){ var $this = $(this); var $prop = $this.siblings('.'+options.labelClass); var prop = $prop.attr('title'); if( $this.is("select")){ var s = $this.get(0); var thing = $(s[s.selectedIndex]).attr('title'); q.PropertyValue.push([prop, thing]); } else { var $input = $this.find("input"); var datatype = $this.attr('title'); var entry = $input.get(0).value; if(entry) { q.PropertyValue.push([prop, '"'+entry+'"']); } } }); return q; }; return this; } }); /** Used by owl_PropertyLens */ jOWL.UI.PropertyBox = function($el, resourcebox){ var v = $('[data-jowl]', $el); if(v.length){ this.descendant = true;} this.el = $el; this.resourcebox = resourcebox; this.valuebox = v.length ? v : $el; this.actiontype = this.valuebox.attr('data-jowl'); }; jOWL.UI.PropertyBox.prototype = { setResults : function(results, item){ var nodes = jOWL.UI.Template(results, this.valuebox, this.resourcebox.options[this.actiontype].split); this.complete(nodes, item); if(nodes && nodes.length && this.descendant) { this.el.show(); this.valuebox.hide(); } if(this.resourcebox.options[this.actiontype].onComplete) { this.resourcebox.options[this.actiontype].onComplete.call(this.el.get(0)); } }, complete : function(nodes, item){ var res = this.resourcebox; if(!nodes || !nodes.length) { return; } var v = $.data(nodes, "parameters"); for(x in v){ if(v[x].length && typeof res.options[this.actiontype][x] == "function") { v[x].each(res.options[this.actiontype][x]); }} for(x in res.options.onChange){ var data = $('[typeof='+x+']', nodes).add(nodes.filter('[typeof='+x+']')); if(x.charAt(0) == "." || x.charAt(0) == "#"){ data = data.add($(x, nodes));} data.each(function(){ var node = $(this); $.data(node, 'data-jowl', x); var id = node.attr('title'); if(id != "anonymousOntologyObject") { res.options.onChange[$.data(node, 'data-jowl')].call(node, item, jOWL(id), res); } }); } }, clear : function(){ var prev = this.valuebox.prev('.jowl-template-result'); if(!prev.length){ prev = this.valuebox.prev('.jowl-template-splitter');} if(prev.length) { prev.remove(); this.clear(this.valuebox); } } }; /**arr: associative array of variablrd, jqel: node for which variables need to be substituted, */ jOWL.UI.Template = function(arr, jqel, splitter){ var options = { resultClass : "jowl-template-result", splitterClass : "jowl-template-splitter" }; if(!arr) { return; } function bindObject(value, jnode){ var bound = false; if(!value) { return false; } if(typeof value == 'string') { jnode.html(value); bound = true;} else if(value.constructor == Array){ if(value.length == 2) { value[1].bind(jnode).text(value[0]); bound = true; } } else if(value.bind){ value.bind(jnode); bound = true; } return bound; } var count = 0, a = [], b = {}; var remnantFn = function(){ var txt = $(this).text(); if(txt.indexOf('${') === 0 && txt.lastIndexOf('}') == txt.length-1 ) { $(this).hide(); } }; for(var i=0;i<arr.length;i++){ var x = jqel.clone(true).wrapInner("<"+jqel.get(0).nodeName+" class='"+options.resultClass+"'/>").children(); /** copy style settings */ x.addClass(jqel.attr('class')).removeClass('propertybox'); /** accepted obj types= string, array["string", "jowlobject"], jowlobject*/ for(obj in arr[i]){ if(!b[obj]) { b[obj] = []; } var occurrences = $(':contains(${'+obj+'})', x); if(!occurrences.length){ if(x.text() == "${"+obj+"}") { if(bindObject(arr[i][obj], x)) { count++; b[obj].push(x.get(0)); }} } else { occurrences.each(function(){ if(this.innerHTML == "${"+obj+"}") { var node = $(this); if(bindObject(arr[i][obj], node)) { count++; b[obj].push(this); } } }); } } var remnants = $(':contains(${)', x); //hide parameters that weren't substituted remnants.each(remnantFn); if(count){ x.insertBefore(jqel); a.push(x.get(0)); if(count > 1 && splitter) { $splitter = (splitter.indexOf('<') === 0) ? $(splitter) : $("<span/>").text(splitter); $splitter.addClass(options.splitterClass).insertBefore(x); } } } for(x in b){ if(b[x].length) { b[x] = $(b[x]); } } var nodes = $(a); $.data(nodes, "parameters", b); return nodes; }; /** Supporting functionality */ $.fn.swapClass = function(c1,c2) { return this.each(function() { if ($(this).hasClass(c1)) { $(this).removeClass(c1); $(this).addClass(c2);} else if ($(this).hasClass(c2)) {$(this).removeClass(c2);$(this).addClass(c1);} }); }; })(jQuery);