/*** @ https://developer.mozilla.org/en-US/docs/Web/API/Element/matches ***/ if ( !Element.prototype.matches ) { Element.prototype.matches = Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector || function(s) { var matches = (this.document || this.ownerDocument).querySelectorAll(s), i = matches.length; while (--i >= 0 && matches.item(i) !== this) {} return i > -1; } ; } /*** @ https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent ***/ (function () { if ( typeof window.CustomEvent === "function" ) return false; function CustomEvent ( event, params ) { params = params || { bubbles: false, cancelable: false, detail: undefined }; var evt = document.createEvent( 'CustomEvent' ); evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail ); return evt; } CustomEvent.prototype = window.Event.prototype; window.CustomEvent = CustomEvent; })(); if ( !Element.prototype.indexOf ) { Element.prototype.indexOf = function( childNode ) { return Array.prototype.indexOf.call( this.children, childNode ); } ; } Event.prototype.__preventDefaultValue = false; var __preventDefault = Event.prototype.preventDefault; Event.prototype.preventDefault = function() { this.__preventDefaultValue = true; return __preventDefault.call( this ); }; Event.prototype.__stopImmediatePropagationValue = false; var __stopImmediatePropagation = Event.prototype.stopImmediatePropagation; Event.prototype.stopImmediatePropagation = function() { this.__stopImmediatePropagationValue = true; return __stopImmediatePropagation.call( this ); }; Event.prototype.__stopPropagationValue = false; var __stopPropagation = Event.prototype.stopPropagation; Event.prototype.stopPropagation = function() { this.__stopPropagationValue = true; return __stopPropagation.call( this ); }; silk.htmlQuery = xb.core.object.extend( { ctor: function( ctx, selectors ) { this.__ctx = ctx; this.__selectors = ( selectors instanceof Array ) ? selectors : [ selectors ]; this.__selectFn = function( m ) { return m; }; this.__query = null; }, select: function( selectFn ) { this.__selectFn = selectFn; return this; }, publish: function( name, precedence ) { silk.drivers.library.add( this.__selectors, name, this.__selectFn, precedence ); return this; }, as: function( name, handler ) { console.error( "silk.html.query.as(", name, ") called / fn has been deprecated!" ); var handler = ( typeof( handler ) === "function" ) ? handler : function( m ) { return m; }; silk.drivers.library.add( this.__selectors, name, handler ); return this; }, on: function( nameList, handler, precedence ) { var selectFn = this.__selectFn; var nameList = ( nameList instanceof Array ) ? nameList : [ nameList ]; for ( var i = 0, il = nameList.length; i < il; i++ ) { silk.drivers.library.add( this.__selectors, nameList[ i ], function( m, evt ) { //console.log( "silk.htmlQuery::on", name, handler ); return handler.call( selectFn.call( null, m ), evt ); }, precedence ); } return this; }, prepare: function() { if ( this.__query === null ) { this.__query = silk.drivers.library.query( this.__selectors ); } return this; }, match: function( domNode, traversal ) { return this.prepare().__query.match( domNode, traversal ); }, find: function( domNode ) { return this.prepare().__query.find( domNode ); }, } ); silk.htmlObject = xb.core.object.extend( { factory: function( context, domNode ) { var ctor = context[ 0 ].ctor; if ( typeof( ctor ) !== "function" ) { ctor = silk.htmlObject; } return new ctor( context, domNode ); }, ctor: function( context, domNode ) { this.context = context; this.domNode = context[ 0 ].domNode; this.dataObject = silk.htmlObject.dataObject( this ); }, data: function() { return this.dataObject.get(); }, parent: function() { if ( this.context.length < 2 ) { return null; } return silk.htmlObject( this.context.slice( 1 ), this.context[ 1 ].domNode ); }, } ); silk.htmlObject.dataObject = xb.core.object.extend( { ctor: function( object ) { this.object = object; this.init(); }, init: function() { this.accessors = []; var context = this.object.context; var accessors = context[ 0 ].accessors; if ( ! ( accessors instanceof Array ) ) { return false; } var prev = null; for ( var i = 0, il = accessors.length; i < il; i++ ) { var acc = accessors[ i ]( this, prev ); this.accessors.push( acc ); prev = acc; } return this; }, get: function() { return this.accessors[ this.accessors.length - 1 ]; }, properties: function( accessor ) { return this.object.context[ 0 ]; }, parent: function( accessor ) { if ( accessor.__parent !== null ) { return accessor.__parent; } var p = this.object.parent(); if ( p === null ) { debugger return null; } return p.data(); }, } ); silk.html = ( xb.core.object.extend( { ctor: function() { this.__renderer = null; this.__initStyles(); this.__initEventRoutes(); }, query: function( selectors ) { return silk.htmlQuery( this, selectors ); }, getLibrary: function( name ) { if ( typeof( silk.drivers ) === "undefined" ) { console.warn( "silk.html::getLibrary(", name, ")", "Drivers not yet loaded" ); return; } if ( silk.drivers.library.__list.length === 0 ) { silk.drivers.library.link(); } return silk.drivers.library.get( name ); }, properties: function( domNode, traversal, scope ) { var query = this.getLibrary( "silk/html/properties" ); if ( query === null ) { return null; } var match = query.matchAll( domNode, traversal, scope ); if ( match === null ) { return null; } var data = { domNode: match.domNode }; for ( var i = 0, il = match.matches.length; i < il; i++ ) { var properties = match.matches[ i ]; for ( var name in properties ) { if ( data[ name ] instanceof Array ) { if ( properties[ name ] instanceof Array ) { data[ name ] = data[ name ].concat( properties[ name ] ); } else { data[ name ].push( data[ name ] ); } continue; } data[ name ] = properties[ name ]; } } return data; }, path: function( domNode, traversal, scope ) { var properties = this.properties( domNode, traversal, scope ); if ( properties !== null ) { return [ properties ].concat( this.path( properties.domNode.parentElement ) ); } return []; }, object: function( domNode, traversal, scope ) { var path = this.path( domNode, traversal, scope ); if ( path.length < 1 ) { return null; } return silk.htmlObject( path, domNode ); var fn = path[ 0 ].ctor; if ( typeof( fn ) !== "function" ) { fn = silk.htmlObject; } return fn.call( null, path, domNode ); }, handleEvent: function( evt, name, scope ) { var result = null; var s = Date.now(); // console.log( "[CS] handleEvent(" + name + ", ", evt.target, ")::start", s ); if ( typeof( silk.drivers ) === "undefined" ) { console.warn( "silk.html::handleEvent(", name, ")", "Drivers not yet loaded" ); return; } if ( silk.drivers.library.__list.length === 0 ) { silk.drivers.library.link(); } var set = silk.drivers.library.get( name ); if ( set !== null ) { result = set.handleEvent( evt, null, scope ); } var e = Date.now(); // console.log( "[CS] handleEvent(" + name + ")::end", e ); //, evt ); // console.log( "[CS] handleEvent(" + name + ")::total time in seconds", ( e - s ) / 1000 ); return result; }, dispatchEvent: function( evt, domNode, scope ) { var result = null; var set = this.getLibrary( evt.type ); if ( set !== null ) { result = set.handleEvent( evt, domNode, scope ); } return result; }, render: function( domNode, data, reset ) { if ( this.__renderer === null ) { this.__renderer = silk.html.renderer(); } var s = Date.now(); console.log( "[silk.html.render] Rendering::start", s ); if ( this.__renderer === null ) { console.error( "[silk.html.renderer] Backend not yet loaded" ); } else { this.__renderer.render( domNode, data, reset ); } var e = Date.now(); console.log( "[silk.html.render] Rendering::end", e ); console.log( "[silk.html.render] Rendering::total time in seconds", ( e - s ) / 1000 ); }, __initEventRoutes: function() { document.addEventListener( "click", function( evt ) { silk.html.handleEvent( evt, "events/mouse/click" ); if ( evt.button !== 2 ) { silk.html.handleEvent( evt, "events/click" ); } }, true ); document.addEventListener( "focusin", function( evt ) { silk.html.handleEvent( evt, "events/focus/in" ); }, true ); document.addEventListener( "focusout", function( evt ) { silk.html.handleEvent( evt, "events/focus/out" ); }, true ); document.addEventListener( "dragstart", function( evt ) { silk.html.handleEvent( evt, "events/drag/start" ); }, true ); document.addEventListener( "dragenter", function( evt ) { silk.html.handleEvent( evt, "events/drag/enter" ); }, true ); document.addEventListener( "dragleave", function( evt ) { silk.html.handleEvent( evt, "events/drag/leave" ); }, true ); document.addEventListener( "submit", function( evt ) { silk.html.handleEvent( evt, "events/submit" ); }, true ); document.addEventListener( "mousedown", function( evt ) { silk.html.handleEvent( evt, "events/mouse/down" ); }, true ); document.addEventListener( "mouseup", function( evt ) { silk.html.handleEvent( evt, "events/mouse/up" ); }, true ); document.addEventListener( "touchstart", function( evt ) { silk.html.handleEvent( evt, "events/touch/start" ); }, true ); document.addEventListener( "touchend", function( evt ) { silk.html.handleEvent( evt, "events/touch/end" ); }, true ); // document.addEventListener( "simply-data-changed", function( evt ) { // console.warn( "*simply-data-changed*" ); // }, true ); document.addEventListener( "load", function( evt ) { silk.html.handleEvent( evt, "events/system/load" ); }, true ); var evtMutationsChange = function( evt ) { var last = evtMutationsChange.last; if ( typeof( last ) === "undefined" ) { last = null; } if ( last !== null && last.timeStamp === evt.timeStamp ) { console.log( "Dropping evt", evt, "for events/mutations/change" ); return; } silk.html.handleEvent( evt, "events/mutations/change" ); evtMutationsChange.last = evt; return; } ; document.addEventListener( "change", evtMutationsChange ); document.addEventListener( "input", evtMutationsChange ); document.addEventListener( "events/dispatcher/render", function( evt ) { silk.html.handleEvent( evt, evt.type ); }, true ); return this; }, __initStyles: function() { var ua = window.navigator.userAgent; var iOS = !!ua.match(/iPad/i) || !!ua.match(/iPhone/i); var webkit = !!ua.match(/WebKit/i); var iOSSafari = iOS && webkit && !ua.match(/CriOS/i); if ( iOS ) { var styleElm = document.createElement( "style" ); styleElm.innerText = "* { cursor: pointer; }"; document.head.appendChild( styleElm ); } }, } ) )(); silk.html.renderer = xb.core.object.extend( { factory: function() { if ( typeof( editor ) !== "object" ) { console.log( "[silk.html.renderer] Initing CS backend" ); return new silk.html.renderer.cs(); } console.log( "[silk.html.renderer] Initing SimplyEditor backend" ); return new silk.html.renderer.simply(); }, ctor: function() { }, } ); silk.html.renderer.simply = xb.core.object.extend( silk.html.renderer, { ctor: function() { silk.html.renderer.prototype.ctor.call( this ); }, render: function( domNode, data, reset ) { console.log( "[silk.html.render] SimplyEditor backend" ); var copy = []; for ( var i = 0, il = data.length; i < il; i++ ) { copy.push( xb.core.object.prototype.copy.call( data[ i ], true ) ); } editor.fireEvent( "databinding:pause", domNode ); if ( reset ) { if ( typeof( domNode.dataBinding ) === "object" ) { domNode.dataBinding.set( copy ); } else { editor.data.list.set( domNode, copy ); } } else { editor.data.list.append( domNode, copy ); } if ( typeof( hope ) !== "undefined" && document.body.getAttribute( "data-simply-edit" ) ) { // editor.editmode.makeEditable( domNode ); } var nodes = domNode.querySelectorAll( "[data-field-attributes]" ); for ( var i = 0, il = nodes.length; i < il; i++ ) { var node = nodes[ i ]; var object = silk.html.object( node ); var attr = node.getAttribute( "data-field-attributes" ); var data = null; if ( attr === "list-attributes" ) { //debugger } if ( node.getAttribute( "data-simply-field" ) || node.getAttribute( "data-simply-list" ) ) { data = object.parent().data().get(); } else { data = object.data().get(); } if ( typeof( data ) !== "object" || data === null ) { console.error( "*skip*", attr ); continue; } if ( typeof( data[ attr ] ) !== "undefined" ) { // console.warn( "attributes", data[ attr ] ); for ( var n in data[ attr ] ) { node.setAttribute( n, data[ attr ][ n ] ); } } } editor.fireEvent( "databinding:resume", domNode ); } } ); silk.html.renderer.cs = xb.core.object.extend( silk.html.renderer, { ctor: function() { silk.html.renderer.prototype.ctor.call( this ); }, render: function( domNode, data, reset ) { console.log( "[silk.html.render] CS backend" ); var query = silk.html.query( "[data-template-id] := template" ); var m = query.match( domNode ); if ( m === null ) { console.error( "[silk.html.render] Could not find a node with attribute [data-template-id]!" ); } else { var _data = data; var _id = m.template.domNode.getAttribute( "data-template-id" ); var _field = domNode.getAttribute( "data-simply-list" ); var _resource = domNode.getAttribute( "data-simply-data" ); var _mount = domNode.getAttribute( "data-silk-mount" ); if ( _mount ) { _resource += "/" + _mount; } if ( typeof( _data.getArray ) === "function" ) { _data = _data.getArray(); } var index = _field; if ( _resource ) { index = _resource + "/" + index; } var innerHTML = ""; if ( typeof( ctx.elm ) === "function" ) { var result = ctx.templates[ _id ][ index ]( {}, _data ); innerHTML = result.content; } else { innerHTML = ctx.templates[ _id ][ index ]( _data, true ); } if ( reset ) { domNode.innerHTML = innerHTML; } else { // https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML domNode.insertAdjacentHTML( "beforeend", innerHTML ); // domNode.innerHTML += innerHTML; } } }, } );