3 ' Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
\r
4 ' For licensing, see LICENSE.html or http://ckeditor.com/license
\r
6 ' Shared variable for all instances ("static")
\r
7 dim CKEDITOR_initComplete
\r
8 dim CKEDITOR_returnedEvents
\r
11 ' \brief CKEditor class that can be used to create editor
\r
12 ' instances in ASP pages on server side.
\r
13 ' @see http://ckeditor.com
\r
17 ' editor = new CKEditor
\r
18 ' editor.editor "editor1", "<p>Initial value.</p>", empty, empty
\r
24 ' The version of %CKEditor.
\r
28 ' A constant string unique for each release of %CKEditor.
\r
32 ' URL to the %CKEditor installation directory (absolute or relative to document root).
\r
33 ' If not set, CKEditor will try to guess it's path.
\r
37 ' editor.basePath = "/ckeditor/"
\r
42 ' A boolean variable indicating whether CKEditor has been initialized.
\r
43 ' Set it to true only if you have already included
\r
44 ' <script> tag loading ckeditor.js in your website.
\r
48 ' Boolean variable indicating whether created code should be printed out or returned by a function.
\r
50 ' Example 1: get the code creating %CKEditor instance and print it on a page with the "echo" function.
\r
52 ' editor = new CKEditor
\r
53 ' editor.returnOutput = true
\r
54 ' code = editor.editor("editor1", "<p>Initial value.</p>", empty, empty)
\r
55 ' response.write "<p>Editor 1:</p>"
\r
56 ' response.write code
\r
61 ' A Dictionary with textarea attributes.
\r
63 ' When %CKEditor is created with the editor() method, a HTML <textarea> element is created,
\r
64 ' it will be displayed to anyone with JavaScript disabled or with incompatible browser.
\r
65 public textareaAttributes
\r
68 ' A string indicating the creation date of %CKEditor.
\r
69 ' Do not change it unless you want to force browsers to not use previously cached version of %CKEditor.
\r
73 ' A dictionary that holds the instance configuration.
\r
74 private oInstanceConfig
\r
77 ' A dictionary that holds the configuration for all the instances.
\r
78 private oAllInstancesConfig
\r
81 ' A dictionary that holds event listeners for the instance.
\r
82 private oInstanceEvents
\r
85 ' A dictionary that holds event listeners for all the instances.
\r
86 private oAllInstancesEvents
\r
89 ' A Dictionary that holds global event listeners (CKEDITOR object)
\r
90 private oGlobalEvents
\r
93 Private Sub Class_Initialize()
\r
95 timeStamp = "B49D5BN"
\r
96 mTimeStamp = "B49D5BN"
\r
98 Set oInstanceConfig = CreateObject("Scripting.Dictionary")
\r
99 Set oAllInstancesConfig = CreateObject("Scripting.Dictionary")
\r
101 Set oInstanceEvents = CreateObject("Scripting.Dictionary")
\r
102 Set oAllInstancesEvents = CreateObject("Scripting.Dictionary")
\r
103 Set oGlobalEvents = CreateObject("Scripting.Dictionary")
\r
105 Set textareaAttributes = CreateObject("Scripting.Dictionary")
\r
106 textareaAttributes.Add "rows", 8
\r
107 textareaAttributes.Add "cols", 60
\r
111 ' Creates a %CKEditor instance.
\r
112 ' In incompatible browsers %CKEditor will downgrade to plain HTML <textarea> element.
\r
114 ' @param name (string) Name of the %CKEditor instance (this will be also the "name" attribute of textarea element).
\r
115 ' @param value (string) Initial value.
\r
119 ' set editor = New CKEditor
\r
120 ' editor.editor "field1", "<p>Initial value.</p>"
\r
123 ' Advanced example:
\r
125 ' set editor = new CKEditor
\r
126 ' set config = CreateObject("Scripting.Dictionary")
\r
127 ' config.Add "toolbar", Array( _
\r
128 ' Array( "Source", "-", "Bold", "Italic", "Underline", "Strike" ), _
\r
129 ' Array( "Image", "Link", "Unlink", "Anchor" ) _
\r
131 ' set events = CreateObject("Scripting.Dictionary")
\r
132 ' events.Add "instanceReady", "function (evt) { alert('Loaded second editor: ' + evt.editor.name );}"
\r
134 ' editor.editor "field1", "<p>Initial value.</p>", config, events
\r
137 public function editor(name, value)
\r
138 dim attr, out, js, customConfig, extraConfig
\r
143 for each attribute in textareaAttributes
\r
144 attr = attr & " " & attribute & "=""" & replace( textareaAttributes( attribute ), """", """ ) & """"
\r
147 out = "<textarea name=""" & name & """" & attr & ">" & Server.HtmlEncode(value) & "</textarea>" & vbcrlf
\r
149 if not(initialized) then
\r
153 set customConfig = configSettings()
\r
154 js = returnGlobalEvents()
\r
156 extraConfig = (new JSON)( empty, customConfig, false )
\r
157 if extraConfig<>"" then extraConfig = ", " & extraConfig
\r
158 js = js & "CKEDITOR.replace('" & name & "'" & extraConfig & ");"
\r
160 out = out & script(js)
\r
162 if not(returnOutput) then
\r
169 oInstanceConfig.RemoveAll
\r
170 oInstanceEvents.RemoveAll
\r
174 ' Replaces a <textarea> with a %CKEditor instance.
\r
176 ' @param id (string) The id or name of textarea element.
\r
178 ' Example 1: adding %CKEditor to <textarea name="article"></textarea> element:
\r
180 ' set editor = New CKEditor
\r
181 ' editor.replace "article"
\r
184 public function replaceInstance(id)
\r
185 dim out, js, customConfig, extraConfig
\r
188 if not(initialized) then
\r
192 set customConfig = configSettings()
\r
193 js = returnGlobalEvents()
\r
195 extraConfig = (new JSON)( empty, customConfig, false )
\r
196 if extraConfig<>"" then extraConfig = ", " & extraConfig
\r
197 js = js & "CKEDITOR.replace('" & id & "'" & extraConfig & ");"
\r
199 out = out & script(js)
\r
201 if not(returnOutput) then
\r
206 replaceInstance = out
\r
208 oInstanceConfig.RemoveAll
\r
209 oInstanceEvents.RemoveAll
\r
213 ' Replace all <textarea> elements available in the document with editor instances.
\r
215 ' @param className (string) If set, replace all textareas with class className in the page.
\r
217 ' Example 1: replace all <textarea> elements in the page.
\r
219 ' editor = new CKEditor
\r
220 ' editor.replaceAll empty
\r
223 ' Example 2: replace all <textarea class="myClassName"> elements in the page.
\r
225 ' editor = new CKEditor
\r
226 ' editor.replaceAll 'myClassName'
\r
229 function replaceAll(className)
\r
230 dim out, js, customConfig
\r
233 if not(initialized) then
\r
237 set customConfig = configSettings()
\r
238 js = returnGlobalEvents()
\r
240 if (customConfig.Count=0) then
\r
241 if (isEmpty(className)) then
\r
242 js = js & "CKEDITOR.replaceAll();"
\r
244 js = js & "CKEDITOR.replaceAll('" & className & "');"
\r
247 js = js & "CKEDITOR.replaceAll( function(textarea, config) {\n"
\r
248 if not(isEmpty(className)) then
\r
249 js = js & " var classRegex = new RegExp('(?:^| )' + '" & className & "' + '(?:$| )');\n"
\r
250 js = js & " if (!classRegex.test(textarea.className))\n"
\r
251 js = js & " return false;\n"
\r
253 js = js & " CKEDITOR.tools.extend(config, " & (new JSON)( empty, customConfig, false ) & ", true);"
\r
257 out = out & script(js)
\r
259 if not(returnOutput) then
\r
266 oInstanceConfig.RemoveAll
\r
267 oInstanceEvents.RemoveAll
\r
272 ' A Dictionary that holds the %CKEditor configuration for all instances
\r
273 ' For the list of available options, see http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.config.html
\r
277 ' editor.config("height") = 400
\r
278 ' // Use @@ at the beggining of a string to ouput it without surrounding quotes.
\r
279 ' editor.config("width") = "@@screen.width * 0.8"
\r
281 Public Property Let Config( configKey, configValue )
\r
282 oAllInstancesConfig.Add configKey, configValue
\r
286 ' Configuration options for the next instance
\r
288 Public Property Let instanceConfig( configKey, configValue )
\r
289 oInstanceConfig.Add configKey, configValue
\r
293 ' Adds event listener.
\r
294 ' Events are fired by %CKEditor in various situations.
\r
296 ' @param eventName (string) Event name.
\r
297 ' @param javascriptCode (string) Javascript anonymous function or function name.
\r
301 ' editor.addEventHandler "instanceReady", "function (ev) { " & _
\r
302 ' " alert('Loaded: ' + ev.editor.name); " & _
\r
306 public sub addEventHandler(eventName, javascriptCode)
\r
307 if not(oAllInstancesEvents.Exists( eventName ) ) then
\r
308 oAllInstancesEvents.Add eventName, Array()
\r
311 dim listeners, size
\r
312 listeners = oAllInstancesEvents( eventName )
\r
313 size = ubound(listeners) + 1
\r
314 redim preserve listeners(size)
\r
315 listeners(size) = javascriptCode
\r
317 oAllInstancesEvents( eventName ) = listeners
\r
318 ' '' Avoid duplicates. fixme...
\r
319 ' if (!in_array($javascriptCode, $this->_events[$event])) {
\r
320 ' $this->_events[$event][] = $javascriptCode;
\r
325 ' Clear registered event handlers.
\r
326 ' Note: this function will have no effect on already created editor instances.
\r
328 ' @param eventName (string) Event name, if set to 'empty' all event handlers will be removed.
\r
330 public sub clearEventHandlers( eventName )
\r
331 if not(isEmpty( eventName )) then
\r
332 oAllInstancesEvents.Remove eventName
\r
334 oAllInstancesEvents.RemoveAll
\r
340 ' Adds event listener only for the next instance.
\r
341 ' Events are fired by %CKEditor in various situations.
\r
343 ' @param eventName (string) Event name.
\r
344 ' @param javascriptCode (string) Javascript anonymous function or function name.
\r
348 ' editor.addInstanceEventHandler "instanceReady", "function (ev) { " & _
\r
349 ' " alert('Loaded: ' + ev.editor.name); " & _
\r
353 public sub addInstanceEventHandler(eventName, javascriptCode)
\r
354 if not(oInstanceEvents.Exists( eventName ) ) then
\r
355 oInstanceEvents.Add eventName, Array()
\r
358 dim listeners, size
\r
359 listeners = oInstanceEvents( eventName )
\r
360 size = ubound(listeners) + 1
\r
361 redim preserve listeners(size)
\r
362 listeners(size) = javascriptCode
\r
364 oInstanceEvents( eventName ) = listeners
\r
365 ' '' Avoid duplicates. fixme...
\r
366 ' if (!in_array($javascriptCode, $this->_events[$event])) {
\r
367 ' $this->_events[$event][] = $javascriptCode;
\r
372 ' Clear registered event handlers.
\r
373 ' Note: this function will have no effect on already created editor instances.
\r
375 ' @param eventName (string) Event name, if set to 'empty' all event handlers will be removed.
\r
377 public sub clearInstanceEventHandlers( eventName )
\r
378 if not(isEmpty( eventName )) then
\r
379 oInstanceEvents.Remove eventName
\r
381 oInstanceEvents.RemoveAll
\r
386 ' Adds global event listener.
\r
388 ' @param event (string) Event name.
\r
389 ' @param javascriptCode (string) Javascript anonymous function or function name.
\r
393 ' editor.addGlobalEventHandler "dialogDefinition", "function (ev) { " & _
\r
394 ' " alert('Loading dialog: ' + ev.data.name); " & _
\r
398 public sub addGlobalEventHandler( eventName, javascriptCode)
\r
399 if not(oGlobalEvents.Exists( eventName ) ) then
\r
400 oGlobalEvents.Add eventName, Array()
\r
403 dim listeners, size
\r
404 listeners = oGlobalEvents( eventName )
\r
405 size = ubound(listeners) + 1
\r
406 redim preserve listeners(size)
\r
407 listeners(size) = javascriptCode
\r
409 oGlobalEvents( eventName ) = listeners
\r
411 ' // Avoid duplicates.
\r
412 ' if (!in_array($javascriptCode, $this->_globalEvents[$event])) {
\r
413 ' $this->_globalEvents[$event][] = $javascriptCode;
\r
418 ' Clear registered global event handlers.
\r
419 ' Note: this function will have no effect if the event handler has been already printed/returned.
\r
421 ' @param eventName (string) Event name, if set to 'empty' all event handlers will be removed .
\r
423 public sub clearGlobalEventHandlers( eventName )
\r
424 if not(isEmpty( eventName )) then
\r
425 oGlobalEvents.Remove eventName
\r
427 oGlobalEvents.RemoveAll
\r
432 ' Prints javascript code.
\r
436 private function script(js)
\r
437 script = "<script type=""text/javascript"">" & _
\r
438 "//<![CDATA[" & vbcrlf & _
\r
441 "</script>" & vbcrlf
\r
445 ' Returns the configuration array (global and instance specific settings are merged into one array).
\r
447 ' @param instanceConfig (Dictionary) The specific configurations to apply to editor instance.
\r
448 ' @param instanceEvents (Dictionary) Event listeners for editor instance.
\r
450 private function configSettings()
\r
451 dim mergedConfig, mergedEvents
\r
452 set mergedConfig = cloneDictionary(oAllInstancesConfig)
\r
453 set mergedEvents = cloneDictionary(oAllInstancesEvents)
\r
455 if not(isEmpty(oInstanceConfig)) then
\r
456 set mergedConfig = mergeDictionary(mergedConfig, oInstanceConfig)
\r
459 if not(isEmpty(oInstanceEvents)) then
\r
460 for each eventName in oInstanceEvents
\r
461 code = oInstanceEvents( eventName )
\r
463 if not(mergedEvents.Exists( eventName)) then
\r
464 mergedEvents.Add eventName, code
\r
467 dim listeners, size
\r
468 listeners = mergedEvents( eventName )
\r
469 size = ubound(listeners)
\r
470 if isArray( code ) then
\r
471 addedCount = ubound(code)
\r
472 redim preserve listeners( size + addedCount + 1 )
\r
473 for i = 0 to addedCount
\r
474 listeners(size + i + 1) = code (i)
\r
478 redim preserve listeners(size)
\r
479 listeners(size) = code
\r
482 mergedEvents( eventName ) = listeners
\r
488 dim i, eventName, handlers, configON, ub, code
\r
490 if mergedEvents.Count>0 then
\r
491 if mergedConfig.Exists( "on" ) then
\r
492 set configON = mergedConfig.items( "on" )
\r
494 set configON = CreateObject("Scripting.Dictionary")
\r
495 mergedConfig.Add "on", configOn
\r
498 for each eventName in mergedEvents
\r
499 handlers = mergedEvents( eventName )
\r
502 if isArray(handlers) then
\r
503 uB = ubound(handlers)
\r
507 code = "function (ev) {"
\r
509 code = code & "(" & handlers(i) & ")(ev);"
\r
516 ' Using @@ at the beggining to signal JSON that we don't want this quoted.
\r
517 configON.Add eventName, "@@" & code
\r
520 ' set mergedConfig.Item("on") = configOn
\r
523 set configSettings = mergedConfig
\r
527 ' Returns a copy of a scripting.dictionary object
\r
529 private function cloneDictionary( base )
\r
532 Set newOne = CreateObject("Scripting.Dictionary")
\r
533 for each tmpKey in base
\r
534 newOne.Add tmpKey , base( tmpKey )
\r
537 set cloneDictionary = newOne
\r
541 ' Combines two scripting.dictionary objects
\r
542 ' The base object isn't modified, and extra gets all the properties in base
\r
544 private function mergeDictionary(base, extra)
\r
547 for each tmpKey in base
\r
548 if not(extra.Exists( tmpKey )) then
\r
549 extra.Add tmpKey, base( tmpKey )
\r
553 set mergeDictionary = extra
\r
557 ' Return global event handlers.
\r
559 private function returnGlobalEvents()
\r
560 dim out, eventName, handlers
\r
561 dim handlersForEvent, handler, code, i
\r
564 if (isempty(CKEDITOR_returnedEvents)) then
\r
565 set CKEDITOR_returnedEvents = CreateObject("Scripting.Dictionary")
\r
568 for each eventName in oGlobalEvents
\r
569 handlers = oGlobalEvents( eventName )
\r
571 if not(CKEDITOR_returnedEvents.Exists(eventName)) then
\r
572 CKEDITOR_returnedEvents.Add eventName, CreateObject("Scripting.Dictionary")
\r
575 set handlersForEvent = CKEDITOR_returnedEvents.Item( eventName )
\r
577 ' handlersForEvent is another dictionary
\r
578 ' and handlers is an array
\r
580 for i = 0 to ubound(handlers)
\r
581 code = handlers( i )
\r
583 ' Return only new events
\r
584 if not(handlersForEvent.Exists( code )) then
\r
585 if (out <> "") then out = out & vbcrlf
\r
586 out = out & "CKEDITOR.on('" & eventName & "', " & code & ");"
\r
587 handlersForEvent.Add code, code
\r
592 returnGlobalEvents = out
\r
596 ' Initializes CKEditor (executed only once).
\r
598 private function init()
\r
599 dim out, args, path, extraCode, file
\r
602 if (CKEDITOR_initComplete) then
\r
607 if (initialized) then
\r
608 CKEDITOR_initComplete = true
\r
614 path = ckeditorPath()
\r
616 if (timestamp <> "") and (timestamp <> "%" & "TIMESTAMP%") then
\r
617 args = "?t=" & timestamp
\r
620 ' Skip relative paths...
\r
621 if (instr(path, "..") <> 0) then
\r
622 out = out & script("window.CKEDITOR_BASEPATH='" & path & "';")
\r
625 out = out & "<scr" & "ipt type=""text/javascript"" src=""" & path & ckeditorFileName() & args & """></scr" & "ipt>" & vbcrlf
\r
628 if (timestamp <> mTimeStamp) then
\r
629 extraCode = extraCode & "CKEDITOR.timestamp = '" & timestamp & "';"
\r
631 if (extraCode <> "") then
\r
632 out = out & script(extraCode)
\r
635 CKEDITOR_initComplete = true
\r
641 private function ckeditorFileName()
\r
642 ckeditorFileName = "ckeditor.js"
\r
646 ' Return path to ckeditor.js.
\r
648 private function ckeditorPath()
\r
649 if (basePath <> "") then
\r
650 ckeditorPath = basePath
\r
652 ' In classic ASP we can't get the location of this included script
\r
653 ckeditorPath = "/ckeditor/"
\r
656 ' Try to check if that folder contains the CKEditor files:
\r
657 ' If it's a full URL avoid checking it as it might point to an external server.
\r
658 if (instr(ckeditorPath, "://") <> 0) then exit function
\r
660 dim filename, oFSO, exists
\r
661 filename = server.mapPath(basePath & ckeditorFileName())
\r
662 set oFSO = Server.CreateObject("Scripting.FileSystemObject")
\r
663 exists = oFSO.FileExists(filename)
\r
666 if not(exists) then
\r
668 response.write "<h1>CKEditor path validation failed</h1>"
\r
669 response.write "<p>The path "" & ckeditorPath & "" doesn't include the CKEditor main file (" & ckeditorFileName() & ")</p>"
\r
670 response.write "<p>Please, verify that you have set it correctly and/or adjust the 'basePath' property</p>"
\r
671 response.write "<p>Checked for physical file: "" & filename & ""</p>"
\r
680 ' URL: http://www.webdevbros.net/2007/04/26/generate-json-from-asp-datatypes/
\r
681 '**************************************************************************************************************
\r
682 '' @CLASSTITLE: JSON
\r
683 '' @CREATOR: Michal Gabrukiewicz (gabru at grafix.at), Michael Rebec
\r
684 '' @CONTRIBUTORS: - Cliff Pruitt (opensource at crayoncowboy.com)
\r
685 '' - Sylvain Lafontaine
\r
688 '' @CREATEDON: 2007-04-26 12:46
\r
689 '' @CDESCRIPTION: Comes up with functionality for JSON (http://json.org) to use within ASP.
\r
690 '' Correct escaping of characters, generating JSON Grammer out of ASP datatypes and structures
\r
691 '' Some examples (all use the <em>toJSON()</em> method but as it is the class' default method it can be left out):
\r
695 '' output = (new JSON)("myNum", 2, false)
\r
696 '' 'generates {"myNum": 2}
\r
698 '' 'array with different datatypes
\r
699 '' output = (new JSON)("anArray", array(2, "x", null), true)
\r
700 '' 'generates "anArray": [2, "x", null]
\r
701 '' '(note: the last parameter was true, thus no surrounding brackets in the result)
\r
705 '' @OPTIONEXPLICIT: yes
\r
708 '**************************************************************************************************************
\r
712 private output, innerCall
\r
714 '**********************************************************************************************************
\r
716 '**********************************************************************************************************
\r
717 public sub class_initialize()
\r
721 '******************************************************************************************
\r
722 '' @SDESCRIPTION: STATIC! takes a given string and makes it JSON valid
\r
723 '' @DESCRIPTION: all characters which needs to be escaped are beeing replaced by their
\r
724 '' unicode representation according to the
\r
725 '' RFC4627#2.5 - http://www.ietf.org/rfc/rfc4627.txt?number=4627
\r
726 '' @PARAM: val [string]: value which should be escaped
\r
727 '' @RETURN: [string] JSON valid string
\r
728 '******************************************************************************************
\r
729 public function escape(val)
\r
730 dim cDoubleQuote, cRevSolidus, cSolidus
\r
731 cDoubleQuote = &h22
\r
734 dim i, currentDigit
\r
735 for i = 1 to (len(val))
\r
736 currentDigit = mid(val, i, 1)
\r
737 if ascw(currentDigit) > &h00 and ascw(currentDigit) < &h1F then
\r
738 currentDigit = escapequence(currentDigit)
\r
739 elseif ascw(currentDigit) >= &hC280 and ascw(currentDigit) <= &hC2BF then
\r
740 currentDigit = "\u00" + right(padLeft(hex(ascw(currentDigit) - &hC200), 2, 0), 2)
\r
741 elseif ascw(currentDigit) >= &hC380 and ascw(currentDigit) <= &hC3BF then
\r
742 currentDigit = "\u00" + right(padLeft(hex(ascw(currentDigit) - &hC2C0), 2, 0), 2)
\r
744 select case ascw(currentDigit)
\r
745 case cDoubleQuote: currentDigit = escapequence(currentDigit)
\r
746 case cRevSolidus: currentDigit = escapequence(currentDigit)
\r
747 case cSolidus: currentDigit = escapequence(currentDigit)
\r
750 escape = escape & currentDigit
\r
754 '******************************************************************************************************************
\r
755 '' @SDESCRIPTION: generates a representation of a name value pair in JSON grammer
\r
756 '' @DESCRIPTION: It generates a name value pair which is represented as <em>{"name": value}</em> in JSON.
\r
757 '' the generation is fully recursive. Thus the value can also be a complex datatype (array in dictionary, etc.) e.g.
\r
760 '' set j = new JSON
\r
761 '' j.toJSON "n", array(RS, dict, false), false
\r
762 '' j.toJSON "n", array(array(), 2, true), false
\r
765 '' @PARAM: name [string]: name of the value (accessible with javascript afterwards). leave empty to get just the value
\r
766 '' @PARAM: val [variant], [int], [float], [array], [object], [dictionary]: value which needs
\r
767 '' to be generated. Conversation of the data types is as follows:<br>
\r
768 '' - <strong>ASP datatype -> JavaScript datatype</strong>
\r
769 '' - NOTHING, NULL -> null
\r
770 '' - INT, DOUBLE -> number
\r
771 '' - STRING -> string
\r
772 '' - BOOLEAN -> bool
\r
773 '' - ARRAY -> array
\r
774 '' - DICTIONARY -> Represents it as name value pairs. Each key is accessible as property afterwards. json will look like <code>"name": {"key1": "some value", "key2": "other value"}</code>
\r
775 '' - <em>multidimensional array</em> -> Generates a 1-dimensional array (flat) with all values of the multidimensional array
\r
776 '' - <em>request</em> object -> every property and collection (cookies, form, querystring, etc) of the asp request object is exposed as an item of a dictionary. Property names are <strong>lowercase</strong>. e.g. <em>servervariables</em>.
\r
777 '' - OBJECT -> name of the type (if unknown type) or all its properties (if class implements <em>reflect()</em> method)
\r
778 '' Implement a <strong>reflect()</strong> function if you want your custom classes to be recognized. The function must return
\r
779 '' a dictionary where the key holds the property name and the value its value. Example of a reflect function within a User class which has firstname and lastname properties
\r
782 '' function reflect()
\r
783 '' . set reflect = server.createObject("scripting.dictionary")
\r
784 '' . reflect.add "firstname", firstname
\r
785 '' . reflect.add "lastname", lastname
\r
789 '' Example of how to generate a JSON representation of the asp request object and access the <em>HTTP_HOST</em> server variable in JavaScript:
\r
791 '' <script>alert(<%= (new JSON)(empty, request, false) % >.servervariables.HTTP_HOST);</script>
\r
793 '' @PARAM: nested [bool]: indicates if the name value pair is already nested within another? if yes then the <em>{}</em> are left out.
\r
794 '' @RETURN: [string] returns a JSON representation of the given name value pair
\r
795 '******************************************************************************************************************
\r
796 public default function toJSON(name, val, nested)
\r
797 if not nested and not isEmpty(name) then write("{")
\r
798 if not isEmpty(name) then write("""" & escape(name) & """: ")
\r
800 if not nested and not isEmpty(name) then write("}")
\r
803 if innerCall = 0 then newGeneration()
\r
806 '******************************************************************************************************************
\r
808 '******************************************************************************************************************
\r
809 private function generateValue(val)
\r
810 if isNull(val) then
\r
812 elseif isArray(val) then
\r
814 elseif isObject(val) then
\r
815 dim tName : tName = typename(val)
\r
816 if val is nothing then
\r
818 elseif tName = "Dictionary" or tName = "IRequestDictionary" then
\r
819 generateDictionary(val)
\r
820 elseif tName = "IRequest" then
\r
821 set req = server.createObject("scripting.dictionary")
\r
822 req.add "clientcertificate", val.ClientCertificate
\r
823 req.add "cookies", val.cookies
\r
824 req.add "form", val.form
\r
825 req.add "querystring", val.queryString
\r
826 req.add "servervariables", val.serverVariables
\r
827 req.add "totalbytes", val.totalBytes
\r
828 generateDictionary(req)
\r
829 elseif tName = "IStringList" then
\r
830 if val.count = 1 then
\r
831 toJSON empty, val(1), true
\r
836 generateObject(val)
\r
841 varTyp = varType(val)
\r
842 if varTyp = 11 then
\r
843 if val then write("true") else write("false")
\r
845 elseif varTyp = 2 or varTyp = 3 or varTyp = 17 or varTyp = 19 then
\r
847 'single, double, currency
\r
848 elseif varTyp = 4 or varTyp = 5 or varTyp = 6 or varTyp = 14 then
\r
849 write(replace(cDbl(val), ",", "."))
\r
851 ' Using @@ at the beggining to signal JSON that we don't want this quoted.
\r
852 if left(val, 2) = "@@" then
\r
853 write( mid( val, 3 ) )
\r
855 write("""" & escape(val & "") & """")
\r
859 generateValue = output
\r
862 '******************************************************************************************************************
\r
864 '******************************************************************************************************************
\r
865 private sub generateArray(val)
\r
869 'the for each allows us to support also multi dimensional arrays
\r
870 for each item in val
\r
871 if i > 0 then write(",")
\r
872 generateValue(item)
\r
878 '******************************************************************************************************************
\r
879 '* generateDictionary
\r
880 '******************************************************************************************************************
\r
881 private sub generateDictionary(val)
\r
882 innerCall = innerCall + 1
\r
883 if val.count = 0 then
\r
884 toJSON empty, null, true
\r
890 for each key in val
\r
891 if i > 0 then write(",")
\r
892 toJSON key, val(key), true
\r
896 innerCall = innerCall - 1
\r
899 '******************************************************************************************************************
\r
901 '******************************************************************************************************************
\r
902 private sub generateObject(val)
\r
904 on error resume next
\r
905 set props = val.reflect()
\r
908 innerCall = innerCall + 1
\r
909 toJSON empty, props, true
\r
910 innerCall = innerCall - 1
\r
913 write("""" & escape(typename(val)) & """")
\r
917 '******************************************************************************************************************
\r
919 '******************************************************************************************************************
\r
920 private sub newGeneration()
\r
925 '******************************************************************************************
\r
926 '* JsonEscapeSquence
\r
927 '******************************************************************************************
\r
928 private function escapequence(digit)
\r
929 escapequence = "\u00" + right(padLeft(hex(ascw(digit)), 2, 0), 2)
\r
932 '******************************************************************************************
\r
934 '******************************************************************************************
\r
935 private function padLeft(value, totalLength, paddingChar)
\r
936 padLeft = right(clone(paddingChar, totalLength) & value, totalLength)
\r
939 '******************************************************************************************
\r
941 '******************************************************************************************
\r
942 private function clone(byVal str, n)
\r
944 for i = 1 to n : clone = clone & str : next
\r
947 '******************************************************************************************
\r
949 '******************************************************************************************
\r
950 private sub write(val)
\r
951 output = output & val
\r