source: sandbox/expressoMail1_2/corretor_ortografico/spell_checker/cpaint/cpaint2.inc.js @ 2375

Revision 2375, 38.1 KB checked in by paula.franceschini, 14 years ago (diff)

Ticket #891 - adicionando modulo do corretor ortografico

Line 
1/**
2* CPAINT - Cross-Platform Asynchronous INterface Toolkit
3*
4* http://sf.net/projects/cpaint
5*
6* released under the terms of the LGPL
7* see http://www.fsf.org/licensing/licenses/lgpl.txt for details
8*
9* @package      CPAINT
10* @access       public
11* @copyright    Copyright (c) 2005-2006 Paul Sullivan, Dominique Stender - http://sf.net/projects/cpaint
12* @author       Paul Sullivan <wiley14@gmail.com>
13* @author       Dominique Stender <dstender@st-webdevelopment.de>
14* @author               Stephan Tijink <stijink@googlemail.com>
15* @version      $Id$
16*/
17function cpaint() {
18  /**
19  * CPAINT version
20  *
21  * @access     protected
22  * @var        string      version
23  */
24  this.version = '2.0.2';
25 
26  /**
27  * configuration options both for this class but also for  the cpaint_call() objects.
28  *
29  * @access     protected
30  * @var        array       config
31  */
32  var config                      = new Array();
33  config['debugging']             = -1;
34  config['proxy_url']             = '';
35  config['transfer_mode']         = 'GET';
36  config['async']                 = true;
37  config['response_type']         = 'OBJECT';
38  config['persistent_connection'] = false;
39  config['use_cpaint_api']        = true;
40 
41  /**
42  * maintains the next free index in the stack
43  *
44  * @access   protected
45  * @var      integer   stack_count
46  */
47  var stack_count = 0;
48
49  /**
50  * property returns whether or not the browser is AJAX capable
51  *
52  * @access             public
53  * @return             boolean
54  */
55  this.capable = test_ajax_capability();
56 
57  /**
58  * switches debug mode on/off.
59  *
60  * @access   public
61  * @param    boolean    debug    debug flag
62  * @return   void
63  */
64  this.set_debug = function() {
65   
66    if (typeof arguments[0] == 'boolean') {
67      if (arguments[0] === true) {
68        config['debugging'] = 1;
69
70      } else {
71        config['debugging'] = 0;
72      }
73     
74    } else if (typeof arguments[0] == 'number') {
75      config['debugging'] = Math.round(arguments[0]);
76    }
77  }
78
79  /**
80  * defines the URL of the proxy script.
81  *
82  * @access   public
83  * @param    string    proxy_url    URL of the proxyscript to connect
84  * @return   void
85  */
86  this.set_proxy_url = function() {
87   
88    if (typeof arguments[0] == 'string') {
89
90      config['proxy_url'] = arguments[0];
91    }
92  }
93
94  /**
95  * sets the transfer_mode (GET|POST).
96  *
97  * @access   public
98  * @param    string    transfer_mode    transfer_mode
99  * @return   void
100  */
101  this.set_transfer_mode = function() {
102   
103    if (arguments[0].toUpperCase() == 'GET'
104      || arguments[0].toUpperCase() == 'POST') {
105
106      config['transfer_mode'] = arguments[0].toUpperCase();
107    }
108  }
109
110  /**
111  * sets the flag whether or not to use asynchronous calls.
112  *
113  * @access   public
114  * @param    boolean    async    syncronization flag
115  * @return   void
116  */
117  this.set_async = function() {
118   
119    if (typeof arguments[0] == 'boolean') {
120      config['async'] = arguments[0];
121    }
122  }
123
124  /**
125  * defines the response type.
126  *
127  * allowed values are:
128  *   TEXT    = raw text response
129  *   XML     = raw XMLHttpObject
130  *   OBJECT  = parsed JavaScript object structure from XMLHttpObject
131  *
132  * the default is OBJECT.
133  *
134  * @access   public
135  * @param    string    response_type    response type
136  * @return   void
137  */
138  this.set_response_type = function() {
139   
140    if (arguments[0].toUpperCase() == 'TEXT'
141      || arguments[0].toUpperCase() == 'XML'
142      || arguments[0].toUpperCase() == 'OBJECT'
143      || arguments[0].toUpperCase() == 'E4X'
144      || arguments[0].toUpperCase() == 'JSON') {
145
146      config['response_type'] = arguments[0].toUpperCase();
147    }
148  }
149
150  /**
151  * sets the flag whether or not to use a persistent connection.
152  *
153  * @access   public
154  * @param    boolean    persistent_connection    persistance flag
155  * @return   void
156  */
157  this.set_persistent_connection = function() {
158   
159    if (typeof arguments[0] == 'boolean') {
160      config['persistent_connection'] = arguments[0];
161    }
162  }
163 
164 
165  /**
166  * sets the flag whether or not to use the cpaint api on the backend.
167  *
168  * @access    public
169  * @param     boolean    cpaint_api      api_flag
170  * @return    void
171  */
172  this.set_use_cpaint_api = function() {
173    if (typeof arguments[0] == 'boolean') {
174      config['use_cpaint_api'] = arguments[0];
175    }
176  }
177 
178  /**
179  * tests whether one of the necessary implementations
180  * of the XMLHttpRequest class are available
181  *
182  * @access     protected
183  * @return     boolean
184  */
185  function test_ajax_capability() {
186    var cpc = new cpaint_call(0, config, this.version);
187    return cpc.test_ajax_capability();
188  }
189
190  /**
191  * takes the arguments supplied and triggers a call to the CPAINT backend
192  * based on the settings.
193  *
194  * upon response cpaint_call.callback() will automatically be called
195  * to perform post-processing operations.
196  *
197  * @access   public
198  * @param    string    url                 remote URL to call
199  * @param    string    remote_method       remote method to call
200  * @param    object    client_callback     client side callback method to deliver the remote response to. do NOT supply a string!
201  * @param    mixed     argN                remote parameters from now on
202  * @return   void
203  */
204  this.call = function() {
205    var use_stack = -1;
206   
207    if (config['persistent_connection'] == true
208      && __cpaint_stack[0] != null) {
209
210      switch (__cpaint_stack[0].get_http_state()) {
211        case -1:
212          // no XMLHttpObject object has already been instanciated
213          // create new object and configure it
214          use_stack = 0;
215          debug('no XMLHttpObject object to re-use for persistence, creating new one later', 2);
216          break;
217         
218        case 4:
219          // object is ready for a new request, no need to do anything
220          use_stack = 0
221          debug('re-using the persistent connection', 2);
222          break;
223         
224        default:
225          // connection is currently in use, don't do anything
226          debug('the persistent connection is in use - skipping this request', 2);
227      }
228     
229    } else if (config['persistent_connection'] == true) {
230      // persistent connection is active, but no object has been instanciated
231      use_stack = 0;
232      __cpaint_stack[use_stack] = new cpaint_call(use_stack, config, this.version);
233      debug('no cpaint_call object available for re-use, created new one', 2);
234   
235    } else {
236      // no connection persistance
237      use_stack = stack_count;
238      __cpaint_stack[use_stack] = new cpaint_call(use_stack, config, this.version);
239      debug('no cpaint_call object created new one', 2);
240    }
241
242    // configure cpaint_call if allowed to
243    if (use_stack != -1) {
244      __cpaint_stack[use_stack].set_client_callback(arguments[2]);
245     
246      // distribute according to proxy use
247      if (config['proxy_url'] != '') {
248        __cpaint_stack[use_stack].call_proxy(arguments);
249     
250      } else {
251        __cpaint_stack[use_stack].call_direct(arguments);
252      }
253
254      // increase stack counter
255      stack_count++;
256      debug('stack size: ' + __cpaint_stack.length, 2);
257    }
258  }
259
260  /**
261  * debug method
262  *
263  * @access  protected
264  * @param   string       message         the message to debug
265  * @param   integer      debug_level     debug level at which the message appears
266  * @return  void
267  */
268  var debug  = function(message, debug_level) {
269    var prefix = '[CPAINT Debug] ';
270   
271    if (debug_level < 1) {
272      prefix = '[CPAINT Error] ';
273    }
274   
275    if (config['debugging'] >= debug_level) {
276      alert(prefix + message);
277    }
278  }
279}
280
281/**
282* internal FIFO stack of cpaint_call() objects.
283*
284* @access   protected
285* @var      array    __cpaint_stack
286*/
287var __cpaint_stack = new Array();
288
289/**
290* local instance of cpaint_transformer
291* MSIE is unable to handle static classes... sheesh.
292*
293* @access   public
294* @var      object    __cpaint_transformer
295*/
296var __cpaint_transformer = new cpaint_transformer();
297
298/**
299* transport agent class
300*
301* creates the request object, takes care of the response, handles the
302* client callback. Is configured by the cpaint() object.
303*
304* @package      CPAINT
305* @access       public
306* @copyright    Copyright (c) 2005-2006 Paul Sullivan, Dominique Stender - http://sf.net/projects/cpaint
307* @author       Dominique Stender <dstender@st-webdevelopment.de>
308* @author       Paul Sullivan <wiley14@gmail.com>
309* @param        integer     stack_id      stack Id in cpaint
310* @param        array       config        configuration array for this call
311* @param        string      version       CPAINT API version
312*/
313function cpaint_call() {
314  /**
315  * CPAINT version
316  *
317  * @access     protected
318  * @var        string      version
319  */
320  var version = arguments[2];
321 
322  /**
323  * configuration options both for this class objects.
324  *
325  * @access     protected
326  * @var        array       config
327  */
328  var config                      = new Array();
329  config['debugging']             = arguments[1]['debugging'];
330  config['proxy_url']             = arguments[1]['proxy_url'];
331  config['transfer_mode']         = arguments[1]['transfer_mode'];
332  config['async']                 = arguments[1]['async'];
333  config['response_type']         = arguments[1]['response_type'];
334  config['persistent_connection'] = arguments[1]['persistent_connection'];
335  config['use_cpaint_api']        = arguments[1]['use_cpaint_api'];
336
337  /**
338  * XMLHttpObject used for this request.
339  *
340  * @access   protected
341  * @var      object     httpobj
342  */
343  var httpobj    = false;
344
345  /**
346  * client callback function.
347  *
348  * @access   public
349  * @var      function    client_callback
350  */
351  var client_callback;
352
353  /**
354  * stores the stack Id within the cpaint object
355  *
356  * @access   protected
357  * @var      stack_id
358  */
359  var stack_id = arguments[0];
360 
361  /**
362  * sets the client callback function.
363  *
364  * @access   public
365  * @param    function    client_callback     the client callback function
366  * @return   void
367  */
368  this.set_client_callback = function() {
369   
370    if (typeof arguments[0] == 'function') {
371      client_callback = arguments[0];
372    }
373  }
374
375  /**
376  * returns the ready state of the internal XMLHttpObject
377  *
378  * if no such object was set up already, -1 is returned
379  *
380  * @access     public
381  * @return     integer
382  */
383  this.get_http_state = function() {
384    var return_value = -1;
385   
386    if (typeof httpobj == 'object') {
387      return_value = httpobj.readyState;
388    }
389   
390    return return_value;
391  }
392 
393  /**
394  * internal method for remote calls to the local server without use of the proxy script.
395  *
396  * @access   public
397  * @param    array    call_arguments    array of arguments initially passed to cpaint.call()
398  * @return   void
399  */
400  this.call_direct = function(call_arguments) {
401    var url             = call_arguments[0];
402    var remote_method   = call_arguments[1];
403    var querystring     = '';
404    var i               = 0;
405   
406    // correct link to self
407    if (url == 'SELF') {
408      url = document.location.href;
409    }
410 
411    if (config['use_cpaint_api'] == true) {
412      // backend uses cpaint api
413      // pass parameters to remote method
414      for (i = 3; i < call_arguments.length; i++) {
415
416        if ((typeof call_arguments[i] == 'string'
417              && call_arguments[i] != ''
418              && call_arguments[i].search(/^\s+$/g) == -1)
419          && !isNaN(call_arguments[i])
420          && isFinite(call_arguments[i])) {
421          // numerical value, convert it first
422          querystring += '&cpaint_argument[]=' + encodeURIComponent(JSON.stringify(Number(call_arguments[i])));
423       
424        } else {
425          querystring += '&cpaint_argument[]=' + encodeURIComponent(JSON.stringify(call_arguments[i]));
426        }
427      }
428   
429      // add response type to querystring
430      querystring += '&cpaint_response_type=' + config['response_type'];
431   
432      // build header
433      if (config['transfer_mode'] == 'GET') {
434                               
435        if(url.indexOf('?') != -1) {
436                                        url = url + '&cpaint_function=' + remote_method +       querystring;
437                               
438        } else {
439                                        url = url + '?cpaint_function=' + remote_method +       querystring;
440                                }
441     
442      } else {
443        querystring = 'cpaint_function=' + remote_method + querystring;
444      }
445     
446    } else {
447      // backend does not use cpaint api
448      // pass parameters to remote method
449      for (i = 3; i < call_arguments.length; i++) {
450       
451        if (i == 3) {
452          querystring += encodeURIComponent(call_arguments[i]);
453       
454        } else {
455          querystring += '&' + encodeURIComponent(call_arguments[i]);
456        }
457      }
458   
459      // build header
460      if (config['transfer_mode'] == 'GET') {
461        url = url + querystring;
462      }
463    }
464 
465    // open connection
466    get_connection_object();
467
468    // open connection to remote target
469    debug('opening connection to "' + url + '"', 1);
470    httpobj.open(config['transfer_mode'], url, config['async']);
471
472    // send "urlencoded" header if necessary (if POST)
473    if (config['transfer_mode'] == 'POST') {
474
475      try {
476        httpobj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
477
478      } catch (cp_err) {
479        debug('POST cannot be completed due to incompatible browser.  Use GET as your request method.', 0);
480      }
481    }
482
483    // make ourselves known
484    httpobj.setRequestHeader('X-Powered-By', 'CPAINT v' + version + ' :: http://sf.net/projects/cpaint');
485
486    // callback handling for asynchronous calls
487    httpobj.onreadystatechange = callback;
488
489    // send content
490    if (config['transfer_mode'] == 'GET') {
491      httpobj.send(null);
492
493    } else {
494      debug('sending query: ' + querystring, 1);
495      httpobj.send(querystring);
496    }
497
498    if (config['async'] == true) {
499      // manual callback handling for synchronized calls
500      callback();
501    }
502  }
503   
504  /**
505  * internal method for calls to remote servers through the proxy script.
506  *
507  * @access   public
508  * @param    array    call_arguments    array of arguments passed to cpaint.call()
509  * @return   void
510  */
511  this.call_proxy = function(call_arguments) {
512    var proxyscript     = config['proxy_url'];
513    var url             = call_arguments[0];
514    var remote_method   = call_arguments[1];
515    var querystring     = '';
516    var i               = 0;
517   
518    var querystring_argument_prefix = 'cpaint_argument[]=';
519
520    // pass parameters to remote method
521    if (config['use_cpaint_api'] == false) {
522      // when not talking to a CPAINT backend, don't prefix arguments
523      querystring_argument_prefix = '';
524    }
525
526    for (i = 3; i < call_arguments.length; i++) {
527
528      if (config['use_cpaint_api'] == true) {
529     
530        if ((typeof call_arguments[i] == 'string'
531              && call_arguments[i] != ''
532              && call_arguments[i].search(/^\s+$/g) == -1)
533          && !isNaN(call_arguments[i])
534          && isFinite(call_arguments[i])) {
535          // numerical value, convert it first
536          querystring += encodeURIComponent(querystring_argument_prefix + JSON.stringify(Number(call_arguments[i])) + '&');
537
538        } else {
539          querystring += encodeURIComponent(querystring_argument_prefix + JSON.stringify(call_arguments[i]) + '&');
540        }
541       
542      } else {
543        // no CPAINT in the backend
544        querystring += encodeURIComponent(querystring_argument_prefix + call_arguments[i] + '&');
545      }
546    }
547
548    if (config['use_cpaint_api'] == true) {
549      // add remote function name to querystring
550      querystring += encodeURIComponent('&cpaint_function=' + remote_method);
551 
552      // add response type to querystring
553      querystring += encodeURIComponent('&cpaint_responsetype=' + config['response_type']);
554    }
555   
556    // build header
557    if (config['transfer_mode'] == 'GET') {
558      proxyscript += '?cpaint_remote_url=' + encodeURIComponent(url)
559        + '&cpaint_remote_query=' + querystring
560        + '&cpaint_remote_method=' + config['transfer_mode']
561        + '&cpaint_response_type=' + config['response_type'];
562
563    } else {
564      querystring = 'cpaint_remote_url=' + encodeURIComponent(url)
565        + '&cpaint_remote_query=' + querystring
566        + '&cpaint_remote_method=' + config['transfer_mode']
567        + '&cpaint_response_type=' + config['response_type'];
568    }
569
570    // open connection
571    get_connection_object();
572
573    // open connection to remote target
574    debug('opening connection to proxy "' + proxyscript + '"', 1);
575    httpobj.open(config['transfer_mode'], proxyscript, config['async']);
576
577    // send "urlencoded" header if necessary (if POST)
578    if (config['transfer_mode'] == 'POST') {
579
580      try {
581        httpobj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
582
583      } catch (cp_err) {
584        debug('POST cannot be completed due to incompatible browser.  Use GET as your request method.', 0);
585      }
586    }
587
588    httpobj.setRequestHeader('X-Powered-By', 'CPAINT v' + version);
589
590    // callback handling for asynchronous calls
591    httpobj.onreadystatechange = callback;
592
593    // send content
594    if (config['transfer_mode'] == 'GET') {
595      httpobj.send(null);
596
597    } else {
598      debug('sending query: ' + querystring, 1);
599      httpobj.send(querystring);
600    }
601
602    if (config['async'] == false) {
603      // manual callback handling for synchronized calls
604      callback();
605    }
606  }
607
608  this.test_ajax_capability = function() {
609    return get_connection_object();
610  }
611 
612  /**
613  * creates a new connection object.
614  *
615  * @access   protected
616  * @return   boolean
617  */
618  var get_connection_object = function() {
619    var return_value    = false;
620    var new_connection  = false;
621
622    // open new connection only if necessary
623    if (config['persistent_connection'] == false) {
624      // no persistance, create a new object every time
625      debug('Using new connection object', 1);
626      new_connection = true;
627
628    } else {
629      // persistent connection object, only open one if no object exists
630      debug('Using shared connection object.', 1);
631
632      if (typeof httpobj != 'object') {
633        debug('Getting new persistent connection object.', 1);
634        new_connection = true;
635      }
636    }
637
638    if (new_connection == true) {
639      try {
640        httpobj = new ActiveXObject('Msxml2.XMLHTTP');
641 
642      } catch (e) {
643       
644        try { 
645          httpobj = new ActiveXObject('Microsoft.XMLHTTP');
646 
647        } catch (oc) {
648          httpobj = null;
649        }
650      }
651 
652      if (!httpobj && typeof XMLHttpRequest != 'undefined') {
653        httpobj = new XMLHttpRequest();
654      }
655 
656      if (!httpobj) {
657        debug('Could not create connection object', 0);
658     
659      } else {
660        return_value = true;
661      }
662    }
663
664    if (httpobj.readyState != 4) {
665      httpobj.abort();
666    }
667
668    return return_value;
669  }
670
671  /**
672  * internal callback function.
673  *
674  * will perform some consistency checks (response code, NULL value testing)
675  * and if response_type = 'OBJECT' it will automatically call
676  * cpaint_call.parse_ajax_xml() to have a JavaScript object structure generated.
677  *
678  * after all that is done the client side callback function will be called
679  * with the generated response as single value.
680  *
681  * @access   protected
682  * @return   void
683  */
684  var callback = function() {
685    var response = null;
686
687    if (httpobj.readyState == 4
688      && httpobj.status == 200) {
689     
690      debug(httpobj.responseText, 1);
691      debug('using response type ' + config['response_type'], 2);
692     
693      // fetch correct response
694      switch (config['response_type']) {
695        case 'XML':
696          debug(httpobj.responseXML, 2);
697          response = __cpaint_transformer.xml_conversion(httpobj.responseXML);
698          break;
699         
700        case 'OBJECT':
701          response = __cpaint_transformer.object_conversion(httpobj.responseXML);
702          break;
703       
704        case 'TEXT':
705          response = __cpaint_transformer.text_conversion(httpobj.responseText);
706          break;
707         
708        case 'E4X':
709          response = __cpaint_transformer.e4x_conversion(httpobj.responseText);
710          break;
711         
712        case 'JSON':
713          response = __cpaint_transformer.json_conversion(httpobj.responseText);
714          break;
715         
716        default:
717          debug('invalid response type \'' + response_type + '\'', 0);
718      }
719     
720      // call client side callback
721      if (response != null
722        && typeof client_callback == 'function') {
723        client_callback(response, httpobj.responseText);
724      }
725     
726      // remove ourselves from the stack
727      remove_from_stack();
728   
729    } else if (httpobj.readyState == 4
730      && httpobj.status != 200) {
731      // HTTP error of some kind
732      debug('invalid HTTP response code \'' + Number(httpobj.status) + '\'', 0);
733    }
734  }
735
736  /**
737  * removes an entry from the stack
738  *
739  * @access     protected
740  * @return     void
741  */
742  var remove_from_stack = function() {
743    // remove only if everything is okay and we're not configured as persistent connection
744    if (typeof stack_id == 'number'
745      && __cpaint_stack[stack_id]
746      && config['persistent_connection'] == false) {
747     
748      __cpaint_stack[stack_id] = null;
749    }
750  }
751
752  /**
753  * debug method
754  *
755  * @access  protected
756  * @param   string       message         the message to debug
757  * @param   integer      debug_level     debug level at which the message appears
758  * @return  void
759  */
760  var debug  = function(message, debug_level) {
761    var prefix = '[CPAINT Debug] ';
762   
763    if (config['debugging'] < 1) {
764      prefix = '[CPAINT Error] ';
765    }
766   
767    if (config['debugging'] >= debug_level) {
768      alert(prefix + message);
769    }
770  }
771}
772
773/**
774* CPAINT transformation object
775*
776* @package      CPAINT
777* @access       public
778* @copyright    Copyright (c) 2005-2006 Paul Sullivan, Dominique Stender - http://sf.net/projects/cpaint
779* @author       Paul Sullivan <wiley14@gmail.com>
780* @author       Dominique Stender <dstender@st-webdevelopment.de>
781*/
782function cpaint_transformer() {
783
784  /**
785  * will take a XMLHttpObject and generate a JavaScript
786  * object structure from it.
787  *
788  * is internally called by cpaint_call.callback() if necessary.
789  * will call cpaint_call.create_object_structure() to create nested object structures.
790  *
791  * @access   public
792  * @param    object    xml_document  a XMLHttpObject
793  * @return   object
794  */
795  this.object_conversion = function(xml_document) {
796    var return_value  = new cpaint_result_object();
797    var i             = 0;
798    var firstNodeName = '';
799   
800    if (typeof xml_document == 'object'
801      && xml_document != null) {
802
803      // find the first element node - for MSIE the <?xml?> node is the very first...
804      for (i = 0; i < xml_document.childNodes.length; i++) {
805
806        if (xml_document.childNodes[i].nodeType == 1) {
807          firstNodeName = xml_document.childNodes[i].nodeName;
808          break;
809        }
810      }
811     
812      var ajax_response = xml_document.getElementsByTagName(firstNodeName);
813
814      return_value[firstNodeName] = new Array();
815   
816      for (i = 0; i < ajax_response.length; i++) {
817        var tmp_node = create_object_structure(ajax_response[i]);
818        tmp_node.id  = ajax_response[i].getAttribute('id')
819        return_value[firstNodeName].push(tmp_node);
820      }
821
822    } else {
823      debug('received invalid XML response', 0);
824    }
825
826    return return_value;
827  }
828
829  /**
830  * performs the necessary conversions for the XML response type
831  *
832  * @access   public
833  * @param    object    xml_document  a XMLHttpObject
834  * @return   object
835  */
836  this.xml_conversion = function(xml_document) {
837    return xml_document;
838  }
839 
840  /**
841  * performs the necessary conversions for the TEXT response type
842  *
843  * @access   public
844  * @param    string    text  the response text
845  * @return   string
846  */
847  this.text_conversion = function(text) {
848    return decode(text);
849  }
850 
851  /**
852  * performs the necessary conversions for the E4X response type
853  *
854  * @access   public
855  * @param    string    text  the response text
856  * @return   string
857  */
858  this.e4x_conversion = function(text) {
859    // remove <?xml ?>tag
860    text = text.replace(/^\<\?xml[^>]+\>/, '');
861    return new XML(text);
862  }
863 
864  /**
865  * performs the necessary conversions for the JSON response type
866  *
867  * @access   public
868  * @param    string    text  the response text
869  * @return   string
870  */
871  this.json_conversion = function(text) {
872    return JSON.parse(text);
873  }
874 
875  /**
876  * this method takes a HTML / XML node object and creates a
877  * JavaScript object structure from it.
878  *
879  * @access   public
880  * @param    object    stream    a node in the XML structure
881  * @return   object
882  */
883  var create_object_structure = function(stream) {
884    var return_value = new cpaint_result_object();
885    var node_name = '';
886    var i         = 0;
887    var attrib    = 0;
888   
889    if (stream.hasChildNodes() == true) {
890      for (i = 0; i < stream.childNodes.length; i++) {
891 
892        node_name = stream.childNodes[i].nodeName;
893        node_name = node_name.replace(/[^a-zA-Z0-9_]*/g, '');
894       
895        // reset / create subnode
896        if (typeof return_value[node_name] != 'object') {
897          return_value[node_name] = new Array();
898        }
899       
900        if (stream.childNodes[i].nodeType == 1) {
901          var tmp_node  = create_object_structure(stream.childNodes[i]);
902
903          for (attrib = 0; attrib < stream.childNodes[i].attributes.length; attrib++) {
904            tmp_node.set_attribute(stream.childNodes[i].attributes[attrib].nodeName, stream.childNodes[i].attributes[attrib].nodeValue);
905          }
906         
907          return_value[node_name].push(tmp_node);
908       
909        } else if (stream.childNodes[i].nodeType == 3) {
910          return_value.data  = decode(String(stream.firstChild.data));
911        }
912      }
913    }
914   
915    return return_value;
916  }
917
918  /**
919  * converts an encoded text back to viewable characters.
920  *
921  * @access     public
922  * @param      string      rawtext     raw text as provided by the backend
923  * @return     mixed
924  */
925  var decode = function(rawtext) {
926    var plaintext = '';
927    var i         = 0;
928    var c1        = 0;
929    var c2        = 0;
930    var c3        = 0;
931    var u         = 0;
932    var t         = 0;
933
934    // remove special JavaScript encoded non-printable characters
935    while (i < rawtext.length) {
936      if (rawtext.charAt(i) == '\\'
937        && rawtext.charAt(i + 1) == 'u') {
938       
939        u = 0;
940       
941        for (j = 2; j < 6; j += 1) {
942          t = parseInt(rawtext.charAt(i + j), 16);
943         
944          if (!isFinite(t)) {
945            break;
946          }
947          u = u * 16 + t;
948        }
949
950        plaintext += String.fromCharCode(u);
951        i       += 6;
952     
953      } else {
954        plaintext += rawtext.charAt(i);
955        i++;
956      }
957    }
958
959    // convert numeric data to number type
960    if (plaintext != ''
961      && plaintext.search(/^\s+$/g) == -1
962      && !isNaN(plaintext)
963      && isFinite(plaintext)) {
964     
965      plaintext = Number(plaintext);
966    }
967 
968    return plaintext;
969  }
970}
971
972/**
973* this is the basic prototype for a cpaint node object
974* as used in cpaint_call.parse_ajax_xml()
975*
976* @package      CPAINT
977* @access       public
978* @copyright    Copyright (c) 2005-2006 Paul Sullivan, Dominique Stender - http://sf.net/projects/cpaint
979* @author       Paul Sullivan <wiley14@gmail.com>
980* @author       Dominique Stender <dstender@st-webdevelopment.de>
981*/
982function cpaint_result_object() {
983  this.id           = 0;
984  this.data         = '';
985  var __attributes  = new Array();
986 
987  /**
988  * Returns a subnode with the given type and id.
989  *
990  * @access     public
991  * @param      string    type    The type of the subnode. Equivalent to the XML tag name.
992  * @param      string    id      The id of the subnode. Equivalent to the XML tag names id attribute.
993  * @return     object
994  */
995  this.find_item_by_id = function() {
996    var return_value  = null;
997    var type    = arguments[0];
998    var id      = arguments[1];
999    var i       = 0;
1000   
1001    if (this[type]) {
1002
1003      for (i = 0; i < this[type].length; i++) {
1004
1005        if (this[type][i].get_attribute('id') == id) {
1006          return_value = this[type][i];
1007          break;
1008        }
1009      }
1010    }
1011
1012    return return_value;
1013  }
1014 
1015  /**
1016  * retrieves the value of an attribute.
1017  *
1018  * @access   public
1019  * @param    string    name    name of the attribute
1020  * @return   mixed
1021  */
1022  this.get_attribute = function() {
1023    var return_value  = null;
1024    var id            = arguments[0];
1025   
1026    if (typeof __attributes[id] != 'undefined') {
1027      return_value = __attributes[id];
1028    }
1029   
1030    return return_value;
1031  }
1032 
1033  /**
1034  * assigns a value to an attribute.
1035  *
1036  * if that attribute does not exist it will be created.
1037  *
1038  * @access     public
1039  * @param      string    name    name of the attribute
1040  * @param      string    value   value of the attribute
1041  * @return     void
1042  */
1043  this.set_attribute = function() {
1044    __attributes[arguments[0]] = arguments[1];
1045  }
1046}
1047
1048
1049/*
1050Copyright (c) 2005 JSON.org
1051
1052Permission is hereby granted, free of charge, to any person obtaining a copy
1053of this software and associated documentation files (the "Software"), to deal
1054in the Software without restriction, including without limitation the rights
1055to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1056copies of the Software, and to permit persons to whom the Software is
1057furnished to do so, subject to the following conditions:
1058
1059The Software shall be used for Good, not Evil.
1060
1061THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1062IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1063FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1064AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1065LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1066OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1067SOFTWARE.
1068*/
1069
1070Array.prototype.______array = '______array';
1071
1072var JSON = {
1073  org: 'http://www.JSON.org',
1074  copyright: '(c)2005 JSON.org',
1075  license: 'http://www.crockford.com/JSON/license.html',
1076
1077  stringify: function (arg) {
1078    var c, i, l, s = '', v;
1079    var numeric = true;
1080   
1081    switch (typeof arg) {
1082    case 'object':
1083      if (arg) {
1084        if (arg.______array == '______array') {
1085          // do a test whether all array keys are numeric
1086          for (i in arg) {
1087            if (i != '______array'
1088              && (isNaN(i)
1089                || !isFinite(i))) {
1090              numeric = false;
1091              break;
1092            }
1093          }
1094         
1095          if (numeric == true) {
1096            for (i = 0; i < arg.length; ++i) {
1097              if (typeof arg[i] != 'undefined') {
1098                v = this.stringify(arg[i]);
1099                if (s) {
1100                  s += ',';
1101                }
1102                s += v;
1103              } else {
1104                s += ',null';
1105              }
1106            }
1107            return '[' + s + ']';
1108          } else {
1109            for (i in arg) {
1110              if (i != '______array') {
1111                v = arg[i];
1112                if (typeof v != 'undefined' && typeof v != 'function') {
1113                  v = this.stringify(v);
1114                  if (s) {
1115                    s += ',';
1116                  }
1117                  s += this.stringify(i) + ':' + v;
1118                }
1119              }
1120            }
1121            // return as object
1122            return '{' + s + '}';
1123          }
1124        } else if (typeof arg.toString != 'undefined') {
1125          for (i in arg) {
1126            v = arg[i];
1127            if (typeof v != 'undefined' && typeof v != 'function') {
1128              v = this.stringify(v);
1129              if (s) {
1130                s += ',';
1131              }
1132              s += this.stringify(i) + ':' + v;
1133            }
1134          }
1135          return '{' + s + '}';
1136        }
1137      }
1138      return 'null';
1139    case 'number':
1140      return isFinite(arg) ? String(arg) : 'null';
1141    case 'string':
1142      l = arg.length;
1143      s = '"';
1144      for (i = 0; i < l; i += 1) {
1145        c = arg.charAt(i);
1146        if (c >= ' ') {
1147          if (c == '\\' || c == '"') {
1148            s += '\\';
1149          }
1150          s += c;
1151        } else {
1152          switch (c) {
1153            case '\b':
1154              s += '\\b';
1155              break;
1156            case '\f':
1157              s += '\\f';
1158              break;
1159            case '\n':
1160              s += '\\n';
1161              break;
1162            case '\r':
1163              s += '\\r';
1164              break;
1165            case '\t':
1166              s += '\\t';
1167              break;
1168            default:
1169              c = c.charCodeAt();
1170              s += '\\u00' + Math.floor(c / 16).toString(16) +
1171                (c % 16).toString(16);
1172          }
1173        }
1174      }
1175      return s + '"';
1176    case 'boolean':
1177      return String(arg);
1178    default:
1179      return 'null';
1180    }
1181  },
1182  parse: function (text) {
1183    var at = 0;
1184    var ch = ' ';
1185
1186    function error(m) {
1187      throw {
1188        name: 'JSONError',
1189        message: m,
1190        at: at - 1,
1191        text: text
1192      };
1193    }
1194
1195    function next() {
1196      ch = text.charAt(at);
1197      at += 1;
1198      return ch;
1199    }
1200
1201    function white() {
1202      while (ch != '' && ch <= ' ') {
1203        next();
1204      }
1205    }
1206
1207    function str() {
1208      var i, s = '', t, u;
1209
1210      if (ch == '"') {
1211outer:      while (next()) {
1212          if (ch == '"') {
1213            next();
1214            return s;
1215          } else if (ch == '\\') {
1216            switch (next()) {
1217            case 'b':
1218              s += '\b';
1219              break;
1220            case 'f':
1221              s += '\f';
1222              break;
1223            case 'n':
1224              s += '\n';
1225              break;
1226            case 'r':
1227              s += '\r';
1228              break;
1229            case 't':
1230              s += '\t';
1231              break;
1232            case 'u':
1233              u = 0;
1234              for (i = 0; i < 4; i += 1) {
1235                t = parseInt(next(), 16);
1236                if (!isFinite(t)) {
1237                  break outer;
1238                }
1239                u = u * 16 + t;
1240              }
1241              s += String.fromCharCode(u);
1242              break;
1243            default:
1244              s += ch;
1245            }
1246          } else {
1247            s += ch;
1248          }
1249        }
1250      }
1251      error("Bad string");
1252    }
1253
1254    function arr() {
1255      var a = [];
1256
1257      if (ch == '[') {
1258        next();
1259        white();
1260        if (ch == ']') {
1261          next();
1262          return a;
1263        }
1264        while (ch) {
1265          a.push(val());
1266          white();
1267          if (ch == ']') {
1268            next();
1269            return a;
1270          } else if (ch != ',') {
1271            break;
1272          }
1273          next();
1274          white();
1275        }
1276      }
1277      error("Bad array");
1278    }
1279
1280    function obj() {
1281      var k, o = {};
1282
1283      if (ch == '{') {
1284        next();
1285        white();
1286        if (ch == '}') {
1287          next();
1288          return o;
1289        }
1290        while (ch) {
1291          k = str();
1292          white();
1293          if (ch != ':') {
1294            break;
1295          }
1296          next();
1297          o[k] = val();
1298          white();
1299          if (ch == '}') {
1300            next();
1301            return o;
1302          } else if (ch != ',') {
1303            break;
1304          }
1305          next();
1306          white();
1307        }
1308      }
1309      error("Bad object");
1310    }
1311
1312    function assoc() {
1313      var k, a = [];
1314
1315      if (ch == '<') {
1316        next();
1317        white();
1318        if (ch == '>') {
1319          next();
1320          return a;
1321        }
1322        while (ch) {
1323          k = str();
1324          white();
1325          if (ch != ':') {
1326            break;
1327          }
1328          next();
1329          a[k] = val();
1330          white();
1331          if (ch == '>') {
1332            next();
1333            return a;
1334          } else if (ch != ',') {
1335            break;
1336          }
1337          next();
1338          white();
1339        }
1340      }
1341      error("Bad associative array");
1342    }
1343
1344    function num() {
1345      var n = '', v;
1346      if (ch == '-') {
1347        n = '-';
1348        next();
1349      }
1350      while (ch >= '0' && ch <= '9') {
1351        n += ch;
1352        next();
1353      }
1354      if (ch == '.') {
1355        n += '.';
1356        while (next() && ch >= '0' && ch <= '9') {
1357          n += ch;
1358        }
1359      }
1360      if (ch == 'e' || ch == 'E') {
1361        n += 'e';
1362        next();
1363        if (ch == '-' || ch == '+') {
1364          n += ch;
1365          next();
1366        }
1367        while (ch >= '0' && ch <= '9') {
1368          n += ch;
1369          next();
1370        }
1371      }
1372      v = +n;
1373      if (!isFinite(v)) {
1374        error("Bad number");
1375      } else {
1376        return v;
1377      }
1378    }
1379
1380    function word() {
1381      switch (ch) {
1382        case 't':
1383          if (next() == 'r' && next() == 'u' && next() == 'e') {
1384            next();
1385            return true;
1386          }
1387          break;
1388        case 'f':
1389          if (next() == 'a' && next() == 'l' && next() == 's' &&
1390              next() == 'e') {
1391            next();
1392            return false;
1393          }
1394          break;
1395        case 'n':
1396          if (next() == 'u' && next() == 'l' && next() == 'l') {
1397            next();
1398            return null;
1399          }
1400          break;
1401      }
1402      error("Syntax error");
1403    }
1404
1405    function val() {
1406      white();
1407      switch (ch) {
1408        case '{':
1409          return obj();
1410        case '[':
1411          return arr();
1412        case '<':
1413          return assoc();
1414        case '"':
1415          return str();
1416        case '-':
1417          return num();
1418        default:
1419          return ch >= '0' && ch <= '9' ? num() : word();
1420      }
1421    }
1422
1423    return val();
1424  }
1425};
Note: See TracBrowser for help on using the repository browser.