/************************************************/ /* IPB3 Javascript */ /* -------------------------------------------- */ /* (c) IPS, Inc 2009 */ /* -------------------------------------------- */ /* Author: Matt Mecham */ /************************************************/ var _tt = window.IPBACP; _tt.prototype.tabbedEditor = { callbacks: { 'open' : '', 'switch' : '', 'close' : '' }, wrapId: '', templates: { 'textArea' : new Template( "
" ), 'tab' : new Template("
  • #{title}
  • " ) }, openTabs: $H(), sPos: {}, _sT : false, _body : null, _po: undefined, _poId: 0, init: function() { Debug.write("Initializing acp.tabbedEditor.js"); document.observe("dom:loaded", function(){ }); }, /** * Manually called init function * * @access public */ initialize: function() { /* Create some divs for use later */ var tabs = new Element( 'div', { id: 'tbe_tabstrip' } ).hide().addClassName( 'tbe_tabstrip' ); $( acp.tabbedEditor.wrapId ).insert( tabs ); var wrap = new Element( 'div', { id: 'tbe_wrap' } ); $( acp.tabbedEditor.wrapId ).insert( wrap ); /* Set body */ acp.tabbedEditor._body = document.getElementsByTagName('body')[0]; }, /** * Open Tab * Creates a tab, or opens a new one if required * * @access public * @param string ID to assign to tab * @param string Tab title * @param string Tab contents */ openTab: function( id, title, content, event ) { /* Store scroll pos */ if ( ! Object.isUndefined( acp.tabbedEditor._body.scrollTop ) ) { acp.tabbedEditor._sT = acp.tabbedEditor._body.scrollTop; } Debug.write( 'OpenTab ' + id ); if ( Object.isUndefined( acp.tabbedEditor.openTabs.get( id ) ) ) { acp.tabbedEditor._createTab( id, title, content ); } else { acp.tabbedEditor._focusTab( id ); } /* Restore scroll pos */ if ( acp.tabbedEditor._sT ) { acp.tabbedEditor._body.scrollTop = acp.tabbedEditor._sT; } }, /** * Close tab * * @access public * @param string Tab ID */ closeTab: function( id ) { /* INIT */ var _l = false; var _t = acp.tabbedEditor.openTabs.get( id ); Debug.write( "Closing tab: " + id ); if( ! Object.isUndefined( acp.tabbedEditor.callbacks['close'] ) ) { Debug.write( 'Calling callback' ); if ( ! acp.tabbedEditor.callbacks['close']( _t, this ) ) { return false; } } /* Remove Tab */ acp.tabbedEditor.openTabs.unset( id ); /* Remove editor div / text area */ $( 'tbe_editor_textarea_' + id ).remove(); $( 'tbe_editor_wrap_' + id ).remove(); /* Fetch next item inline */ $H( acp.tabbedEditor.openTabs ).each( function(tab) { /* Set last ID */ _l = tab.value['id']; } ); /* Make one lit? */ if ( _l !== false ) { acp.tabbedEditor.openTab( _l ); } else { $( 'tbe_tabstrip' ).hide(); $( 'tbe_tabs' ).hide(); } }, /** * Get current file details * * @access public */ getCurrentFile: function() { if ( $$('.tbe_item_lit')[0] ) { var _t = $$('.tbe_item_lit')[0].id; if ( ! Object.isUndefined( _t ) ) { return acp.tabbedEditor.openTabs.get( _t.replace( 'tbe_tab_', '' ) ); } else { return undefined; } } else { return undefined; } }, /** * Get all files * * @access public */ getAllFiles: function() { return acp.tabbedEditor.openTabs; }, /** * Set Content of an editor * * @access public * @param string Tab ID * @param string Content to set */ setContent: function( id, content ) { if ( $( 'tbe_editor_textarea_' + id ) ) { $( 'tbe_editor_textarea_' + id ).value = content; } }, /** * Get Content of an editor * * @access public * @param string Tab ID * @param string Content to set */ getContent: function( id ) { id = ( id ) ? id : acp.tabbedEditor.getCurrentFile().id; if ( $( 'tbe_editor_textarea_' + id ) ) { return acp.tabbedEditor._HtmlOutgoing( $( 'tbe_editor_textarea_' + id ).value ); } }, /** * Set the edited status of a file * * @access public * @param string Tab ID * @param string [Content to update] * @param boolean */ setFileEditedMode: function( id, status, content ) { status = ( status === true ) ? true : false; var _t = acp.tabbedEditor.openTabs.get( id ); var _c = ( Object.isUndefined( content ) ) ? _t.content : content; /* Got stuff to do? */ if ( $( 'tbe_tab_s_' + id ) ) { if ( status === true && _t.edited !== true ) { /* mark as edited for the first time */ $( 'tbe_tab_s_' + id ).update( _t.title + ' *' ); } else if ( status === false && _t.edited !== false ) { _t.title = _t.title.replace( /\s+\*/, '' ); /* mark as NOT edited for the first time */ $( 'tbe_tab_s_' + id ).update( _t.title ); } } acp.tabbedEditor.openTabs.set( id, { id: _t.id, title: _t.title, content: _c, edited: status } ); return true; }, /** * Open tab (From event) * * @access private * @param object Mouse event * @param string Tab ID */ _openTab: function( event, id ) { Event.stop( event ); /* Open Tab */ acp.tabbedEditor.openTab( id ); }, /** * Open tab (From event) * * @access private * @param object Mouse event * @param string Tab ID */ _closeTab: function( event, id ) { Event.stop( event ); /* Open Tab */ acp.tabbedEditor.closeTab( id ); }, /** * Pop up tab (From event) * * @access private * @param object Mouse event * @param string Tab ID */ _popUp: function( event, id ) { Event.stop( event ); Debug.write("SHOWING POPUP"); /* Create pop-up elements */ var _id = '__p_' + id; var _data = acp.tabbedEditor.openTabs.get( id ); var _t = acp.tabbedEditor.templates['textArea'].evaluate( { 'id': _id } ); // Have to replace <> otherwise script tags are executed and removed // @link http://community.invisionpower.com/tracker/issue-32621-template-editor-maximise-button-deletes-script-tags var content = acp.tabbedEditor.getContent( id ).replace( //g, '>' ); var title = _data.title; var _initial = '

    ' + title + '

    ' + _t.replace( '{content}', content ) + "
    "; var _dims = document.viewport.getDimensions(); var _popUp = new ipb.Popup( '_p_' + id, { type: 'pane', w: ( _dims.width - 50 ) + 'px', h: ( _dims.height - 50 ) + 'px', initial: _initial }, { afterShow: acp.tabbedEditor._popUpShow, afterHide: acp.tabbedEditor._popUpClose } ); _popUp.show(); }, /** */ _popUpShow: function( event ) { var _dims = document.viewport.getDimensions(); var _id = '_' + event.id; $('tbe_editor_wrap_' + _id).setStyle( { height: ( _dims.height - 60 ) + 'px' } ); $('tbe_editor_wrap_' + _id).up('.popupWrapper').setStyle( { top: '20px' } ); $('tbe_editor_wrap_' + _id).up('.popupInner').setStyle( { overflow: 'hidden' } ); $('tbe_editor_textarea_' + _id).setStyle( { height: ( _dims.height - 90 ) + 'px' } ); /* Add listener */ $( 'tbe_editor_textarea_' + _id ).observe('keydown', acp.tabbedEditor._keyDownCheck.bindAsEventListener( event, event.id.replace( /^_p_/, '' ) ) ); $( 'tbe_editor_textarea_' + _id ).observe('change', acp.tabbedEditor._keyDownCheck.bindAsEventListener( event, event.id.replace( /^_p_/, '' ) ) ); }, /** */ _popUpClose: function( event ) { var _id = event.id; var _rid = _id.replace( /^_p_/, '' ); /* Update contents */ acp.tabbedEditor.setContent( _rid, $('tbe_editor_textarea_' + '_' + _id).value ); /* remove pop-up */ $( _id + '_popup' ).remove(); }, /** * Create a new tab * * @access private * @param string ID to assign to tab * @param string Tab title * @param string Tab contents */ _createTab: function( id, title, content ) { /* INIT */ var _t = acp.tabbedEditor.templates['textArea'].evaluate( { 'id': id } ); /* Push tab */ acp.tabbedEditor.openTabs.set( id, { id: id, title: title, content: content, edited: false } ); /* Create wrapper */ try { //Debug.write("htmlincoming: " + acp.tabbedEditor._HtmlIncoming( content ) ); $( 'tbe_wrap' ).innerHTML += _t.replace( '{content}', acp.tabbedEditor._HtmlIncoming( content ) ); } catch( e ) { /* insert sometimes complains with regular HTML which is why we don't use .insert() */ Debug.error( e ); } /* Add listener */ $( 'tbe_editor_textarea_' + id ).observe('keydown', acp.tabbedEditor._keyDownCheck.bindAsEventListener( this, id ) ); $( 'tbe_editor_textarea_' + id ).observe('change', acp.tabbedEditor._keyDownCheck.bindAsEventListener( this, id ) ); /* Set listener */ acp.tabbedEditor._setObserver( id ); Debug.write( "Created tab: " + id + " - " + title ); /* Focus */ acp.tabbedEditor._focusTab( id ); }, /** * Brings a tab into focus * * @access private * @param string Tab ID */ _focusTab: function( id ) { /* Hide all divs */ $H( acp.tabbedEditor.openTabs ).each( function(tab) { acp.tabbedEditor._hideTab( tab.value['id'] ); } ); /* Show the correct one */ acp.tabbedEditor._showTab( id ); /* Redraw tab strip */ acp.tabbedEditor._redrawTabstrip( id ); /* Call back */ if( ! Object.isUndefined( acp.tabbedEditor.callbacks['switch'] ) ) { acp.tabbedEditor.callbacks['switch']( acp.tabbedEditor.openTabs.get( id ), this ); } }, /** * Hide a tab * * @param string Tab ID */ _hideTab: function( id ) { var _t = acp.tabbedEditor.openTabs.get( id ); Debug.write( "Hiding tab " + id ); /* Make sure it's not hidden for focus grab */ $( 'tbe_editor_wrap_' + id ).show(); $( 'tbe_editor_textarea_' + id ).show(); $( 'tbe_editor_textarea_' + id ).value = _t.content; $( 'tbe_editor_textarea_' + id ).focus(); /* Store scrollTop */ if ( $( 'tbe_editor_textarea_' + id ).scrollTop ) { acp.tabbedEditor.sPos[ id ] = $( 'tbe_editor_textarea_' + id ).scrollTop; } $( 'tbe_editor_wrap_' + id ).hide(); }, /** * Hide a tab * * @param string Tab ID */ _showTab: function( id ) { Debug.write( "Showing tab " + id ); $( 'tbe_editor_wrap_' + id ).show(); $( 'tbe_editor_textarea_' + id ).focus(); /* Add listener */ $( 'tbe_editor_textarea_' + id ).observe('keydown', acp.tabbedEditor._keyDownCheck.bindAsEventListener( this, id ) ); $( 'tbe_editor_textarea_' + id ).observe('change', acp.tabbedEditor._keyDownCheck.bindAsEventListener( this, id ) ); /* Got a scroll pos? */ if ( !Object.isUndefined( acp.tabbedEditor.sPos[ id ] ) ) { $( 'tbe_editor_textarea_' + id ).scrollTop = acp.tabbedEditor.sPos[ id ]; } else { setTimeout( function(){ $( 'tbe_editor_textarea_' + id ).scrollTop = 0; }, 50 ); } /* Set listener */ acp.tabbedEditor._setObserver( id ); }, /** * Redraws the tab strip * * @access private * @param string ID to bring focus on */ _redrawTabstrip: function( focusId ) { /* Init */ var _c = 0; /* Remove old strip */ if( $( 'tbe_tabs' ) ) { $( 'tbe_tabs' ).remove(); } /* Add tab strip */ $( 'tbe_tabstrip' ).insert( new Element( 'ul', { id: 'tbe_tabs' } ).hide().addClassName( 'tbe_tabs' ) ); /* Build 'em */ $H( acp.tabbedEditor.openTabs ).each( function(tab) { /* Increment */ _c++; /* Edited? */ if ( tab.value['edited'] === true && ( ! tab.value['title'].match( /\*$/ ) ) ) { tab.value['title'] += ' *'; } $( 'tbe_tabs' ).insert( acp.tabbedEditor.templates['tab'].evaluate( { 'id': tab.value['id'], 'title' : tab.value['title'] } )); /* Focus */ $( 'tbe_tab_' + tab.value['id'] ).observe('click', acp.tabbedEditor._openTab.bindAsEventListener( this, tab.value['id'] )); /* Go FS and Close */ $( 'tbe_tab_f_' + tab.value['id'] ).observe('click', acp.tabbedEditor._popUp.bindAsEventListener( this, tab.value['id'] )); $( 'tbe_tab_c_' + tab.value['id'] ).observe('click', acp.tabbedEditor._closeTab.bindAsEventListener( this, tab.value['id'] )); } ); /* Make one lit? */ if ( focusId && $( 'tbe_tab_' + focusId ) ) { $( 'tbe_tab_' + focusId ).addClassName( 'tbe_item_lit' ); $( 'tbe_tabstrip' ).show(); $( 'tbe_tabs' ).show(); } else { $( 'tbe_tabstrip' ).hide(); $( 'tbe_tabs' ).hide(); } }, /** * Make HTML safe * * @access private * @param string Incoming HTML * @return string Outgoing HTML */ _HtmlIncoming: function( t ) { if ( t == null ) { return; } t = t.replace( /&/g, "&" ); t = t.replace( //g, ">" ); t = t.replace( /"/g, """ ); t = t.replace( /'/g, "'"); return t; }, /** * Return normal HTML * * @access private * @param string Incoming HTML * @return string Outgoing HTML */ _HtmlOutgoing: function( t ) { if ( t == null ) { return; } t = t.replace( "&" , "&", "g" ); t = t.replace( "<" , "<", "g" ); t = t.replace( ">" , ">", "g" ); t = t.replace( """ , '"', "g" ); t = t.replace( "'" , "'", "g" ); return t; }, /** * Set observer * @access private * @param Object ID to observe */ _setObserver: function( id ) { if ( ! Object.isUndefined( acp.tabbedEditor._po ) ) { Debug.write( "Clearing time out for " + acp.tabbedEditor._poId ); clearTimeout( acp.tabbedEditor._po ); } Debug.write( "Setting time out for " + id ); acp.tabbedEditor.poId = id; acp.tabbedEditor._po = setTimeout( acp.tabbedEditor._timeOut, 400 ); /*if ( !Object.isUndefined( acp.tabbedEditor.sPos[ id ] ) ) { $( 'tbe_editor_textarea_' + id ).scrollTop = acp.tabbedEditor.sPos[ id ]; } else { setTimeout( function(){ $( 'tbe_editor_textarea_' + id ).scrollTop = 0; }, 50 ); }*/ }, /** * Time out function * @access private * @param Object Event */ _timeOut: function( e ) { if ( acp.tabbedEditor.poId ) { var id = acp.tabbedEditor.poId; var _t = acp.tabbedEditor.openTabs.get( id ); if ( ! Object.isUndefined( _t ) ) { acp.tabbedEditor.openTabs.set( id, { id: _t.id, title: _t.title, content: $F( 'tbe_editor_textarea_' + id ), edited: _t.edited } ); acp.tabbedEditor._po = setTimeout( acp.tabbedEditor._timeOut, 400 ); } } }, /** * Check to see if this document is edited and if not, set it to edited * * @access private * @param object Event * @param string Tab ID */ _keyDownCheck: function( e, id ) { /* Ignore simple ctrl, shift and alt keydowns */ if( e.keyCode == 16 || e.keyCode == 17 || e.keyCode == 18 ) { return false; } acp.tabbedEditor.setFileEditedMode( id, true ); return true; } }; acp.tabbedEditor.init();