forena-8.x-1.x-dev/forena_query/forena_query.js

forena_query/forena_query.js
/**
 * @file forena_query.js
 * Javascript library for forena query
 */
var forenaSQLEditor = new function() { 
  // Initialize the object, binding the autocomplete function to the appropriate contorl
  // THis should be called in the attach behavior
  this.control = {}; // Jquery Control selector
  this.instance = this; 

  this.position = 0; 
  this.autocompletePath = ''; 
  this.tokens = []; 
  this.tables = []; 
  this.reserved = ['select', 
                   'from', 
                   'inner', 
                   'left', 
                   'join', 
                   'right', 
                   'cross', 
                   'where', 
                   'having', 
                   'order', 
                   'group', 
                   'by',
                   'on',
                   'in']; 
  this.states = [
                   'select', 
                   'from', 
                   'join', 
                   'on', 
                   'where', 
                   'having', 
                   'order', 
                   'group'
                   ]; 
  this.repos = ''; 
  var self = this; 
  
  /**
   * Parse the list of tables/aliases from the sql. 
   */ 
  this.tableAliases = function() { 
    // Split on commas
    var clause = self.parseTables(); 
    var tables = {}; 
    var parts = clause.split(","); 
    for (var i=0; i< parts.length; i++) { 
      if (parts[i].trim() && parts[i].search('--') == -1) { 
        var p = parts[i].trim().split(/\s+/);
        if (p.length > 1) {
          tables[p[1]] = p[0];  
        }
        else { 
          tables[p[0]] = p[0]
        }
      }
    }
    return tables; 
  };
  
  /**
   * Parse table aliases from the sql statement
   */
  this.parseTables = function () { 
    var sql = self.control.get(0).value; 
    // Split array on words. 
    var words = sql.split(/\s+/); // Break apart the sql statement by white space. 
    var word=''; 
    var state = '';
    var table_clause = ''; // rough comma separated list of tables/aliases for further processing
    var wcnt = 0; // Word count within the statement section
    for( var i=0; i<words.length; i++) {
      // Remove the parents as we don't need them for this level of parsing. 
      word = words[i].toLowerCase().replace(/\(|\)/g,"");
        
      // Certain words mean we are in a different section of the sql. 
      if (self.states.indexOf(word) != -1) {
        state = word; 
        wcnt = 0; 
      }
      
      // non reserved words are candidates for table aliases. 
      if (self.reserved.indexOf(word) == -1) {
        wcnt++; 
        switch (state) { 
         case 'from': 
         case 'join': 
           if (wcnt == 1) {
             table_clause = table_clause + ','; 
           }
           table_clause = table_clause + ' ' + word; 
           break; 
        }
      }
    }
    return table_clause; 
  };
  
  /**
   * Initialization function for setting up the editor. 
   * Should fire on attach (document ready). 
   */
  this.init = function (context, settings) {
    self.control = jQuery('#edit-config-file', context); 
    self.control.keydown(self.keyDownHandler); 
    self.control.keyup(self.keyUpHandler); 
    self.autocompletePath = settings.basePath + "forena-query/table_autocomplete_simple/sampledb"; 
    self.repos = settings.forenaSQLEditor.repos; 
    self.tokens = []; 
    self.term = ''; 
    self.control.autocomplete(
      { 
        source : self.autocompleteSource, 
        minLength : 1, 
        focus : function () { return false; }, 
        select : self.selectHandler
      }
    ); 
  };
  
  /**
   * Determine the caret position registered on keyup. 
   */
  this.getCaretPosition = function() {
    var el = self.control.get(0);
    var pos = 0;
    if('selectionStart' in el) {
        pos = el.selectionStart;
    } else if('selection' in document) {
        el.focus();
        var Sel = document.selection.createRange();
        var SelLength = document.selection.createRange().text.length;
        Sel.moveStart('character', -el.value.length);
        pos = Sel.text.length - SelLength;
    }
    self.position = pos; 
  };
  
  /**
   * Move the caret position to a specified place in the cursor. 
   */
  this.setCaretPosition = function(pos) { 
    var c = self.control.get(0); 
    if (c.setSelectionRange) {
      c.setSelectionRange(pos, pos);
    } else if (c.createTextRange) {
      var range = c.createTextRange();
      range.collapse(true);
      range.moveEnd('character', pos);
      range.moveStart('character', pos);
      range.select();
    }
  }; 
  
  //Determine the current term 
  this.currentTerm = function() { 
    // Get the string up to the position. 
    var s =  self.control.val().slice(0, self.position); 
    var term = /\S+$/.exec(s);
    if (term) { 
      self.term = term.toString(); 
    }
    else { 
      self.term = ''; 
    }
    return self.term; 
  };
  
  /**
   * New function for determining dropdown contents based on last term. 
   */
  this.autocompleteSource = function(request, response) { 
    self.reponse = response; 
    var t = self.currentTerm(); 
    var table = ''; 
    var alias = ''; 
    table = '';
    alias = ''; 
    if (t.search('.') != -1) { 
      var aliases = self.tableAliases(); 
      var a = t.substring(0, t.indexOf('.')); 
      if (aliases[a]) { 
        table = aliases[a];
        alias = a; 
        t = t.substring(t.indexOf('.')+1); 
      }
      
    }
    jQuery.getJSON(
      self.autocompletePath, 
      {
        term : t,
        repos : self.repos, 
        table : table,
        alias : alias
      }, 
      self.jsonSuccess
    ); 
  };
  
  /**
   * Ajax return handler 
   * saves away raw response and then chains autocomplete response. 
   */
  this.jsonSuccess = function(data) { 
    console.log(data); 
    self.tokens = data; 
    self.reponse(data); 
  };
  
  /**
   * Inserts the term into the specified location of the textarea. 
   */
  this.select = function(token) { 
    var s = self.control.val().slice(0, self.position).lastIndexOf(self.term); 
    var end = self.control.val().slice(self.position); 
    var start = self.control.val().slice(0, s);
    self.control.get(0).value = start + token + end;
    // Make sure to close the widget. 
    self.control.autocomplete("close");
    self.setCaretPosition(s + token.length);
    
    
  };
  
  this.selectHandler = function (event, ui) { 
    self.select(ui.item.value); 
    if (event.keyCode == jQuery.ui.keyCode.TAB) { 
      event.preventDefault(); 
      self.control.get(0).focus(); 
    }
    return false; 
  };
  
  this.keyUpHandler = function () { 
    self.getCaretPosition(); 
  };
  
  /*
   * Custom keyboard handler
   */
  this.keyDownHandler = function (event) { 
    // Prevent the default autocomplete behavior of changing focus after hitting the tab key. 
    if (event.keyCode === jQuery.ui.keyCode.TAB) { 
      event.preventDefault(); 
      // Select the first item in the array
      if (self.tokens && self.tokens.length > 0) { 
        var token = self.tokens[0]; 
        if (token) self.select(token); 
      }

    }
  };
  
};

Drupal.behaviors.forena_query_sql_editor = { 
    attach : forenaSQLEditor.init
};

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc