internalUrl = /^([A-z0-9-_]+)(:[A-z0-9-_]+)?$/; internalUri = /^([a-zA-Z0-9-_]+)\(([a-zA-Z0-9-_]+)\):\/\/(.*)|([a-zA-Z0-9-_]+):\/\/(.*)$/; isGeneratedId = /^\d+\(javascript\)$/; arrayName = /^([A-z0-9-_]+)\[\]$/; startsDoubleDot = /^:/; // cached_urls = {}; $.ajaxPrefilter(function( options, originalOptions, jqXHR ){ if( options.url != 'undefined' && internalUrl.test( options.url ) ){ // if( !cached_urls[options.url] ) // return; // alert( options.url + " dentro" ); jqXHR.abort(); var callback = ( options.success || options.complete || $.noop ); switch( options.type.toUpperCase() ) { case 'GET': return callback( DataLayer.get( options.url, /*false,*/ options.data ) ); case 'POST': return callback( DataLayer.put( options.url, options.data ) ); } //return( false ); // options.url = params[1]; // options.data = ( options.data || "" ) + "&" + params[2]; } }); // $("a").live("click", function( event ){ // // event.preventDefault(); // // $.ajax({ // // // // }); // // }); $("form").live( "submit", function( event ){ var action = $(this).attr("action"), res = false; if( res = internalUrl.exec( action ) ) { event.preventDefault(); var data = DataLayer.form( this ); DataLayer.put( res[1], data ); return( false ); } return( true ); }); $.storage = new $.store(); DataLayer = { links: {}, concepts: {}, listeners: {}, encoders: {}, decoders: {}, templates: {}, criterias: {}, tasks: [], render: function( templateName, data, filter, formatter, force ){ if( $.isFunction( filter ) ) { force = formatter; formatter = filter; filter = false; } if( typeof data === "string" ) { data = this.get( data, filter, force ) || {}; } var formatting = function( template ){ if( template === false ) return( false ); if( template ) DataLayer.templates[ templateName ] = new EJS({ text: template, cache: false }); var html = DataLayer.templates[ templateName ].render( { data: data } ); if( !formatter ) return( html ); return formatter( html ); } if( this.templates[ templateName ] ) { return formatting(); } return this.send( DataLayer.templatePath + templateName, 'get', false, formatting, !!!formatter ); }, send: function( url, type, data, callback, sync ){ var result = false, fired = false; var envelope = { 'async': ( typeof sync !== "undefined" ? !sync : !!callback ), 'url': url, 'success': function( dt, textStatus, jqXHR ){ if( callback ) { fired = true; result = callback( dt, textStatus, jqXHR ); } else result = dt; }, 'complete': function( jqXHR, textStatus ){ if( !fired && callback ) result = callback( false, textStatus, jqXHR ); }, 'type': $.isArray( type ) ? type[0] : type, 'data': data }; if( $.isArray( type ) && type[1] ) envelope['dataType'] = type[1]; $.ajax( envelope ); return( result ); }, dispatch: function( dispatcher, data, callback, isPost ){ return this.send( this.dispatchPath + dispatcher + ".php", [ ( isPost ? 'post' : 'get' ), 'json' ], data, callback ); // $.ajax({ // 'async': !!callback, // 'url': this.dispatchPath + dispatcher + ".php", // 'type': ( isPost ? 'post' : 'get' ), // 'dataType': 'json', // 'data': data, // 'success': function( dt, textStatus, jqXHR ){ // // if( callback ) // { // fired = true; // callback( dt, textStatus, jqXHR ); // } // else // result = dt; // // }, // 'complete': function( jqXHR, textStatus ){ // // if( !fired && callback ) // callback( false, textStatus, jqXHR ); // // }/*, // 'processData': false*/ // }); //return( result ); }, form: function( target ){ var params = {}, $this = $(target); if( !$this.is( "form" ) ) $this = $this.parents( "form" ); $.each( $this.serializeArray(), function( i, el ){ if( newName = arrayName.exec( el.name ) ) el.name = newName[1]; else if( !params[ el.name ] ) return( params[ el.name ] = el.value ); params[ el.name ] = params[ el.name ] || []; if( $.type(params[ el.name ]) !== "array" ) params[ el.name ] = [ params[ el.name ] ]; params[ el.name ].push( el.value ); }); // alert(dump(params)); return this.decode( $this.attr( "action" ), params ); }, blend: function( action, data ){ // if( notArray = (!$.isArray(data)) ) // data = [ data ]; var form = $('form[action="'+action+'"]'); form.get(0).reset(); var named = form.find( 'input[name]' ); for( var name in data ) { named.filter( '[name="'+name+'"]' ).val( data[name] ); } }, put: function( concept, filter, data, oneSide ){ ///////////////////////////// normalize //////////////////////////////// if( arguments.length == 2 ) { data = filter; filter = false; } if( typeof data === "undefined" || $.type(data) === "boolean" ) { oneSide = data; data = filter; filter = false; } if( !concept || !data ) return( false ); var decoder = "", id = false, bothSides = (typeof oneSide === "undefined"), notArray, res; if( $.type(filter) === "string" ) { id = filter; filter = false; } if( id ) data.id = id; if( notArray = ( $.type( data ) !== "array" ) ) data = [ data ]; if( res = internalUrl.exec( concept ) ) { //TODO: verificar se a decodificaçao deve ser feita em cada item do array data = this.decode( concept, data ); concept = res[1]; decoder = res[2]; } //////////////////////////////////////////////////////////////////////// if( bothSides || !oneSide ) { var result = false, links = this.links( concept ), current = this.check( concept ) || {}, ids = []; for( var i = 0; i < data.length; i++ ) { var key = ids[ ids.length ] = data[i].id || this.generateId( concept ), updateSet = {}; ////////////////////////////// linkage ///////////////////////////////// for( var link in links ) { if( data[i][link] ) { var isConcept = false; if( isConcept = this.isConcept( concept, link ) ) data[i][link] = [ data[i][link] ]; var _this = this; $.each( data[i][link], function( ii, el ){ var isRef = false if( isRef = ($.type(el) === "string") ) el = { id: el }; var nestedLinks = _this.links( links[link], true ); if( isConcept ) { el[ nestedLinks[concept] ] = el[ nestedLinks[concept] ] || []; el[ nestedLinks[concept] ].push( key ); } else el[ nestedLinks[concept] ] = key; if( isRef && ( !current[ key ] || !current[ key ][ link ] || (isConcept ? current[ key ][ link ] !== el.id : !$.inArray( el.id, current[ key ][ link ] )) ) ) { updateSet[ links[link] ] = updateSet[ links[link] ] || []; updateSet[ links[link] ].push( el ); } else if( !isRef ) data[i][link][ii] = _this.put( links[link], el, oneSide ); }); if( isConcept ) data[i][link] = data[i][link][0]; } } ////////////////////////////////////////////////////////////////////////// if( data[i].id ) data[i] = this.merge( concept, current[ data[i].id ], data[i] ); current[ key ] = data[i]; if( bothSides ) this.report( concept, key, data[i] ); } this.store( concept, current ); for( var setKey in updateSet ) { DataLayer.put( setKey, updateSet[ setKey ], false ); if( bothSides ) for( var i = 0; i < updateSet[ setKey ].length; i++ ) this.report( setKey, updateSet[ setKey ][i].id, updateSet[ setKey ][i] ); } } if( oneSide ) this.commit( concept, ids/*, true */); this.broadcast( concept, oneSide ? 'server' : bothSides ? 'serverclient' : 'client', true ); return( notArray ? ids[0] : ids ); }, remove: function( concept, id, oneSide ){ var bothSides = (typeof oneSide === "undefined"); if( bothSides || !oneSide ) this.del( concept, id ); if( bothSides ) this.report( concept, id, false ); if( oneSide ) this.commit( concept, id ); this.broadcast( concept, oneSide ? 'server' : bothSides ? 'serverclient' : 'client', false ); }, report: function( concept, id, data ) { var current = this.check( ':current', concept ) || {}; if( !current[ id ] ) current[ id ] = this.check( concept, id ) || {}; this.store( ':current', concept, current ); var diff = this.diff( current[ id ], data ); var diffs = this.check( ':diff', concept ) || {}; diffs[ id ] = diff; this.store( ':diff', concept, diffs ); }, // enqueue: function( queueName, concept, id, data ){ // // var queue = this.check( ':' + queueName, concept ) || {}; // // // }, // // dequeue: function( queueName, concept, id ){ // // // // }, rollback: function( concept, ids ){ var queue = this.prepareQ( 'current', concept, ids ); ids = []; for( var id in queue ) { this.put( concept, id, queue[id], false ); ids[ ids.length ] = id; } this.clearQ( concept, ( ids.length ? ids : false ) ); this.broadcast( concept, 'revert' ); }, prepareQ: function( queueName, concept, ids ){ if( notArray = ($.type(concept) !== "array") ) concept = [ concept ]; for( var i = 0; i < concept.length; i++ ) { var queue = this.check( ':' + queueName, concept[i] || false ); if( ids ) { if( $.type(ids) !== "array" ) ids = [ ids ]; var filtered = {}; for( var ii = 0; ii < ids.length; ii++ ) { filtered[ ids[ii] ] = queue[ ids[ii] ]; } queue = filtered; } } return( queue ); }, clearQ: function( concept, ids ){ var current = this.check( ':current', concept || false ); var diffs = this.check( ':diff', concept || false ); if( !ids ) current = diffs = {}; else { if( notArray = ($.type(ids) !== "array") ) ids = [ ids ]; for( var i = 0; i < ids.length; i++ ) { delete current[ ids[i] ]; delete diffs[ ids[i] ]; } } this.store( ':current', concept, current ); this.store( ':diff', concept, diffs ); }, commit: function( concept, ids, callback ){ var queue = this.prepareQ( 'diff', concept, ids ); this.sync( queue, concept || false, callback ); }, sync: function( queue, concept, callback ){ if( !queue || $.isEmptyObject( queue ) ) return; if( concept ) { var helper = {}; helper[concept] = queue; queue = helper; } var data = {}, URIs = {}; for( var concept in queue ) for( var id in queue[concept] ) { data[ this.URI( concept, id ) ] = queue[concept][id]; URIs[ this.URI( concept, id ) ] = { concept: concept, id: id }; } if( $.isEmptyObject( data ) ) return; this.dispatch( "Sync", data, function( data, status, jqXHR ){ // switch( status ) // { // case "error": // case "parsererror": // return DataLayer.rollback( concept, URI ); // case "success": // return DataLayer.commit(); // case "timeout": // case "notmodified": // } for( var URI in data ) { var parsed = DataLayer.parseURI( URI ), concept = parsed[1], id = parsed[3]; if( $.type(data[URI]) === "string" ) { //TODO:threat the exception thrown DataLayer.rollback( concept, id ); delete URIs[ URI ]; continue; } if( data[URI] === false ){ DataLayer.remove( concept, id, false ); continue; } if( id !== data[URI].id ) DataLayer.move( concept, id, data[URI].id ); DataLayer.put( concept, id, data[URI], false ); } for( var URI in URIs ) DataLayer.clearQ( URIs[URI].concept, URIs[URI].id ); if( callback ) callback(); }, true ); }, receive: function( concept, data ){ this.put( concept, data, false ); // if( typeof data.URI === "undefined" ) // { // URI = this.add( concept, data, oneSide ); // } // else if( data.URI === false ) // { // status = this.remove( concept, URI, oneSide ); // } // else // { // status = this.set( concept, URI, data, oneSide ); // } // // if( URI && data.URI && URI !== data.URI ) // this.move( concept, URI, data.URI ); }, merge: function( concept, current, data ){ return $.extend( current, data ); }, diff: function( base, toDiff ){ // var df = toDiff; // // for( var key in base ){ // // if( base[key] === df[key] ) // delete df[key]; // // // } if( toDiff === false ) return( false ); var toDiff = $.extend( {}, toDiff ); if( isGeneratedId.test( toDiff.id ) ) delete toDiff['id']; return( toDiff ); }, links: function( concept, reverse ){ if( !this.links[ concept ] ) { var result = this.dispatch( "links", { concept: concept } ) || false; if( !result ) return( false ); this.concepts[ concept ] = $.extend( this.concepts[ concept ] || {}, result['concepts'] || {} ); this.links[ concept ] = result['links'] || {}; } if( reverse ) { var reverted = {}, llinks = this.links[ concept ]; for( var key in llinks ) reverted[ llinks[key] ] = key; return( reverted ); } return( this.links[ concept ] ); }, isConcept: function( concept, attr ){ if( typeof this.concepts[concept] === "undefined" ) { this.links( concept ); } return !!this.concepts[ concept ][ attr ]; }, URI: function( concept, URI, context ){ if( res = internalUrl.exec( concept ) ) concept = res[1]; context = context ? "(" + context + ")" : ""; if( URI ) return( concept + context + "://" + URI ); else return( concept ); }, parseURI: function( URI ){ return internalUri.exec( URI ) || false; }, generateId: function( concept ){ var newId = this.counter + "(javascript)"; this.store( ":counter", (this.counter++) + "" ); return( newId ); }, get: function( concept, /*URI, */filter, oneSide ){ ///////////////////////////// normalize //////////////////////////////// if( arguments.length == 2 && $.type(filter) === "boolean" ) { oneSide = filter; filter = false; } var encoder = false, id = false, bothSides = (typeof oneSide === 'undefined'), res; if( $.type(filter) === "string" ) { id = filter; filter = false; } filter = filter || false; if( !concept ) return( false ); if( res = internalUrl.exec( concept ) ) { encoder = concept; concept = res[1]; if( filter ) filter = this.criteria( encoder, filter ); } if ( $.type(filter) === "array" ) { filter = { filter: filter, criteria: false }; } ////////////////////////////////////////////////////////////////////////// var result = false; if( bothSides || !oneSide ) result = this.check( concept, id || filter ); if( !result && (bothSides || oneSide) ) { result = this.request( concept, id || filter.filter, filter.criteria ); if( result && bothSides ) { var newResult = []; for( var i = 0; i < result.length; i++ ) newResult[i] = $.extend( {}, result[i] ); this.put( concept, id, newResult, false ); } } if( /*result &&*/ encoder ) result = this.encode( encoder, result, filter ); //TODO: retirar o filtro no método encode return( result ); }, filter: function( base, filter ){ var filtered = []; // var operator = filter.shift(); /*for( var key in base ) { switch( operator ) { case 'AND': for( var i = 0, current = true; i < filter.length && current; i++ ) current = this.compare( '&', current, this.compare( base[key], filter[i] ) ); break; case 'OR': for( var i = 0, current = false; i < filter.length && !current; i++ ) current = this.compare( '|', current, this.compare( base[key], filter[i] ) ); break; case 'IN': for( var i = 0, current = false; i < filter[1].length && !current; i++ ) current = this.compare( '|', current, this.compare( base[key], [ '=', filter[0], filter[1][i] ] ) ); break; default : current = this.compare( operator, base[key], ); } */ // if( !noGroup ) // for( var i = 0, current = original; i < filter.length && ( current === original ); i++ ) // current = this.compare( operator, current, this.compare( base[key], filter[i] ) ); // if( current ) // filtered[ filtered.length ] = key; // } return( filtered ); }, compare: function( operator, base, test ){ switch( operator ) { case '*': return RegExp( "*" + base + "*" ).test( test ); case '^': return RegExp( "^" + base + "" ).test( test ); case '$': return RegExp( "" + base + "$" ).test( test ); case '&': return ( base && test ); case '|': return ( base || test ); case '=': return ( base == test ); case '<=': return ( base <= test ); case '>=': return ( base >= test ); case '>': return ( base < test ); case '<': return ( base > test ); } }, check: function( namespace, keys ){ if( !namespace ) return( false ); var result = $.storage.get( namespace ); if( !keys || !result ) return( result || false ); if( notArray = $.type(keys) === "string" ) keys = [ keys ]; else if( $.type(keys) !== "array" ) keys = this.filter( result, keys.filter ); var res = []; for( var i = 0; i < keys.length; i++ ) res[ res.length ] = result[keys[i]]; return( notArray ? res[0] || false : res.length ? res : false ); }, store: function( namespace, key, data ){ if( !data ) return $.storage.set( namespace, key ); var res = this.check( namespace ) || {}; res[key] = data; return $.storage.set( namespace, res ); }, del: function( namespace, key ){ if( !key ) return $.storage.del( namespace ); var res = this.check( namespace ) || {}; delete res[key]; return $.storage.set( namespace, res ); }, move: function( concept, oldId, newId ){ this.store( concept, newId, this.check( concept, oldId ) ); this.del( concept, oldId ); }, request: function( concept, filter, criteria ){ var id = false, criteria = criteria || {}; if( $.type(filter) === "string" ) { id = filter; filter = false; } return this.dispatch( "request", { concept: concept || '', id: id || '', filter: filter || '', criteria: criteria || '', service: criteria.service || '', properties: criteria.properties || '' } ); }, // sync: function( data, callback ){ // // if( !data || $.isEmptyObject( data ) ) // return; // // this.send( "Sync", data, function( data, status, jqXHR ){ // // // switch( status ) // // { // // case "error": // // case "parsererror": // // return DataLayer.rollback( concept, URI ); // // case "success": // // return DataLayer.commit(); // // case "timeout": // // case "notmodified": // // } // // if( callback ) // { // var result = callback( data, status, jqXHR ); // // if( result === false ) // return; // else if( typeof result != "undefined" ) // data = result; // } // // for( var URI in data ) // { // var parsed = DataLayer.parseURI( URI ), // // concept = parsed[1], /*URI = parsed[3],*/ // // links = DataLayer.links( concept ); // // for( var linkName in links ) // { // var subURI = data[URI][linkName]; // // if( subURI && data[subURI] ) // { // data[URI][linkName] = DataLayer.put( linkName, subURI, data[subURI], false ); // // delete( data[subURI] ); // } // } // // DataLayer.put( concept, URI, data[URI], false ); // } // }, true ); // // }, // report: function( concept, URI, data, sync ) // { // var current = this.dequeue( 'current', concept, URI ); // // if( !current ) // this.enqueue( 'current', concept, URI, ( current = this.check( concept, URI ) || {} ) ); // // var diff = this.diff( current, data ); // // if( !diff ) // this.dequeue( 'current', concept, URI, true ); // else // this.enqueue( 'diff', concept, URI, diff ); // // if( sync ) // this.commit( concept, URI, function(){ // // DataLayer.set( concept, URI, data, false ); // // }); // }, // enqueue: function( type, concept, URI, obj ){ // // //var newURI = this.URI( concept, URI ); // // if( !this.queue[type] ) // this.queue[type] = {}; // // if( !this.queue['all'] ) // this.queue['all'] = {}; // // if( !this.queue[type][concept] ) // this.queue[type][concept] = {}; // // if( !this.queue['all'][type] ) // this.queue['all'][type] = {}; // // if( !this.queue['all'][type][/*new*/URI] ) // this.queue[type][concept][URI] = this.queue['all'][type][/*new*/URI] = obj; // // this.store( ':queue', this.queue ); // }, // // dequeue: function( type, concept, URI, remove ){ // // ///////////////////////////// normalize //////////////////////////////// // if( arguments.length < 4 && $.type(URI) === 'boolean' ) // { // remove = URI; // URI = false; // } // if( arguments.length < 3 && $.type(concept) === 'boolean' ) // { // remove = concept; // concept = false; // } // ////////////////////////////////////////////////////////////////////////// // // if( !this.queue[type] || !this.queue['all'] ) // return( false ); // // if( !concept ) // { // var obj = this.queue['all'][type]; // // if( remove ) // { // delete this.queue['all'][type]; // delete this.queue[type]; // } // // this.store( ':queue', this.queue ); // return( obj ); // } // // if( !this.queue[type][concept] ) // return( false ); // // if( !URI ) // { // var obj = this.queue[type][concept]; // // if( remove ) // { // var URIs = this.queue[type][concept]; // // for( var subURI in URIs ) // delete this.queue['all'][type][subURI]; // // delete this.queue[type][concept]; // } // // this.store( ':queue', this.queue ); // return( obj ); // } // // // var newURI = URI ? this.URI( concept, URI ) : concept; // // var obj = this.queue['all'][type][/*new*/URI]; // // if( remove ) // { // delete this.queue['all'][type][/*new*/URI]; // delete this.queue[type][concept][URI]; // } // // this.store( ':queue', this.queue ); // return( obj ); // }, //TODO: definir a 'usage' desta função e refatora-la // set: function( concept, filter, data, oneSide ){ // // ///////////////////////////// normalize //////////////////////////////// // if( arguments.length == 2 ) // { // data = filter; // filter = false; // } // if( $.type(data) === "boolean" ) // { // oneSide = data; // data = filter; // filter = false; // } // // if( !concept || !data ) // return( false ); // // var decoder = "", URI = false, bothSides = (typeof oneSide === "undefined"); // // if( $.type(filter) === "string" ) // { // URI = filter; // filter = false; // } // // if( res = internalUrl.exec( concept ) ) // { // //TODO: verificar se a decodificaçao deve ser feita em cada item do array // data = this.decode( concept, data ); // concept = res[1]; // decoder = res[2]; // } // /////////////////////////////////////////////////////////////////////////// // // if( bothSides || oneSide ) // this.report( concept, URI, data, !bothSides ); // // if( bothSides || !oneSide ) // { // if( URI ) // { // var helper = {}; // helper[URI] = data; // data = helper; // } // // for( var URI in data ) // { // var current = this.check( concept, URI ) || {}; // // data[URI] = this.merge( current, data[URI] ); // // this.store( concept, URI, data[URI] ); // } // // } // // this.broadcast( concept, oneSide ? 'client' : 'server' ); // // return( true ); // }, // put: function( concept, URI, data, oneSide ){ // // ///////////////////////////// normalize //////////////////////////////// // if( $.type(URI) !== "string" && arguments.length < 4 ) // { // oneSide = data; // data = URI; // URI = false; // } // //////////////////////////////////////////////////////////////////////// // // ////////////////////////////// linkage ///////////////////////////////// // var result = false, links = this.links( concept ); // // for( var link in links ) // { // if( data[link] ) // { // if( $.isArray( data[link] ) ) // { // data[link] = this.put( links[link], data[link].URI, data[link], oneSide ); // } // else if( $.isObject( data[link] ) ) // { // $.each( data[link], function( i, el ){ // // data[link][i] = this.put( links[link], el.URI, el, oneSide ); // // }); // } // } // } // ////////////////////////////////////////////////////////////////////////// // // if( typeof data.URI === "undefined" ) // { // URI = this.add( concept, data, oneSide ); // } // else if( data.URI === false ) // { // status = this.remove( concept, URI, oneSide ); // } // else // { // status = this.set( concept, URI, data, oneSide ); // } // // if( URI && data.URI && URI !== data.URI ) // this.move( concept, URI, data.URI ); // // return( data.URI || URI ); // // }, // add: function( concept, data, oneSide ){ // // ///////////////////////////// normalize //////////////////////////////// // if( !concept || !data ) // return( false ); // // if( res = internalUrl.exec( concept ) ) // { // //TODO: verificar se a decodificaᅵᅵo deve ser feita em cada item do array // data = this.decode( concept, data ); // concept = res[1]; // decoder = res[2]; // } // // var bothSides = (typeof oneSide === "undefined"), uris = []; // // if( notArray = $.type(data) !== "array" ) // data = [ data ]; // ////////////////////////////////////////////////////////////////////////// // // for( var i = 0; i < data.length; i++ ) // { // var URI = uris[i] = this.generateURI( concept ); // // this.set( concept, URI, data[i], oneSide ); // } // // return( notArray ? uris[0] : uris ); // }, // put: function( concept, data ){ // // var decoder = ""; // // if( res = internalUrl.exec( concept ) ) // { // data = this.decode( concept, data ); // concept = res[1]; // decoder = res[2]; // } // // var New = [], Update = [], uris = []; // // if( notArray = $.type(data) !== "array" ) // data = [ data ]; // // for( var i = 0; i < data.length; i++ ) // { // if( !data[i].URI ) // { // uris[ uris.length ] = data[i].URI = this.create( concept, data[i] ); // New[ New.length ] = data[i]; // continue; // } // // for( var key in data[i] ) // if( klass = this.isReference( concept, key, data[i][key] ) ) // data[i][key] = this.put( klass + decoder, data[i][key] ); // // Update[ Update.length ] = this.update( concept, data[i].URI, data[i] ); // } // // this.report( concept, { "created": New, "updated": Update }); // // return( notArray ? uris[0] : uris ); // }, // merge: function( concept, current, data ){ // // current = current || {}; // // for( var key in data ) // current[key] = (klass = this.isReference( concept, key, data[key] )) ? // this.merge( klass, current[key], data[key] ) : data[key]; // // return( current ); // }, // // isReference: function( concept, key, value ){ // // return( ($.type(value) === "object" || // $.type(value) === "array" )? this.links[concept][key] : false ); // // }, // // set: function( concept, data, URI, mergeable ){ // // if( URI ) // { // var res = this.get( concept, true ) || {}; // // if( mergeable ) // data = this.merge( res[URI] || {}, data ); // // res[URI] = data; // // data = res; // } // // return this.store( concept, data ); // }, // // create: function( concept, data ){ // // if( notArray = ($.type(data) !== "array") ) // data = [ data ]; // // var uris = []; // // for( var i = 0; i < data.length; i++ ) // { // uris[ uris.length ] = data[i].URI = "javascript://" + (this.counter + i); // // this.set( concept, data[i], data[i].URI ); // } // // this.set( ":counter", (this.counter += data.length) ); // // return notArray ? uris[0] : uris; // }, // // update: function( concept, URI, data ) // { // var target = this.check( concept, URI ) || {}; // // target = this.merge( concept, target, data ); // // if( target.URI !== URI ) // this.remove( concept, URI ); // // this.set( concept, target, target.URI ); // // return( target ); // }, // // remove: function( concept, URI ){ // // if( !URI ) // return $.storage.del( concept ); // // var res = this.check( concept ); // // delete res[URI]; // // this.set( concept, res ); // }, // // del: function( concept, URI ){ // // this.remove( concept, URI ); // // this.report( concept, { "deleted": { 'URI': URI } }); // }, // // report: function( concept, changes ){ // // this.broadcast( concept, changes.created, changes.updated, changes.deleted ); // // if( changes.created ) // this.sync( concept, changes.created, 'create' ); // if( changes.updated ) // this.sync( concept, changes.updated, 'update' ); // if( changes.deleted ) // this.sync( concept, changes.deleted, 'delete' ); // // }, // // // sync: function( concept, data, type ){ // // if( $.type(data) !== "array" ) // data = [ data ]; // // $.each( data, function( i, el ){ // // DataLayer.send( concept, el, type ); // // }); // // }, // // // // // // request: function( concept, URI, filter ){ // // // if( startsDoubleDot.test(concept) ) // // return( false ); // // filter = filter || {}; // // if( URI ) // filter.URI = URI; // // return this.send( concept, filter, "read", true ); // // }, // // send: function( concept, data, type, wait ){ // // switch( type ) // { // case "create": type = "POST"; break; // case "update": type = "PUT"; break; // case "delete": type = "DELETE"; break; // case "read": type = "GET"; break; // } // // var url = this.basePath + concept; // // var result = [], notArray = false; // // // alert( data.URI ); // // if( data.URI && data.URI.indexOf("javascript://") !== 0 ) // url += "/" + data.URI; // // var callback = function( dt, textStatus, jqXHR ){ // // if( notArray = (!$.isArray( dt )) ) // dt = [ dt ]; // // $.each( dt, function( i, el ){ // // if( !el || !el.URI ) // return; // // if( data.URI ) // el = DataLayer.update( concept, data.URI, el ); // else // DataLayer.set( concept, el, el.URI ); // // result[ result.length ] = el; // DataLayer.broadcast( concept ); // }); // }; // // $.ajax({ // 'async': ( !wait ), // 'url': url, // 'type': type, // 'success': callback, // 'dataType': 'json', // 'data': data/*, // 'processData': false*/ // }); // // return( notArray ? result[0] || false : result ); // }, generateURI: function( concept ){ return this.URI( concept, this.generateId( concept ), "javascript" ); }, broadcast: function( concept, status, diff ){ if( this.listeners[ concept ] ) for( var i = 0; i < this.listeners[ concept ].length; this.listeners[ concept ][ i++ ]( status, diff ) ); }, listen: function( concept, listener ){ this.register( "listeners", concept, listener ); }, codec: function( concept, namespace, codec ){ if( codec.encoder ) this.encoder( concept, namespace, codec.encoder ); if( codec.decoder ) this.decoder( concept, namespace, codec.decoder ); if( codec.criteria ) this.register( "criterias", concept + ":" + namespace, codec.criteria ); }, encoder: function( concept, namespace, encoder ){ this.register( "encoders", concept + ":" + namespace, encoder ); }, encode: function( encoder, data, filter ){ if( this.encoders[ encoder ] ) for( var i = 0; i < this.encoders[ encoder ].length; data = this.encoders[ encoder ][ i++ ]( data, filter ) ); return( data ); }, decoder: function( concept, namespace, decoder ){ this.register( "decoders", concept + ":" + namespace, decoder ); }, decode: function( decoder, data ){ if( this.decoders[ decoder ] ) for( var i = 0; i < this.decoders[ decoder ].length; data = this.decoders[ decoder ][ i++ ]( data ) ); return( data ); }, criteria: function( codec, filter ){ if( this.criterias[ codec ] ) for( var i = 0; i < this.criterias[ codec ].length; filter = this.criterias[ codec ][ i++ ]( filter ) ); return( filter ); }, register: function( kind, concept, deployable ){ if( !this[ kind ][ concept ] ) this[ kind ][ concept ] = []; this[ kind ][ concept ][ this[ kind ][ concept ].length ] = deployable; }, start: function(){ var timer = function(){ setTimeout( timer, 1 ); var now = parseInt( $.now() / 1000 ); var tasks = DataLayer.tasks[ now ]; if( !tasks ) return; for( var i = 0; i < tasks.length; i++ ) { var result = tasks[i].task( now ); DataLayer.schedule( tasks[i].task, tasks[i].factor ); } delete DataLayer.tasks[ now ]; }; setTimeout( timer, 1 ); }, schedule: function( task, time ){ time = time || 1; var index = parseInt( $.now() / 1000 ) + time; if( !this.tasks[ index ] ) this.tasks[ index ] = []; this.tasks[ index ][ this.tasks[ index ].length ] = { task: task, factor: time }; }, poll: function( concept, time ){ this.schedule( function( now ){ DataLayer.commit( concept ); }, time || 5 ); }, init: function(){ this.counter = parseInt( this.get( ":counter", false ) ) || 0; if( !this.dispatchPath ) this.dispatchPath = "../../"; if( !this.templatePath ) this.templatePath = ""; if( !this.basePath ) this.basePath = this.dispatchPath + "REST.php?q="; this.start(); } } DataLayer.init(); // setTimeout(function(){ // // // // }, 1000 ); // var DataLayer = { // // get: function( concept, filter ){ // // var data = $.storage.get( concept ); // // if( !filter ) // return( data ); // // return this.filter( data, filter ); // }, // // filter:function( data, filter ){ // // if( filter.charAt ) // filter = { URI: filter }; // // var filtered = []; // // $.each(data, function(i, obj){ // // for( var attr in filter ) // if( filter[attr] !== obj[attr] ) // return( true ); // // filtered[i] = obj; // }); // // return( filtered ); // }, // // find: function( concept, filter, callback ){ // // var data = this.get( concept, filter ); // // if( data ) // return callback( data ); // // //TODO: register callback like a weak listener // // // $.ajax({ // // type: 'GET', // // data: $.param( filter ), // // success: callback, // // url: BASE_PATH + filter.URI || concept // // }); // this.report( concept, filter ); // }, // // put: function( concept, data, filter ){ // // var beforeDiff = this.store( concept, $.extend({},data) ); // // this.report( concept, data, filter, beforeDiff ); // }, // // // /*var data = { // startTime: $.now(), // endTime: $.now() + 1800000, // summary: "meu querido evento", // description: "desc do evento", // location: "prognus software livre", // class: 1, // calendar: 1, // category: 1, // participants: [ { // user: { isExternal: true, mail: "user7@prognus.org", name: "user7" } // },{ // user: "1003" // } ] // // };*/ // // // merge:function( data, target ){ // // var diff = { New: {}, Update:{}, Delete: {} }; // // for( var key in data ) // { // if( !target[ key ] ) // diff.New[ key ] = target[ key ] = data[ key ]; // // // // } // // } // // store: function( concept, data, filter ){ // // if( !data.spline ) // data = [ data ]; // // var target = $.storage.get( concept ); // // var diff = { New: {}, Update:{}, Delete: {} }; // // for( var i = 0; i < data.length; i++ ) // { // if( data[i].URI && target[ data[i].URI ] ) // { // diff.Update[ data[i].URI ] = this.merge( target[ data[i].URI ], data[i] ); // } // else // { // diff.New[] = data[i]; // } // } // // // // this.broadcast( concept, data ); // // if( filter ) // target = this.filter( target, filter ); // // if( target ) // data = $.extend( target, data ); // // $.storage.set( concept, data ); // // // return; // }, // // set: function( concept, data, filter ){ // // // // }, // // post: function( concept, data, filter, isNew ){ // // var callback = function( ){ DataLayer.store( concept, data, filter ) }; // // //TODO: register callback like a weak listener // // this.report( concept, data, filter, isNew ); // }, // // report: function( concept, filter, postData, isNew ){ // // $.ajax({ // type: postData ? isNew ? 'POST' : 'PUT' : 'GET', // data: postData || $.param( filter ), // success: function( data ){ DataLayer.broadcast( concept ) }, // url: BASE_PATH + filter.URI || concept // }); // }, // // del:function( concept, filter ){ // // // // } // // broadcast: function( concept, data ){ // // // // }, // // pool: function(){ // // }, // // refresh: function(){ // // } // }; // // DataLayer = { // // get: function( concept, filter ){ // // var data = $.storage.get( concept ); // // if( !filter ) // return( data ); // // if( filter.charAt ) // filter = { URI: filter }; // // var filtered = []; // // $.each(data, function(i, obj){ // // for( var attr in filter ) // if( filter[attr] !== obj[attr] ) // return( true ); // // filtered[i] = obj; // }); // // return( filtered ); // }, // // find: function( concept, filter, callback ){ // // var data = this.get( concept, filter ); // // if( data ) // return callback( data ); // // $.ajax({ // type: 'GET', // data: $.param( filter ), // success: callback, // url: filter.URI || concept // }); // }, // // put: function( concept, data, filter ){ // // var target = this.get( concept, filter ); // // if( target ) // data = $.extend( target, data ); // // $.storage.set( concept, data ); // // //diff // }, // // post: function( concept, data, filter ){ // // // // }, // // pool: function(){ // // }, // // queue: function(){ // // }, // // dequeue: function(){ // // }, // // refresh: function(){ // // } // } // var DataLayer = { // cache: {}, // get: function( concept, location ){ /* if( location ) {*/ // var schema = $.data( this.cache, concept + ':schema' ); // var uri = []; // // $.each( schema, function( i, addrs ){ // uri[ uri.length ] = location[addrs]; // }); /*var filter = [], result = false; while( !(result = $.data( this.cache, uri.join( '.' ) )) || !(uri = uri.join('.')) ) filter[ filter.length ] = uri.pop(); if( !filter.length ) { var indexes = $.data( this.cache, uri + ':indexes' ); if( indexes ) Array.prototype.concat.apply( result, indexes ); return( result ); } for( var i = 0; i < result.length; i++ ) { } if( result.length ) return( result ); }*/ // var data = $.data( this.cache, concept ); // if( !data ) // $.ajax( ); // return( data ); // }, // data: function(){ // // // // } // // search: function( concept, filter ){ // // var schema = $.data( this.cache, concept + ':schema' ); // var uri = []; // // $.each( schema, function( i, addrs ){ // uri[ uri.length ] = location[addrs]; // }); // } // put: function( concept, data, location ){ // if( location ) // { // var schema = $.data( this.cache, concept + ':schema'); // var uri = []; // $.each( schema, function( i, addrs ){ // uri[ uri.length ] = location[addrs]; // }); // var result = false, filter = []; // while( !(result = $.data( this.cache, uri.join('.')) ) // filter[ filter.length ] = uri.pop(); // $.data( this.cache, ' // } // var model = $.storage.get( concept ); // // $.each( model, function( i, o ){ // $.each( location, function( ii, attr ){ // if( o[ii] === attr ) // return( false ); // }); // }); // return $.data( this.cache, concept, data ); // }, // del: function( concept, location ){ // // if( location ) // { // var schema = $.data( this.cache, 'concepts', concept ); // var uri = []; // // $.each( schema, function( i, addrs ){ // uri[ uri.length ] = location[addrs]; // }); // // concept = uri.join( '.' ); // var model = $.storage.get( concept ); // // $.each( model, function( i, o ){ // $.each( location, function( ii, attr ){ // if( o[ii] === attr ) // return( false ); // }); // }); // } // // // $.removeData( this.cache, concept ); // } // }