text: //----------------------------------------------------------------------------
  //  Copyright (C) 2008-2011  The IPython Development Team
  //
  //  Distributed under the terms of the BSD License.  The full license is in
  //  the file COPYING, distributed as part of this software.
  //----------------------------------------------------------------------------
  
  //============================================================================
  // Cell
  //============================================================================
  /**
   * An extendable module that provide base functionnality to create cell for notebook.
   * @module IPython
   * @namespace IPython
   * @submodule Cell
   */
  
  var IPython = (function (IPython) {
  
      var utils = IPython.utils;
  
      /**
       * The Base `Cell` class from which to inherit
       * @class Cell
       */
  
      /*
       * @constructor
       */
      var Cell = function () {
          this.placeholder = this.placeholder || '';
          this.read_only = false;
          this.selected = false;
          this.element = null;
          this.metadata = {};
          // load this from metadata later ?
          this.user_highlight = 'auto';
          this.create_element();
          if (this.element !== null) {
              this.element.data("cell", this);
              this.bind_events();
          }
          this.cell_id = utils.uuid();
      };
  
  
      /**
       * Empty. Subclasses must implement create_element.
       * This should contain all the code to create the DOM element in notebook
       * and will be called by Base Class constructor.
       * @method create_element
       */
      Cell.prototype.create_element = function () {};
  
  
      /**
       * Subclasses can implement override bind_events.
       * Be carefull to call the parent method when overwriting as it fires event.
       * this will be triggerd after create_element in constructor.
       * @method bind_events
       */
      Cell.prototype.bind_events = function () {
          var that = this;
          // We trigger events so that Cell doesn't have to depend on Notebook.
          that.element.click(function (event) {
              if (that.selected === false) {
                  $([IPython.events]).trigger('select.Cell', {'cell':that});
              }
          });
          that.element.focusin(function (event) {
              if (that.selected === false) {
                  $([IPython.events]).trigger('select.Cell', {'cell':that});
              }
          });
      };
  
      /**
       * Triger typsetting of math by mathjax on current cell element
       * @method typeset
       */
      Cell.prototype.typeset = function () {
          if (window.MathJax){
              var cell_math = this.element.get(0);
              MathJax.Hub.Queue(["Typeset",MathJax.Hub,cell_math]);
          }
      };
  
      /**
       * should be triggerd when cell is selected
       * @method select
       */
      Cell.prototype.select = function () {
          this.element.addClass('ui-widget-content ui-corner-all');
          this.selected = true;
      };
  
  
      /**
       * should be triggerd when cell is unselected
       * @method unselect
       */
      Cell.prototype.unselect = function () {
          this.element.removeClass('ui-widget-content ui-corner-all');
          this.selected = false;
      };
  
      /**
       * should be overritten by subclass
       * @method get_text
       */
      Cell.prototype.get_text = function () {
      };
  
      /**
       * should be overritten by subclass
       * @method set_text
       * @param {string} text
       */
      Cell.prototype.set_text = function (text) {
      };
  
      /**
       * Refresh codemirror instance
       * @method refresh
       */
      Cell.prototype.refresh = function () {
          this.code_mirror.refresh();
      };
  
  
      /**
       * should be overritten by subclass
       * @method  edit
       **/
      Cell.prototype.edit = function () {
      };
  
  
      /**
       * should be overritten by subclass
       * @method render
       **/
      Cell.prototype.render = function () {
      };
  
      /**
       * should be overritten by subclass
       * serialise cell to json.
       * @method toJSON
       **/
      Cell.prototype.toJSON = function () {
          var data = {};
          data.metadata = this.metadata;
          return data;
      };
  
  
      /**
       * should be overritten by subclass
       * @method fromJSON
       **/
      Cell.prototype.fromJSON = function (data) {
          if (data.metadata !== undefined) {
              this.metadata = data.metadata;
          }
      };
  
  
      /**
       * can the cell be splitted in 2 cells.
       * @method is_splittable
       **/
      Cell.prototype.is_splittable = function () {
          return true;
      };
  
  
      /**
       * @return {String} - the text before the cursor
       * @method get_pre_cursor
       **/
      Cell.prototype.get_pre_cursor = function () {
          var cursor = this.code_mirror.getCursor();
          var text = this.code_mirror.getRange({line:0,ch:0}, cursor);
          text = text.replace(/^\n+/, '').replace(/\n+$/, '');
          return text;
      }
  
  
      /**
       * @return {String} - the text after the cursor
       * @method get_post_cursor
       **/
      Cell.prototype.get_post_cursor = function () {
          var cursor = this.code_mirror.getCursor();
          var last_line_num = this.code_mirror.lineCount()-1;
          var last_line_len = this.code_mirror.getLine(last_line_num).length;
          var end = {line:last_line_num, ch:last_line_len}
          var text = this.code_mirror.getRange(cursor, end);
          text = text.replace(/^\n+/, '').replace(/\n+$/, '');
          return text;
      };
  
  
      /** Grow the cell by hand. This is used upon reloading from JSON, when the
       *  autogrow handler is not called.
       *
       *  could be made static
       *
       *  @param {Dom element} - element
       *  @method grow
       **/
      Cell.prototype.grow = function(element) {
          var dom = element.get(0);
          var lines_count = 0;
          // modified split rule from
          // http://stackoverflow.com/questions/2035910/how-to-get-the-number-of-lines-in-a-textarea/2036424#2036424
          var lines = dom.value.split(/\r|\r\n|\n/);
          lines_count = lines.length;
          if (lines_count >= 1) {
              dom.rows = lines_count;
          } else {
              dom.rows = 1;
          }
      };
  
      /**
       * Toggle  CodeMirror LineNumber
       * @method toggle_line_numbers
       **/
      Cell.prototype.toggle_line_numbers = function () {
          if (this.code_mirror.getOption('lineNumbers') == false) {
              this.code_mirror.setOption('lineNumbers', true);
          } else {
              this.code_mirror.setOption('lineNumbers', false);
          }
          this.code_mirror.refresh();
      };
  
      /**
       * force codemirror highlight mode
       * @method force_highlight
       * @param {object} - CodeMirror mode
       **/
      Cell.prototype.force_highlight = function(mode) {
          this.user_highlight = mode;
          this.auto_highlight();
      };
  
      /**
       * Try to autodetect cell highlight mode, or use selected mode
       * @methods _auto_highlight
       * @private
       * @param {String|object|undefined} - CodeMirror mode | 'auto'
       **/
      Cell.prototype._auto_highlight = function (modes) {
          //Here we handle manually selected modes
          if( this.user_highlight != undefined &&  this.user_highlight != 'auto' )
          {
              var mode = this.user_highlight;
              CodeMirror.autoLoadMode(this.code_mirror, mode);
              this.code_mirror.setOption('mode', mode);
              return;
          }
          var first_line = this.code_mirror.getLine(0);
          // loop on every pairs
          for( var mode in modes) {
              var regs = modes[mode]['reg'];
              // only one key every time but regexp can't be keys...
              for(var reg in regs ) {
                  // here we handle non magic_modes
                  if(first_line.match(regs[reg]) != null) {
                      if (mode.search('magic_') != 0) {
                          this.code_mirror.setOption('mode',mode);
                          CodeMirror.autoLoadMode(this.code_mirror, mode);
                          return;
                      }
                      var open = modes[mode]['open']|| "%%";
                      var close = modes[mode]['close']|| "%%end";
                      var mmode = mode;
                      mode = mmode.substr(6);
                      CodeMirror.autoLoadMode(this.code_mirror, mode);
                      // create on the fly a mode that swhitch between
                      // plain/text and smth else otherwise `%%` is
                      // source of some highlight issues.
                      // we use patchedGetMode to circumvent a bug in CM
                      CodeMirror.defineMode(mmode , function(config) {
                          return CodeMirror.multiplexingMode(
                          CodeMirror.patchedGetMode(config, 'text/plain'),
                              // always set someting on close
                              {open: open, close: close,
                               mode: CodeMirror.patchedGetMode(config, mode),
                               delimStyle: "delimit"
                              }
                          );
                      });
                      this.code_mirror.setOption('mode', mmode);
                      return;
                  }
              }
          }
          // fallback on default (python)
          var default_mode = this.default_mode || 'text/plain';
          this.code_mirror.setOption('mode', default_mode);
      };
  
      IPython.Cell = Cell;
  
      return IPython;
  
  }(IPython));
  
  