X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=to-be-integrated%2Fplugins%2Fcode_editor%2Fstatic%2Fjs%2Fcode_editor.js;fp=to-be-integrated%2Fplugins%2Fcode_editor%2Fstatic%2Fjs%2Fcode_editor.js;h=664bbdc7aae14db31d9d697afff1d7865c9f3c78;hb=31540dd504798e0aca69e10d8144fbedc5b16af8;hp=0000000000000000000000000000000000000000;hpb=937653fd70bbf7d95bcf870e7f2b46b4a8fec486;p=myslice.git diff --git a/to-be-integrated/plugins/code_editor/static/js/code_editor.js b/to-be-integrated/plugins/code_editor/static/js/code_editor.js new file mode 100644 index 00000000..664bbdc7 --- /dev/null +++ b/to-be-integrated/plugins/code_editor/static/js/code_editor.js @@ -0,0 +1,433 @@ +/** + * Description: CodeEditor plugin + * Copyright (c) 2012 UPMC Sorbonne Universite - INRIA + * License: GPLv3 + */ + +/* + * It's a best practice to pass jQuery to an IIFE (Immediately Invoked Function + * Expression) that maps it to the dollar sign so it can't be overwritten by + * another library in the scope of its execution. + */ + +(function($){ + + var default_code_mirror_options = { + gutters: ["note-gutter", "CodeMirror-linenumbers"], + tabSize: 4, + indentUnit: 4, + matchBrackets: true, + lineNumbers: true, + lineWrapping: true, + tabMode: 'spaces' // or 'shift' + }; + + + // routing calls + jQuery.fn.CodeEditor = function( method ) { + if ( methods[method] ) { + return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 )); + } else if ( typeof method === 'object' || ! method ) { + return methods.init.apply( this, arguments ); + } else { + jQuery.error( 'Method ' + method + ' does not exist on jQuery.CodeEditor' ); + } + }; + + /*************************************************************************** + * Public methods + ***************************************************************************/ + + var methods = { + + /** + * @brief Plugin initialization + * @param options : an associative array of setting values + * @return : a jQuery collection of objects on which the plugin is + * applied, which allows to maintain chainability of calls + */ + init : function ( options ) { + + /* Default settings */ + var options = $.extend( { + useCodeMirror: true, + codeMirrorOptions: default_code_mirror_options, + syntaxHighlighting: [] + }, options); + + return this.each(function() { + + var $this = $(this); + + /* An object that will hold private variables and methods */ + var plugin = new CodeEditor(options); + $this.data('Manifold', plugin); + + /* Events */ + $this.on('show.CodeEditor', methods.show); + + }); // this.each + }, // init + + /** + * @brief Plugin destruction + * @return : a jQuery collection of objects on which the plugin is + * applied, which allows to maintain chainability of calls + */ + destroy : function( ) { + + return this.each(function() { + var $this = $(this); + var hazelnut = $this.data('Manifold'); + + // Unbind all events using namespacing + $(window).unbind('Manifold'); + + // Remove associated data + hazelnut.remove(); + $this.removeData('Manifold'); + }); + }, // destroy + + show : function( ) { + var $this=$(this); + // xxx wtf. why [1] ? would expect 0... + if (debug) + messages.debug("Hitting suspicious line in hazelnut.show"); + var oTable = $($('.dataTable', $this)[1]).dataTable(); + oTable.fnAdjustColumnSizing() + + /* Refresh dataTabeles if click on the menu to display it : fix dataTables 1.9.x Bug */ + $(this).each(function(i,elt) { + if (jQuery(elt).hasClass('dataTables')) { + var myDiv=jQuery('#hazelnut-' + this.id).parent(); + if(myDiv.height()==0) { + var oTable=$('#hazelnut-' + this.id).dataTable(); + oTable.fnDraw(); + } + } + }); + } // show + + }; // var methods; + + /*************************************************************************** + * Plugin object + ***************************************************************************/ + + function CodeEditor(options) + { + + this.initialize = function() { + this.validationTooltip; + + // switch off CodeMirror for IE + //if (Browser.Engine.trident) options.useCodeMirror = false; + this.element = $('#' + this.options.plugin_uuid + '-textarea')[0]; // jordan added [0] for jquery + if (!this.options.syntaxHighlighting.contains(this.options.language)) { + this.forceDefaultCodeMirrorOptions(); + } + //this.setOptions(this.options); + var is_disallowed = (disallowedPlatforms.contains(Browser.Platform.name)); + if (this.options.useCodeMirror && !is_disallowed) { + // hide textarea + this.element.hide(); + // prepare settings + if (!this.options.codeMirrorOptions.stylesheet && this.options.stylesheet) { + this.options.codeMirrorOptions.stylesheet = this.options.stylesheet.map(function(path) { + return mediapath + path; + }); + } + if (!this.options.codeMirrorOptions.path) { + var codemirrorpath = ''; // jordan + this.options.codeMirrorOptions.path = codemirrorpath + 'js/'; + } + if (!this.options.codeMirrorOptions.content) { + this.options.codeMirrorOptions.content = this.element.get('value'); + } + + var parentNode = this.element.getParent(); + var options = { value: this.element.value }; + options = Object.append(options, this.options.codeMirrorOptions); + this.editor = CodeMirror(parentNode, options); + + // run this after initialization + if (!this.options.codeMirrorOptions.initCallback){ + if (this.options.codeMirrorOptions.autofocus) { + // set current editor + Layout.current_editor = this.options.name; + } + } + + // set editor options that can only be set once the editor is initialized + var cur = this.editor.getLineHandle(this.editor.getCursor().line); + this.setEditorEvents({ + focus: function(){ + Layout.current_editor = this.options.name; + // this.editor.removeLineClass(cur, 'background', 'activeline'); + // this.editor.hlLine = this.editor.addLineClass(0, "background", "activeline"); + }, + cursorActivity: function(){ + // var cur = this.editor.getLineHandle(this.editor.getCursor().line); + // if (cur != this.editor.hlLine) { + // this.editor.removeLineClass(this.editor.hlLine, 'background', 'activeline'); + // this.editor.hlLine = this.editor.addLineClass(cur, 'background', 'activeline'); + // } + }, + blur: function(){ + // this.editor.removeLineClass(this.editor.hlLine, 'background', 'activeline'); + }, + change: function(){ + this.validateEditorInput.call(this, parentNode); + window.editorsModified = true; + }.bind(this) + }); + + // disable new line insertion when saving fiddle + CodeMirror.keyMap.default['Ctrl-Enter'] = function(){ + return false; + }; + + // don't let Emmet capture this + delete CodeMirror.keyMap.default['Cmd-L']; + } + + this.editorLabelFX = new Fx.Tween(this.getLabel(), { + property: 'opacity', + link: 'cancel' + }); + + this.getWindow().addEvents({ + mouseenter: function() { + this.editorLabelFX.start(0); + }.bind(this), + mouseleave: function() { + this.editorLabelFX.start(0.8); + }.bind(this) + }); + + // jordan commented + // mooshell.addEvents({ + // 'run': this.b64decode.bind(this) + // }); + + Layout.registerEditor(this); + this.setLabelName(this.options.language || this.options.name); + }, + + /** + * + */ + this.validateEditorInput = function(parentNode){ + var currentValue = this.getCode(); + var warnings = []; + + // destroy tooltip if it already exists for this editor + if (this.validationTooltip){ + this.validationTooltip.destroy(); + } + + // create the container + this.validationTooltip = Element('ul', { + 'class': 'warningTooltip' + }); + + // collect warnings + Object.each(this.options.disallowed, function(value, key){ + if (currentValue.test(key, 'i')){ + warnings.push('
  • ' + value + '
  • '); + } + }); + + // inject container + this.validationTooltip = this.validationTooltip.inject(parentNode); + + // squash and apply warnings + this.validationTooltip.set({ + html: warnings.join('') + }); + }, + + /** + * + */ + this.getEditor = function() { + return this.editor || this.element; + }, + + /** + * + */ + this.getWindow = function() { + if (!this.window) { + this.window = this.element.getParent('.window'); + } + return this.window; + }, + + /** + * + */ + this.getLabel = function() { + return this.getWindow().getElement('.window_label'); + }, + + /** + * + */ + this.b64decode = function() { + this.element.set('value', this.before_decode); + }, + + /** + * + */ + this.getCode = function() { + return (this.editor) ? this.editor.getValue() : this.element.get('value'); + }, + + /** + * + */ + this.updateFromMirror = function() { + this.before_decode = this.getCode(); + this.element.set('value', Base64.encode(this.before_decode)); + }, + + /** + * + */ + this.updateCode = function() { + this.element.set('value', this.getCode()); + }, + + /** + * + */ + this.clean = function() { + this.element.set('value', ''); + this.cleanEditor(); + }, + + /** + * + */ + this.cleanEditor = function() { + if (this.editor) this.editor.setCode(''); + }, + + /** + * + */ + this.hide = function() { + this.getWindow().hide(); + }, + + this.show = function() { + this.getWindow().show(); + }, + + /** + * + */ + this.setEditorOptions = function(options){ + Object.each(options, function(fn, key){ + this.editor.setOption(key, fn.bind(this)); + }, this); + }, + + /** + * + */ + this.setEditorEvents = function(e){ + Object.each(e, function(fn, key){ + this.editor.on(key, fn.bind(this)); + }, this); + }, + + /** + * + */ + this.setLanguage = function(language) { + // Todo: This is hacky + this.setLabelName(language); + }, + + /** + * + */ + this.setLabelName = function(language) { + this.getLabel().set('text', this.window_names[language] || language); + }, + + /** + * + */ + this.setStyle = function(key, value) { + if (this.editor) return $(this.editor.frame).setStyle(key, value); + return this.element.setStyle(key, value); + }, + + /** + * + */ + this.setStyles = function(options) { + if (this.editor) return $(this.editor.frame).setStyles(options); + return this.element.setStyles(options); + }, + + /** + * + */ + this.setWidth = function(width) { + this.getWindow().setStyle('width', width); + }, + + /** + * + */ + this.setHeight = function(height) { + this.getWindow().setStyle('height', height); + }, + + /** + * + */ + this.getPosition = function() { + if (this.editor) return $(this.editor.frame).getPosition(); + return this.element.getPosition(); + }, + + /** + * + */ + this.forceDefaultCodeMirrorOptions = function() { + this.options.codeMirrorOptions = default_code_mirror_options; + } + + // BEGIN CONSTRUCTOR + + /* member variables */ + this.options = options; + + var object = this; + + // adapted from EditorCM.js from jsfiddle.net + + var disallowedPlatforms = ['ios', 'android', 'ipod']; + + this.window_names = { + 'javascript': 'JavaScript', + 'html': 'HTML', + 'css': 'CSS', + 'scss': 'SCSS', + 'coffeescript': 'CoffeeScript', + 'javascript 1.7': 'JavaScript 1.7' + }; + + this.initialize(); + // END CONSTRUCTOR + } // function CodeEditor + +})( jQuery ); +