Most of the editor css, working editor

This commit is contained in:
Eston Bond
2010-11-01 15:32:46 -07:00
parent 135156cea5
commit b4006ec007
6 changed files with 535 additions and 276 deletions
+393
View File
@@ -0,0 +1,393 @@
/**
* gollum.editor.js
* A jQuery plugin that creates the Gollum Editor.
*
* Usage:
* $.GollumEditor(); on DOM ready.
*/
(function($) {
// Editor options
var DefaultOptions = {
MarkupType: 'markdown',
EditorMode: 'code',
HasFunctionBar: true,
Debug: true
};
var ActiveOptions = {};
/**
* $.GollumEditor
*
* You don't need to do anything. Just run this on DOM ready.
*/
$.GollumEditor = function( IncomingOptions ) {
ActiveOptions = $.extend( DefaultOptions, IncomingOptions );
debug('GollumEditor loading');
if ( EditorHas.baseEditorMarkup() ) {
// Initialise the function bar by loading proper definitions
if ( EditorHas.functionBar() ) {
var htmlSetMarkupLang =
$('#gollum-editor-body').attr('data-markup-lang');
if ( htmlSetMarkupLang ) {
ActiveOptions.MarkupType = htmlSetMarkupLang;
}
if ( !LanguageDefinition.isLoadedFor(ActiveOptions.MarkupType) ) {
debug('Loading language definition for ' + ActiveOptions.MarkupType);
LanguageDefinition.loadFor( ActiveOptions.MarkupType,
function(data, textStatus) {
console.log( data, textStatus );
if ( textStatus != 'success' ) {
debug('Language definition could not be loaded for markup '
+ 'type ' + ActiveOptions.MarkupType);
return;
}
// activate the function bar
debug('Activating function bar');
FunctionBar.activate();
} );
} else {
// loaded language already
debug('Activating function bar');
FunctionBar.activate();
}
}
// EditorHas.functionBar
}
// EditorHas.baseEditorMarkup
};
/**
* $.GollumEditor.defineLanguage
* Defines a set of language actions that Gollum can use.
* Used by the definitions in langs/ to register language definitions.
*/
$.GollumEditor.defineLanguage = function( language_name, languageObject ) {
console.log('Defining language for ' + language_name);
if ( typeof languageObject == 'object' )
LanguageDefinition.define( language_name, languageObject );
else
debug('GollumEditor.defineLanguage: definition for ' + language_name
+ ' is not an object');
};
/**
* debug
* Prints debug information to console.log if debug output is enabled.
*
* @param mixed Whatever you want to dump to console.log
* @return void
*/
var debug = function(m) {
if ( ActiveOptions.Debug && console
&& typeof console.log == 'function' ) {
console.log( m );
}
};
/**
* LanguageDefinition
* Language definition file handler
* Loads language definition files as necessary.
*/
var LanguageDefinition = {
_ACTIVE_LANG: '',
_LOADED_LANGS: [],
_LANG: {},
/**
* Defines a language
*
* @param name string The name of the language
* @param name object The definition object
*/
define: function( name, definitionObject ) {
LanguageDefinition._ACTIVE_LANG = name;
LanguageDefinition._LOADED_LANGS.push( name );
LanguageDefinition._LANG[name] = definitionObject;
},
/**
* gets a definition object for a specified attribute
*
* @param string attr The specified attribute.
* @param string specified_lang The language to pull a definition for.
* @return object if exists, null otherwise
*/
getDefinitionFor: function( attr, specified_lang ) {
if ( !specified_lang ) {
specified_lang = LanguageDefinition._ACTIVE_LANG;
}
if ( LanguageDefinition.isLoadedFor(specified_lang) &&
LanguageDefinition._LANG[specified_lang][attr] &&
typeof LanguageDefinition._LANG[specified_lang][attr] == 'object' ) {
return LanguageDefinition._LANG[specified_lang][attr];
}
return null;
},
/**
* loadFor
* Asynchronously loads a definition file for the current markup.
* Definition files are necessary to use the code editor.
*
* @param string markup_name The markup name you want to load
* @return void
*/
loadFor: function( markup_name, on_complete ) {
// attempt to load the definition for this language
var script_uri = 'js/gollum-editor/langs/' + markup_name + '.js';
$.ajax({
url: script_uri,
dataType: 'script',
complete: function( xhr, textStatus ) {
if ( typeof on_complete == 'function' ) {
on_complete( xhr, textStatus );
}
}
});
},
/**
* isLoadedFor
* Checks to see if a definition file has been loaded for the
* specified markup language.
*
* @param string markup_name The name of the markup.
* @return boolean
*/
isLoadedFor: function( markup_name ) {
if ( LanguageDefinition._LOADED_LANGS.length == 0 ) return false;
for ( var i=0; i < LanguageDefinition._LOADED_LANGS.length; i++ ) {
if ( LanguageDefinition._LOADED_LANGS[i] == markup_name )
return true;
}
return false;
}
};
/**
* EditorHas
* Various conditionals to check what features of the Gollum Editor are
* active/operational.
*/
var EditorHas = {
/**
* EditorHas.baseEditorMarkup
* True if the basic editor form is in place.
*
* @return boolean
*/
baseEditorMarkup: function() {
return ( $('#gollum-editor').length &&
$('#gollum-editor-body').length );
},
/**
* EditorHas.functionBar
* True if the Function Bar markup exists.
*
* @return boolean
*/
functionBar: function() {
return ( ActiveOptions.HasFunctionBar &&
$('#gollum-editor-function-bar').length );
},
/**
* EditorHas.ff4Environment
* True if in a Firefox 4.0 Beta environment.
*
* @return boolean
*/
ff4Environment: function() {
var ua = new RegExp(/Firefox\/4.0b/);
return ( ua.test( navigator.userAgent ) );
}
};
/**
* FunctionBar
*
* Things the function bar does.
*/
var FunctionBar = {
isActive: false,
/**
* FunctionBar.activate
* Activates the function bar, attaching all click events
* and displaying the bar.
*
*/
activate: function() {
$('#gollum-editor-function-bar a.function-button')
.click( FunctionBar.evtFunctionButtonClick );
// show bar as active
$('#gollum-editor-function-bar').addClass( 'active' );
FunctionBar.isActive = true;
},
/**
* FunctionBar.evtFunctionButtonClick
* Event handler for the function buttons. Traps the click and
* executes the proper language action.
*
* @param jQuery.Event jQuery event object.
*/
evtFunctionButtonClick: function(e) {
e.preventDefault();
var def = LanguageDefinition.getDefinitionFor( $(this).attr('id') );
if ( typeof def == 'object' ) {
FunctionBar.executeAction( def );
}
},
/**
* FunctionBar.executeAction
* Executes a language-specific defined action for a function button.
*
*/
executeAction: function( definitionObject ) {
// get the selected text from the textarea
var txt = $('#gollum-editor-body').val();
// hmm, I'm not sure this will work in a textarea
var selPos = FunctionBar
.getFieldSelectionPosition( $('#gollum-editor-body') );
var selText = FunctionBar.getFieldSelection( $('#gollum-editor-body') );
var repText = selText;
// execute a replacement function if one exists
if ( definitionObject.exec &&
typeof definitionObject.exec == 'function' ) {
repText = definitionObject.exec (
txt, selText, $('#gollum-editor-body') );
}
// execute a search/replace if they exist
var searchExp = /([^\n]+)/gi;
if ( definitionObject.search &&
typeof definitionObject.search == 'object' ) {
debug('Replacing search Regex');
searchExp = definitionObject.search;
debug( searchExp );
}
// replace text
if ( definitionObject.replace &&
typeof definitionObject.replace == 'string' ) {
debug('Running replacement - using ' + definitionObject.replace);
repText = repText.replace( searchExp, definitionObject.replace );
}
// append if necessary
if ( definitionObject.append &&
typeof definitionObject.append == 'string' ) {
repText += definitionObject.append;
}
if (repText)
FunctionBar.replaceFieldSelection( $('#gollum-editor-body'),
repText );
},
/**
* getFieldSelectionPosition
* Retrieves the selection range for the textarea.
*
* @return object the .start and .end offsets in the string
*/
getFieldSelectionPosition: function( $field ) {
if ($field.length) {
return {
start: $field[0].selectionStart,
end: $field[0].selectionEnd
}
}
},
/**
* getFieldSelection
* Returns the currently selected substring of the textarea.
*
* @param jQuery A jQuery object for the textarea.
* @return string Selected string.
*/
getFieldSelection: function( $field ) {
var selStr = '';
var selPos;
if ( $field.length ) {
selPos = FunctionBar.getFieldSelectionPosition( $field );
selStr = $field.val().substring( selPos.start, selPos.end );
debug('Selected: ' + selStr + ' (' + selPos.start + ', '
+ selPos.end + ')');
return selStr;
}
return false;
},
/**
* replaceFieldSelection
* Replaces the currently selected substring of the textarea with
* a new string.
*
* @param jQuery A jQuery object for the textarea.
* @param string The string to replace the current selection with.
*/
replaceFieldSelection: function( $field, replaceText ) {
var selPos = FunctionBar.getFieldSelectionPosition( $field );
var fullStr = $field.val();
$field.val( fullStr.substring(0, selPos.start) + replaceText +
fullStr.substring(selPos.end));
if ( $field[0].setSelectionRange ) {
$field[0].focus();
$field[0].setSelectionRange( selPos.start,
selPos.start + replaceText.length );
}
}
};
})(jQuery);
jQuery(document).ready(function() {
$.GollumEditor();
});
-260
View File
@@ -1,260 +0,0 @@
/**
* gollum.editor.js
* A jQuery plugin that creates the Gollum Editor.
*
* Usage:
* $.GollumEditor(); on DOM ready.
**/
/* (function($) { */
var GollumDefaults = {
MarkupType: 'markdown',
EditorMode: 'code',
HasFunctionBar: true,
Debug: true
};
var ActiveOptions = {};
$.GollumEditor = function(options) {
ActiveOptions = $.extend(GollumDefaults, options);
debug('GollumEditor loading');
if ( EditorHas.baseEditorMarkup() ) {
// Initialise the function bar by loading proper definitions
if ( EditorHas.functionBar() ) {
var htmlSetMarkupLang =
$('#gollum-editor-body').attr('data-markup-lang');
if ( htmlSetMarkupLang ) {
ActiveOptions.MarkupType = htmlSetMarkupLang;
}
if ( !LanguageDefinition.isLoadedFor(ActiveOptions.MarkupType) ) {
debug('Loading language definition for ' + ActiveOptions.MarkupType);
LanguageDefinition.loadFor(ActiveOptions.MarkupType,
function(data, textStatus) {
if (textStatus != 'success') {
debug('Language definition could not be loaded for markup '
+ 'type ' + ActiveOptions.MarkupType);
return;
}
// activate the function bar
FunctionBar.activate();
});
}
}
}
};
$.GollumEditor.defineLanguage = function( language_name, languageObject ) {
if ( typeof languageObject == 'object' )
LanguageDefinition.define( language_name, languageObject );
else
debug('GollumEditor.defineLanguage: definition for ' + language_name
+ ' is not an object');
};
/**
* debug
* Prints debug information to console.log if debug output is enabled.
*
* @param mixed Whatever you want to dump to console.log
* @return void
**/
var debug = function(m) {
if ( ActiveOptions.Debug && console
&& typeof console.log == 'function' ) {
console.log(m);
}
};
/**
* LanguageDefinition
* Language definition file handler
* Loads language definition files as necessary.
**/
var LanguageDefinition = {
_ACTIVE_LANG: '',
_LOADED_LANGS: [],
_LANG: {},
/**
* Defines a language
**/
define: function( name, definitionObject ) {
LanguageDefinition._LANG[name] = definitionObject;
LanguageDefinition._ACTIVE_LANG = name;
},
/**
* gets a definition object for a specified attribute
*
* @param string attr The specified attribute.
* @param string specified_lang The language to pull a definition for.
* @return object if exists, null otherwise
**/
getDefinitionFor: function( attr, specified_lang ) {
if ( !specified_lang ) {
specified_lang = LanguageDefinition._ACTIVE_LANG;
}
if ( LanguageDefinition.isLoadedFor(specified_lang) &&
LanguageDefinition._LANG[specified_lang][attr] &&
typeof LanguageDefinition_LANG[specified_lang][attr] == 'object' ) {
return LanguageDefinition._LANG[specified_lang][attr];
}
return null;
},
/**
* loadFor
* Asynchronously loads a definition file for the current markup.
* Definition files are necessary to use the code editor.
*
* @param string markup_name The markup name you want to load
* @return void
**/
loadFor: function( markup_name, on_complete ) {
// attempt to load the definition for this language
var script_uri = 'js/gollum-editor/langs/' + markup_name + '.js';
$.ajax({
url: script_uri,
dataType: 'script',
complete: function(xhr, textStatus) {
if (textStatus == 'success') {
LanguageDefinition._LOADED_LANGS.push(markup_name);
}
if (typeof on_complete == 'function') {
on_complete(xhr, textStatus, markup_name);
}
}
});
},
/**
* isLoadedFor
* Checks to see if a definition file has been loaded for the
* specified markup language.
*
* @param string markup_name The name of the markup.
* @return boolean
**/
isLoadedFor: function( markup_name ) {
if ( LanguageDefinition._LOADED_LANGS.length == 0 ) return false;
for (var i=0; i < LanguageDefinition._LOADED_LANGS.length; i++) {
if ( LanguageDefinition._LOADED_LANGS[i] == markup_name )
return true;
}
return false;
}
};
/**
* EditorHas
* Various conditionals to check what features of the Gollum Editor are
* active/operational.
**/
var EditorHas = {
baseEditorMarkup: function() {
return ( $('#gollum-editor').length &&
$('#gollum-editor-body').length );
},
functionBar: function() {
return ( ActiveOptions.HasFunctionBar &&
$('#gollum-editor-function-bar').length );
}
};
/**
* FunctionBar
*
* Things the function bar does.
**/
var FunctionBar = {
isActive: false,
activate: function() {
$('#gollum-editor-function-bar a.function-button')
.click(FunctionBar.evtFunctionButtonClick);
// show bar as active
$('#gollum-editor-function-bar').addClass('active');
FunctionBar.isActive = true;
},
evtFunctionButtonClick: function(e) {
e.preventDefault();
var def = LanguageDefinition.getDefinitionFor( $(this).attr() );
if ( def ) {
FunctionBar.executeAction( def );
}
},
executeAction: function( definitionObject ) {
// get the selected text from the textarea
var txt = $('#gollum-editor-body').val();
// hmm, I'm not sure this will work in a textarea
var selText = $('#gollum-editor-body').getSelection();
var repText = null;
// exec a function if it exists first
if ( definitionObject.exec &&
typeof definitionObject.exec == 'function' ) {
definitionObject(txt, selText, $('#gollum-editor-body'));
}
// exec search/replace if both exist
if ( definitionObject.replace &&
typeof definitionObject.replace == 'string' ) {
var searchRegex = /(.*)/gi;
if ( definitionObject.search &&
( typeof definitionObject.search == 'string' ||
typeof definitionObject.search == 'regexp' )) {
searchRegex = definitionObject.search;
} else {
debug('Invalid search regex, using default');
}
repText = selText.replace(searchRegex, definitionObject.replace);
} else {
debug('Invalid replacement string');
}
// now, add append if it exists
if ( definitionObject.append &&
typeof definitionObject.append == 'string' ) {
repText += definitionObject.append;
}
if (repText)
$('#gollum-editor-body').replaceSelection(repText);
}
};
/* })(jQuery); */
jQuery(document).ready(function() {
$.GollumEditor();
});