toloframework
Version:
Javascript/HTML/CSS compiler for Firefox OS or nodewebkit apps using modules in the nodejs style.
267 lines (242 loc) • 6.57 kB
JavaScript
/**
* @module wdg.modal
*
* @class
* @param {boolean} scroll - Default true.
*
*
* @example
* var mod = require('wdg.modal');
*/
var $ = require( "dom" );
var DB = require( "tfw.data-binding" );
var Flex = require( "wdg.flex" );
var Button = require( "wdg.button" );
/**
@exports {class}
@param {object} opts.content -
*/
function Modal( opts ) {
var that = this;
var body = $.div();
body.addEventListener("scroll", onScroll.bind( this, body ));
var laterScroll = function() {
window.setTimeout(function() {
onScroll( body );
});
};
var header = $.tag( 'header', 'thm-ele8', 'thm-bgPD' );
var footer = $.tag( 'footer' );
var cell = $.div( 'cell', 'thm-ele24', 'thm-bg0', [ header, body, footer ] );
var elem = $.elem( this, 'div', 'wdg-modal', [ $.div([cell]) ] );
DB.prop( this, 'content' )( function ( v ) {
$.clear( body );
if ( Array.isArray( v ) ) {
v.forEach( function ( itm ) {
$.add( body, itm );
} );
} else if ( typeof v !== 'undefined' && v !== null ) {
$.add( body, v );
}
laterScroll();
} );
DB.prop( this, 'header' )( function ( v ) {
$.clear( header );
if ( Array.isArray( v ) ) {
v.forEach( function ( itm ) {
$.add( header, itm );
} );
} else if ( typeof v !== 'undefined' && v !== null ) {
$.add( header, v );
}
laterScroll();
} );
DB.prop( this, 'footer' )( function ( v ) {
if ( typeof v === 'undefined' || v === null || v.length === 0 ) {
$.addClass( footer, 'hide' );
return;
}
$.removeClass( footer, 'hide' );
$.clear( footer );
if ( Array.isArray( v ) ) {
v.forEach( function ( itm ) {
$.add( footer, itm );
} );
} else {
$.add( footer, v );
}
laterScroll();
} );
DB.propString( this, 'width' )( function ( v ) {
$.css( body, {
'max-width': v
} );
laterScroll();
} );
DB.propAddClass( this, 'fullscreen' );
DB.propAddClass( this, 'padding' );
DB.propAddClass( this, 'scroll' );
DB.propAddClass( this, 'wide' );
DB.propBoolean( this, 'visible' )( function ( v ) {
if ( v ) {
that.attach();
} else {
that.detach();
}
} );
opts = DB.extend( {
visible: false,
header: [],
content: [],
footer: [],
padding: true,
scroll: true,
wide: false,
fullscreen: false,
width: 'auto'
}, opts, this );
}
/**
* @member Modal.refresh
* Refresh the content.
*/
Modal.prototype.refresh = function () {
DB.fire( this, 'content' );
return this;
};
/**
* @member Modal.attach
* Append element to body.
*/
Modal.prototype.attach = function () {
var that = this;
if ( this._timeoutDetach ) {
window.clearTimeout( this._timeoutDetach );
delete this._timeoutDetach;
}
document.body.appendChild( this.element );
DB.set( this, 'visible', true );
$.addClass( this, 'fadeout' );
window.setTimeout( function () {
$.removeClass( that, 'fadeout' );
} );
};
/**
* @member Modal.detach
* Remove element from body.
*/
Modal.prototype.detach = function () {
var that = this;
window.setTimeout( function () {
$.addClass( that, 'fadeout' );
} );
this._timeoutDetach = window.setTimeout( function () {
delete this._timeoutDetach;
DB.set( that, 'visible', false );
$.detach( that.element );
}, 250 );
};
/**
* @function Modal.comfirm
* @param {array|object|string} args.content - Content to display.
* @param {string} args.title - Modal title.
* @param {string} args.yes - Text of the confirmation button. Default is `OK`.
* @param {string} args.no - Text of the cancellation button. Default is `Cancel`.
* @param {function} args.onYes - Callback for confirmation.
* @param {function} args.onNo - Callback for cancel.
*/
Modal.confirm = function ( args, onYes, onNo ) {
if( typeof onYes === 'function' ) {
// This is the old calling way, with multiple arguments.
args = {
content: args,
onYes: onYes,
onNo: onNo
};
}
if( typeof args.title === 'undefined' ) args.title = _('confirm');
if( typeof args.yes === 'undefined' ) args.yes = _('ok');
if( typeof args.no === 'undefined' ) args.no = _('cancel');
if( typeof args.onYes === 'undefined' ) args.onYes = function() {};
if( typeof args.onNo === 'undefined' ) args.onNo = function() {};
onYes = args.onYes;
onNo = args.onNo;
var btnYes = new Button({ text: args.yes, flat: true });
var btnNo = new Button({ text: args.no, flat: true });
if ( Array.isArray(args.content) ) {
// Arrays must be wrapped in a DIV.
args.content = $.div(args.content);
}
if ( typeof args.content === 'string' && args.content.substr( 0, 6 ) == '<html>' ) {
// This is HTML code.
var html = args.content.substr( 6 );
args.content = $.div();
args.content.innerHTML = html;
}
var modal = new Modal( {
header: args.title,
footer: [btnNo, btnYes],
content: args.content
} );
modal.attach();
btnNo.on( function () {
modal.detach();
if ( typeof onNo === 'function' ) {
onNo();
}
} );
btnYes.on( function () {
if ( typeof onYes === 'function' ) {
var caption = onYes();
if ( typeof caption !== 'string' ) modal.detach();
else {
btnNo.visible = false;
btnYes.waitOn( caption );
}
} else {
modal.detach();
}
} );
return modal;
};
/**
* Display a message with an OK button.
*/
Modal.alert = function ( content, onOK ) {
var btnOK = new Button( { text: _('close'), flat: true } );
if ( typeof content === 'string' && content.substr( 0, 6 ) == '<html>' ) {
// This is HTML code.
var html = content.substr( 6 );
content = $.div();
content.innerHTML = html;
}
var modal = new Modal( {
footer: btnOK,
content: content
} );
modal.attach();
btnOK.on( function () {
modal.detach();
if ( typeof onOK === 'function' ) onOK();
} );
return modal;
};
/**
* Help the user to understand that the `body` can or cannot scroll to
* the top or to the bottom, or both.
* If the user can scroll up, a thin top inset shadow is displayed.
* If the user can scroll down, a thin bottom inset shadow is displayed.
*/
function onScroll( body, evt ) {
if( body.scrollTop > 0 ) {
$.addClass( body, "top" );
} else {
$.removeClass( body, "top" );
}
if( body.scrollHeight - body.scrollTop > body.clientHeight ) {
$.addClass( body, "bottom" );
} else {
$.removeClass( body, "bottom" );
}
}
module.exports = Modal;