{"id":587,"date":"2010-04-16T09:09:59","date_gmt":"2010-04-16T14:09:59","guid":{"rendered":"http:\/\/www.lonhosford.com\/lonblog\/?p=587"},"modified":"2015-07-31T18:25:51","modified_gmt":"2015-07-31T23:25:51","slug":"actionscript-3-0-debug-console-lite","status":"publish","type":"post","link":"https:\/\/www.lonhosford.com\/lonblog\/2010\/04\/16\/actionscript-3-0-debug-console-lite\/","title":{"rendered":"Actionscript 3.0 Debug Console Lite"},"content":{"rendered":"<p><strong>By Lon (Alonzo) Hosford<\/strong><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"\" src=\"http:\/\/lh4.ggpht.com\/_e5pwU0LJbN8\/TG1JstRAf0I\/AAAAAAAAFrU\/C6UIhqYDDBQ\/s144\/debug_console_published.png\" class=\"alignleft\" width=\"144\" height=\"90\" \/>I created this debug console for use in learning and teaching Actionscript programming. This is developed in pure Actionscript without component libraries. For that reason it can be used in Flash, AIR, and Flex. It will work in Flash IDE like Flash CS4 or Flex Builder. It also works creating Flash, Flex or AIR from the Flex SDK command line. <\/p>\n<div style = \"float:right\">\n[ad name=&#8221;Google Adsense&#8221;]<\/div>\n<p>The debug console plays in the published movie. It also outputs the results to the consoles in the respective IDEs: Flex Builder, Flash CS4, etc. You can turn that feature off and make the DebugConsole invisible when you publish if you wish.<\/p>\n<p>This is an ActionScript project created in Flex Builder and updated to Flex Builder 4. <a href=\"https:\/\/www.lonhosford.com\/content\/flex\/ActionscriptDebuggerLite\/DebuggerLite.zip\">Download the example code<\/a>. You can build this with the free Flex SDK by using the code in the src folder. Same for Flash CS3 and CS4. You need to create a Flash Document in the src folder and set the document class to <code>DebuggerLite<\/code>.<\/p>\n<p>If you want to use the DebugConsole in a Flash CS4 or CS3 you do not need to set the document class to <code>DebuggerLite<\/code>. Rather in Actionscript you include this code: <\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\nimport com.lonhosford.util.debug.lite.DebugConsole\r\nvar debugConsole:DebugConsole = DebugConsole.getInstance();\r\nstage.addChild(debugConsole);\r\ndebugConsole.width = 200;\r\ndebugConsole.height = 200;\r\ndebugConsole.write(&quot;Hello World&quot;);\r\n<\/pre>\n<p> For your convenience you can <a href=\"https:\/\/www.lonhosford.com\/content\/flex\/ActionscriptDebuggerLite\/DebuggerLite_Flash_CS4.zip\">download a Flash CS4 ready to go example<\/a>.<\/p>\n<p><strong>Testing Application In Flex Builder<\/strong><br \/>\nThis is a testing Actionscript application in Flex Builder. No Flash or Flex components are used so there is not need to import libraries. The <code>DebugConsole<\/code> class is instantiated as <code>_debugConsole<\/code> on line 23. It is a singleton design pattern so only one exists for the application. <\/p>\n<p>A <code>Timer<\/code> is used to generate entries to the <code>DebugConsole<\/code>. The <code>Timer<\/code> is instantiated on line 24 as <code>_testTimer<\/code>.<\/p>\n<p>The <code>_testTimeCount<\/code> variable is used to determine how many generated entries to the <code>DebugConsole<\/code>. General purpose is to see when vertical scroll bar appears. <\/p>\n<p>The <code>_showWideLineAt <\/code>variable on line 25 is used add a very wide line of text to trip showing the horizontal scroll bar. The  <code>_showWideLineAt<\/code> variable trips this when it equal <code>_testTimer.currentCount<\/code> value.<\/p>\n<p>The <code>_testTimeDelay<\/code> variable on line 26 is the millisecond value for the <code>_testTimer<\/code>. Just depends on how fast you want to see the automated updates to the <code>DebugConsole<\/code>.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\n\/**\r\n *  Purpose: Test Debugger Lite\r\n\t&lt;p&gt;Author: Lon Hosford www.lonhosford.com 908 996 3773&lt;\/p&gt;\r\n\t&lt;p&gt;Date: March 12, 2010&lt;\/p&gt;\r\n * *\/\r\npackage\r\n{\r\n\timport com.lonhosford.util.debug.lite.DebugConsole;\r\n\t\r\n\timport flash.display.Sprite;\r\n\timport flash.events.KeyboardEvent;\r\n\timport flash.events.TimerEvent;\r\n\timport flash.ui.Keyboard;\r\n\timport flash.utils.Timer;\r\n\t\r\n\t&#x5B;SWF(width=500, height = 300, frameRate = 30)]\r\n\t\/**\r\n\t * Testing application for DebugConsole.\r\n\t * @see com.lonhosford.util.debug.lite.DebugConsole  \r\n\t * *\/\r\n\tpublic class DebuggerLite extends Sprite\r\n\t{\r\n\t\tprivate var _debugConsole:DebugConsole = DebugConsole.getInstance();\r\n\t\tprivate var _testTimeCount:Number = 15; \r\n\t\tprivate var _showWideLineAt:Number = 2; \r\n\t\tprivate var _testTimeDelay:Number = 250; \r\n\t\tprivate var _testTimer:Timer; \r\n\t\tpublic function DebuggerLite()\r\n\t\t{\r\n\t\t\tstage.addChild(_debugConsole);\r\n\t\t\t_debugConsole.width = stage.stageWidth;\r\n\t\t\t_debugConsole.height = stage.stageHeight;\r\n\t\t\t\r\n\t\t\t_testTimer = new Timer(_testTimeDelay,_testTimeCount); \r\n\t\t\t_testTimer.addEventListener(TimerEvent.TIMER,testTimerEventHandler);\r\n\t\t\t_testTimer.addEventListener(TimerEvent.TIMER_COMPLETE,testTimerCompleteEventHandler);\r\n\t\t\tstage.addEventListener(KeyboardEvent.KEY_UP, stageKeyUpEventHandler);\r\n\t\t\tstart();\r\n\t\t\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Starts the automated testing.\r\n\t\t * *\/\r\n\t\tprivate function start():void\r\n\t\t{\r\n\t\t_debugConsole.write(&quot;Debugger Lite Tester&quot;);\r\n\t\t_debugConsole.write(&quot;Hit Space Bar to Clear.&quot;);\r\n\t\t_debugConsole.write(&quot;Hit Ctr+ Space Bar to Repeat.&quot;);\r\n\t\t_debugConsole.write(&quot;\\n&quot;);\r\n\t\t_testTimer.start();\r\n\t\t\t\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Handles the KeyboardEvent.KEY_UP event for the stage.\r\n\t\t * *\/\r\n\t\tprivate function stageKeyUpEventHandler(event:KeyboardEvent):void \r\n\t\t{\r\n\t\t\t\/\/ Space bar\r\n\t\t\tif ( event.keyCode == Keyboard.SPACE )\r\n\t\t\t{\r\n\t\t\t\t\/\/ Control key\r\n\t\t\t\tif (event.ctrlKey)\r\n\t\t\t\t{\r\n\t\t\t\t\t_testTimer.stop();\r\n\t\t\t\t\t_testTimer.reset();\r\n\t\t\t\t\t_debugConsole.clear();\r\n\t\t\t\t\tstart();\r\n\t\t\t\t}\r\n\t\t\t\t\/\/ No control key\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t_debugConsole.clear();\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Handles the TimerEvent.TIMER event.\r\n\t\t * *\/\r\n\t\tprivate function testTimerEventHandler(event:TimerEvent):void \r\n\t\t{\r\n\t\t\t_debugConsole.write(new Date().toTimeString());\r\n\t\t\tif (_testTimer.currentCount == _showWideLineAt)\r\n\t\t\t{\r\n\t\t\t\t_debugConsole.write(&quot;START Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. END&quot;);\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Handles the TimerEvent.TIMER_COMPLETE event.\r\n\t\t * *\/\r\n\t\tprivate function testTimerCompleteEventHandler(event:TimerEvent):void \r\n\t\t{\r\n\t\t\t_debugConsole.write(&quot;LAST LINE&quot;);\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p>[ad name=&#8221;Google Adsense&#8221;]<br \/>\n<strong>DebugConsole Class<\/strong><br \/>\nThis is the<code> DebugConsole<\/code> class. It is a singleton and as such can be instantiated anywhere in your code to use the <code>write()<\/code> method on line 291. The DebugConsole <code>write()<\/code> method calls the Debugger class <code>write()<\/code>method.  The Debugger class <code>write()<\/code>method dispatches a <code>DebuggerEvent.WRITE<\/code> which the <code>DebugConsole<\/code> listens in the <code>consoleUpdate() <\/code>on line 308. For this reason you can also instantiate the <code>Debugger<\/code> class in code and use its <code>write() <\/code>method if you prefer. You only need to instantiate the <code>DebugConsole<\/code> where you intend to add it to your display.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage com.lonhosford.util.debug.lite\r\n{\r\n\timport flash.display.Sprite;\r\n\timport flash.events.Event;\r\n\timport flash.events.MouseEvent;\r\n\timport flash.text.TextField;\r\n\timport flash.text.TextFieldAutoSize;\r\n\timport flash.text.TextFormat;\r\n\timport flash.text.TextFormatAlign;\r\n\t\r\n\t\/**\r\n\t *  UI for debug.lite package\r\n\t * *\/\r\n\tpublic class DebugConsole extends Sprite\r\n\t{\r\n\t\tprivate static var _instance:DebugConsole;\t\t\t\t\t\/\/ Singleton instance\r\n\t\tprivate var _debugger:Debugger;\t\t\t\t\t\t\t\t\r\n\t\tprivate var _content_tf:TextField;\t\t\t\t\t\t\t\/\/ The console content\r\n\t\tprivate var _lineCount_tf:TextField;\t\t\t\t\t\t\/\/ The line count\t\t\t\t\t\r\n\t\tprivate var _width:Number = 0;\t\t\t\t\t\t\t\t\/\/ Width\r\n\t\tprivate var _height:Number = 0;\t\t\t\t\t\t\t\t\/\/ Height\r\n\t\tprivate var _scrollVContainer:Sprite;\t\t\t\t\t\t\/\/ Vertical scroller container\r\n\t\tprivate var _scrollHContainer:Sprite;\t\t\t\t\t\t\/\/ Horizontal scroller container\r\n\t\tprivate var _scrollLeftButton:DebugConsoleArrowButton;\t\t\/\/ Scroll left button\r\n\t\tprivate var _scrollRightButton:DebugConsoleArrowButton;\t\t\/\/ Scroll right button\r\n\t\tprivate var _scrollUpButton:DebugConsoleArrowButton;\t\t\/\/ Scroll up button\r\n\t\tprivate var _scrollDownButton:DebugConsoleArrowButton;\t\t\/\/ Scroll down button\r\n\t\tprivate var _horizontalScrollIncrement:int = 10;\t\t\t\/\/ Character count increment for horizontal scrolling\r\n\t\tprivate var _verticalScrollIncrement:int = 1;\t\t\t\t\/\/ Line count increment for vertical scrolling.\r\n\t\tprivate var _autoScroll:Boolean = true;\t\t\t\t\t\t\/\/ Autoscroll to last line\r\n\t\t\r\n\t\t\/**\r\n\t\t *  Constructor\r\n\t\t * \r\n\t\t * @param pvt Enforces a singleton pattern.\r\n\t\t * @see #getInstance() \r\n\t\t * *\/\r\n\t\tpublic function DebugConsole(pvt:DebugConsolePrivateClass)\r\n\t\t{\r\n\t\t\t_content_tf = new TextField();\r\n\t\t\t_lineCount_tf = new TextField();\r\n\t\t\t\r\n\t\t\tvar format:TextFormat = new TextFormat();\r\n\t\t\tformat.font = &quot;_typewriter&quot;;\r\n\t\t\tformat.color = 0x000000;\r\n\t\t\tformat.size = 12;\r\n\t\t\tformat.indent = 2;\r\n\t\t\t_content_tf.defaultTextFormat = format;\r\n\t\t\t_content_tf.background= true;\r\n\t\t\t_content_tf.backgroundColor = 0xffffff;\r\n\t\t\t\r\n\t\t\tvar format2:TextFormat = new TextFormat();\r\n\t\t\tformat2.font = &quot;_typewriter&quot;;\r\n\t\t\tformat2.color = 0x000000;\r\n\t\t\tformat2.size = 12;\r\n\t\t\tformat2.leftMargin = 1\r\n\t\t\tformat2.align = TextFormatAlign.RIGHT;\r\n\t\t\t\/\/format2.indent = 1;\r\n\t\t\t\r\n\t\t\t_lineCount_tf.defaultTextFormat = format2;\r\n\t\t\t_lineCount_tf.background= true;\r\n\t\t\t_lineCount_tf.backgroundColor = 0xcccccc;\r\n\t\r\n\t\t\t_content_tf.addEventListener(Event.SCROLL, _console_tfScrollHandler);\r\n\r\n\t\t\t_scrollHContainer = new Sprite();\r\n\t\t\t_scrollVContainer = new Sprite();\r\n\t\t\t\r\n\t\t\t_scrollLeftButton = new DebugConsoleArrowButton();\r\n\t\t\t_scrollLeftButton.addEventListener(MouseEvent.CLICK,scrollLeftButtonMouseClick);\r\n\t\t\t_scrollRightButton = new DebugConsoleArrowButton();\r\n\t\t\t_scrollRightButton.addEventListener(MouseEvent.CLICK,scrollRightButtonMouseClick);\r\n\t\t\t\r\n\t\t\t_scrollUpButton = new DebugConsoleArrowButton();\r\n\t\t\t_scrollUpButton.addEventListener(MouseEvent.CLICK,scrollUpButtonMouseClick);\r\n\t\t\t_scrollDownButton = new DebugConsoleArrowButton();\r\n\t\t\t_scrollDownButton.addEventListener(MouseEvent.CLICK,scrollDownButtonMouseClick);\r\n\t\t\t\r\n\t\t\taddChild(_content_tf);\r\n\t\t\taddChild(_lineCount_tf);\r\n\t\t\taddChild(_scrollHContainer);\r\n\t\t\taddChild(_scrollVContainer);\r\n\t\t\t_scrollHContainer.addChild(_scrollLeftButton);\r\n\t\t\t_scrollHContainer.addChild(_scrollRightButton);\r\n\t\t\t_scrollVContainer.addChild(_scrollUpButton);\r\n\t\t\t_scrollVContainer.addChild(_scrollDownButton);\r\n\t\t\t_debugger = Debugger.getInstance();\r\n\t\t\t_debugger.addEventListener(DebuggerEvent.WRITE,consoleUpdate);\r\n\t\t\t\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Singleton instantiation method\r\n\t\t * *\/\r\n\t\tpublic static function getInstance():DebugConsole\r\n\t\t{\r\n\t\t\tif (DebugConsole._instance == null)\r\n\t\t\t{\r\n\t\t\t\tDebugConsole._instance = new DebugConsole(new DebugConsolePrivateClass());\r\n\t\t\t}\r\n\t\t\treturn DebugConsole._instance;\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Redraws the components\r\n\t\t * *\/\r\n\t\tprivate function draw():void\r\n\t\t{\r\n\t\t\tvar rightPanelHeight:Number;\r\n\t\t\tvar bottomPanelWidth:Number;\r\n\t\t\tvar lineCount_tf_width:Number = _lineCount_tf.textWidth + 12;\/\/ Extra for TextField overhead\r\n\t\t\tvar bottomPanelHeight:Number = 20;\r\n\t\t\tvar rightPanelWidth:Number = 20;\r\n\t\t\t\t\r\n\t\t\tvar tfHeight:Number;\/\/ = _height;\r\n\t\t\tvar tfWidth:Number = _width;\r\n\t\t\t\/\/ Component border\r\n\t\t\tgraphics.clear();\r\n\t\t\tgraphics.beginFill(0xffffff);\r\n\t\t\tgraphics.lineStyle(2, 0x000000);\r\n\t\t\tgraphics.drawRect(0, 0, _width, _height);\r\n\t\t\tgraphics.endFill();\r\n\t\t\t_scrollLeftButton.draw(\r\n\t\t\t\tbottomPanelHeight,\r\n\t\t\t\tbottomPanelHeight,\r\n\t\t\t\t0x00ffff,\r\n\t\t\t\t1,\r\n\t\t\t\t0x000000,\r\n\t\t\t\t0x666666,\r\n\t\t\t\t90\r\n\t\t\t);\r\n\t\t\t_scrollRightButton.draw(\r\n\t\t\t\tbottomPanelHeight,\r\n\t\t\t\tbottomPanelHeight,\r\n\t\t\t\t0x00ffff,\r\n\t\t\t\t1,\r\n\t\t\t\t0x000000,\r\n\t\t\t\t0x666666,\r\n\t\t\t\t-90\r\n\t\t\t);\r\n\t\t\t\r\n\t\t\t_scrollUpButton.draw(\r\n\t\t\t\trightPanelWidth,\r\n\t\t\t\trightPanelWidth,\r\n\t\t\t\t0x00ffff,\r\n\t\t\t\t1,\r\n\t\t\t\t0x000000,\r\n\t\t\t\t0x666666,\r\n\t\t\t\t0\r\n\t\t\t);\r\n\t\t\t_scrollDownButton.draw(\r\n\t\t\t\trightPanelWidth,\r\n\t\t\t\trightPanelWidth,\r\n\t\t\t\t0x00ffff,\r\n\t\t\t\t1,\r\n\t\t\t\t0x000000,\r\n\t\t\t\t0x666666,\r\n\t\t\t\t180\r\n\t\t\t);\r\n\t\t\ttfHeight = height\r\n\t\t\trightPanelHeight = height-3;\r\n\t\t\tbottomPanelWidth = width - 3 - lineCount_tf_width;\r\n\t\t\tif (_content_tf.textHeight &gt; _content_tf.height)\r\n\t\t\t{\r\n\t\t\t\tbottomPanelWidth -= rightPanelWidth - 1;\r\n\t\t\t}\r\n\t\t\tif (_content_tf.textWidth &gt; _content_tf.width)\r\n\t\t\t{\r\n\t\t\t\trightPanelHeight -= bottomPanelHeight - 1;\r\n\t\t\t}\r\n\t\t\t\/\/ Right scrollbar panel\r\n\t\t\tif (_content_tf.textHeight &gt; _content_tf.height)\r\n\t\t\t{\r\n\t\t\t\t_scrollUpButton.x = 0;\r\n\t\t\t\t_scrollUpButton.y = 0;\r\n\t\t\t\t_scrollDownButton.x = 0;\r\n\t\t\t\t_scrollDownButton.y = 0;\r\n\t\t\t\t_scrollVContainer.graphics.clear();\r\n\t\t\t\t\r\n\t\t\t\t_scrollVContainer.graphics.beginFill(0xcccccc);\r\n\t\t\t\t_scrollVContainer.graphics.lineStyle(1, 0x000000);\r\n\t\t\t\t_scrollVContainer.graphics.drawRect(0, 0, rightPanelWidth - 1, rightPanelHeight);\r\n\t\t\t\t_scrollVContainer.graphics.endFill();\r\n\t\t\t\t_scrollVContainer.x = _width - _scrollVContainer.width + .5;\r\n\t\t\t\t_scrollVContainer.y = .5;\r\n\r\n\t\t\t\t\r\n\t\t\t\t_scrollDownButton.x = (_scrollVContainer.width - _scrollDownButton.width) ;\r\n\t\t\t\t_scrollDownButton.y = (_scrollVContainer.height - _scrollDownButton.height) ;\r\n\t\t\t\t_scrollUpButton.x = _scrollDownButton.x;\r\n\t\t\t\t_scrollUpButton.y = 0;\r\n\t\t\t\t\r\n\t\t\t\ttfWidth -= _scrollVContainer.width - 1;\r\n\t\t\t\t\r\n\t\t\t\t_scrollVContainer.visible = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t_scrollVContainer.visible = false;\r\n\t\t\t}\r\n\t\t\t\/\/ Bottom scrollbar panel\r\n\t\t\tif (_content_tf.textWidth &gt; _content_tf.width)\r\n\t\t\t{\r\n\t\t\t\t_scrollLeftButton.x = 0;\r\n\t\t\t\t_scrollLeftButton.y = 0;\r\n\t\t\t\t_scrollRightButton.x = 0;\r\n\t\t\t\t_scrollRightButton.y = 0;\r\n\t\t\t\t_scrollHContainer.graphics.clear();\r\n\t\t\t\t_scrollHContainer.graphics.beginFill(0xcccccc);\r\n\t\t\t\t_scrollHContainer.graphics.lineStyle(1, 0x000000);\r\n\t\t\t\t_scrollHContainer.graphics.drawRect(0, 0, bottomPanelWidth, bottomPanelHeight - 1);\r\n\t\t\t\t_scrollHContainer.graphics.endFill();\r\n\t\t\t\t_scrollHContainer.y = _height - _scrollHContainer.height + .5;\r\n\t\t\t\t_scrollHContainer.x = lineCount_tf_width;\r\n\t\t\t\t_scrollLeftButton.x = (_scrollHContainer.width - _scrollLeftButton.width) ;\r\n\t\t\t\t_scrollLeftButton.y = (_scrollHContainer.height - _scrollLeftButton.height) ;\r\n\t\t\t\t_scrollRightButton.x = 0;\r\n\t\t\t\t_scrollRightButton.y = _scrollLeftButton.y;\r\n\r\n\t\t\t\t_scrollHContainer.visible = true;\r\n\t\t\t\ttfHeight -= _scrollHContainer.height -1;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t_scrollHContainer.visible = false;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t\/\/ Left bottom rectangle if horizontal and vertical scroll bars are visible.\r\n\t\t\tif (_scrollHContainer.visible &amp;&amp; _scrollVContainer.visible)\r\n\t\t\t{\r\n\t\t\t\tgraphics.beginFill(0xcccccc);\r\n\t\t\t\tgraphics.lineStyle(0, 0x000000,0);\r\n\t\t\t\tgraphics.drawRect(_scrollHContainer.x + _scrollHContainer.width, _scrollVContainer.height, bottomPanelHeight-2, bottomPanelHeight-2);\r\n\t\t\t\tgraphics.endFill();\r\n\t\t\t}\r\n\t\t\t\/\/ Left bottom rectangle if horizontal scroll bar is visible.\r\n\t\t\tif (_scrollHContainer.visible)\r\n\t\t\t{\r\n\t\t\t\tgraphics.beginFill(0xcccccc);\r\n\t\t\t\tgraphics.lineStyle(1, 0x000000,100);\r\n\t\t\t\tgraphics.drawRect( 0, _scrollHContainer.y, lineCount_tf_width, bottomPanelHeight-1);\r\n\t\t\t\tgraphics.endFill();\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t\/\/ Position and resize line count text field.\r\n\t\t\t_lineCount_tf.width = lineCount_tf_width;\t\r\n\t\t\t_lineCount_tf.height = tfHeight - 4;\t\t\t\r\n\t\t\t_lineCount_tf.x = 1;\r\n\t\t\t_lineCount_tf.y = 1;\r\n\t\t\t\r\n\t\t\t_lineCount_tf.scrollV = _content_tf.scrollV;\r\n\t\t\t\r\n\t\t\t\/\/ Position and resize line content text field.\r\n\t\t\t_content_tf.width = tfWidth - 2 - lineCount_tf_width;\r\n\t\t\t_content_tf.height = _lineCount_tf.height;\r\n\t\t\t_content_tf.x = _lineCount_tf.x + _lineCount_tf.width ;\r\n\t\t\t_content_tf.y = _lineCount_tf.y;\r\n\t\t\t\r\n\t\t\t_scrollUpButton.enabled =  _content_tf.scrollV != 1;\r\n\t\t\t_scrollDownButton.enabled =  _content_tf.scrollV != _content_tf.maxScrollV;\r\n\t\t\t_scrollLeftButton.enabled =  _content_tf.scrollH != _content_tf.maxScrollH;\r\n\t\t\t_scrollRightButton.enabled =  _content_tf.scrollH != 0;\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Change width\r\n\t\t * *\/\r\n\t\toverride public function set width(width:Number):void\r\n\t\t{\r\n\t\t\t_width = width;\r\n\t\t\tdraw();\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Change height\r\n\t\t * *\/\r\n\t\toverride public function set height(height:Number):void\r\n\t\t{\r\n\t\t\t_height = height;\r\n\t\t\tdraw();\r\n\t\t\t\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Scroll to last line. \r\n\t\t * @default true  \r\n\t\t * *\/\r\n\t\tpublic function set autoScroll(autoScrollEnabled:Boolean):void\r\n\t\t{\r\n\t\t\t_autoScroll = autoScrollEnabled;\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Adds one line. Multiple lines can be added inserting \\n. A blank line can be added with \\n.\r\n\t\t * &lt;p&gt;The writing is delegated to the Debugger class.&lt;\/p&gt;\r\n\t\t * @see com.lonhosford.util.debug.lite.Debugger.write()\r\n\t\t * *\/\r\n\t\tpublic function write(msg:String):void \r\n\t\t{\r\n\t\t\t_debugger.write(msg);\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Clears the display. Line count is not reset to 0 and continues to increment.\r\n\t\t * *\/\r\n\t\tpublic function clear():void \r\n\t\t{\r\n\t\t\t_lineCount_tf.text = &quot;&quot;;\r\n\t\t\t_content_tf.text = &quot;&quot;;\r\n\t\t\tdraw();\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Handles the DebuggerEvent.WRITE event.\r\n\t\t * *\/\r\n\t\tprivate function consoleUpdate(e:DebuggerEvent):void\r\n\t\t{\r\n\t\t\tvar debugMessage:DebugMessage = e.debugMessage;\r\n\t\t\t\r\n\t\t\t_lineCount_tf.appendText(debugMessage.lineNumber + &quot;.&quot; + &quot;\\n&quot;);\r\n\t\t\tif (debugMessage.text == &quot;\\n&quot;)\r\n\t\t\t{\r\n\t\t\t\tdebugMessage.text = &quot;&quot;;\r\n\t\t\t}\r\n\t\t\t_content_tf.appendText( debugMessage.text + &quot;\\n&quot;);\r\n\t\t\tif(_autoScroll)\r\n\t\t\t{\r\n\t\t\t\t_content_tf.scrollV = _content_tf.maxScrollV;\r\n\t\t\t}\t\t\t\r\n\t\t\tdraw();\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Handler for the scrollUpButton MouseEvent.CLICK event.\r\n\t\t * *\/\r\n\r\n\t\tprivate function scrollUpButtonMouseClick(e:MouseEvent):void\r\n\t\t{\r\n\t\t\tif (_content_tf.scrollV &lt;= _verticalScrollIncrement)\r\n\t\t\t{\r\n\t\t\t\t_content_tf.scrollV = 1;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t_content_tf.scrollV -= _verticalScrollIncrement;\r\n\t\t\t}\r\n\t\t\tdraw();\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Handler for the scrollRightButton MouseEvent.CLICK event.\r\n\t\t * *\/\r\n\t\tprivate function scrollRightButtonMouseClick(e:MouseEvent):void\r\n\t\t{\r\n\t\t\tif (_content_tf.scrollH &lt;= _horizontalScrollIncrement)\r\n\t\t\t{\r\n\t\t\t\t_content_tf.scrollH = 0;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t_content_tf.scrollH -= _horizontalScrollIncrement;\r\n\t\t\t}\r\n\t\t\tdraw();\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Handler for the scrollDownButton MouseEvent.CLICK event.\r\n\t\t * *\/\r\n\t\tprivate function scrollDownButtonMouseClick(e:MouseEvent):void\r\n\t\t{\r\n\t\t\t\r\n\t\t\tif (_content_tf.scrollV + _verticalScrollIncrement &gt;= _content_tf.maxScrollV)\r\n\t\t\t{\r\n\t\t\t\t_content_tf.scrollV = _content_tf.maxScrollV;\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t_content_tf.scrollV += _verticalScrollIncrement;\r\n\t\t\t}\r\n\t\t\tdraw();\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Handler for the scrollLeftButton MouseEvent.CLICK event.\r\n\t\t * *\/\r\n\t\tprivate function scrollLeftButtonMouseClick(e:MouseEvent):void\r\n\t\t{\r\n\t\t\t\r\n\t\t\tif (_content_tf.scrollH + _horizontalScrollIncrement &gt;= _content_tf.maxScrollH)\r\n\t\t\t{\r\n\t\t\t\t_content_tf.scrollH =_content_tf.maxScrollH;\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t_content_tf.scrollH += _horizontalScrollIncrement;\r\n\t\t\t}\r\n\t\t\tdraw();\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Handler for the _content_tf Event.SCROLL event.\r\n\t\t * *\/\r\n\t\tpublic function _console_tfScrollHandler(event:Event):void\r\n\t\t{\r\n\t\t\tdraw();\r\n\t\t}\r\n\t}\r\n}\r\n\/**\r\n * Singleton enforcer class\r\n * *\/\r\nclass DebugConsolePrivateClass\r\n{\r\n\tpublic function DebugConsolePrivateClass()\r\n\t{\r\n\t\t\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>Debugger Class<\/strong><br \/>\nThis class receives write messages and dispatches them. It also will write to the IDE debug console on line 60.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage com.lonhosford.util.debug.lite\r\n{\r\n\timport flash.events.EventDispatcher;\r\n\t\/**\r\n\t * Singleton for receiving and dispatching debugging messages\r\n\t * *\/\r\n\tpublic class Debugger extends EventDispatcher\r\n\t{\r\n\t\tprivate static var _instance:Debugger;\r\n\t\tprivate var _msg:String;\r\n\t\tprivate var _isTracing:Boolean = true;\t\t\/\/ State of using the trace() function.\r\n\t\tprivate var _lineCount:Number = 0;\t\t\t\/\/ Line count of tracing messages\r\n\t\tprivate var _lang_productName:String = &quot;Actionscript 3 Debugger Lite&quot;;\r\n\t\tprivate var _lang_productVersion:String = &quot;Version&quot;;\r\n\t\t\/**\r\n\t\t *  Constructor\r\n\t\t * \r\n\t\t * @param pvt Enforces a singleton pattern.\r\n\t\t * @see #getInstance() \r\n\t\t * *\/\r\n\t\tpublic function Debugger(pvt:DebuggerPrivateClass)\r\n\t\t{\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Singleton instantiation method\r\n\t\t * *\/\r\n\t\tpublic static function getInstance():Debugger\r\n\t\t{\r\n\t\t\tif (Debugger._instance == null)\r\n\t\t\t{\r\n\t\t\t\tDebugger._instance = new Debugger(new DebuggerPrivateClass());\r\n\t\t\t}\r\n\t\t\treturn Debugger._instance;\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Turns on or off tracing to the Flash or Flex IDE console.\r\n\t\t * @default true\r\n\t\t * *\/\r\n\t\tpublic function set isTracing(value:Boolean):void\r\n\t\t{\r\n\t\t\t_isTracing = value;\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Adds one line. Multiple lines can be added inserting \\n. A blank line can be added with \\n.\t\t * &lt;p&gt;The writing is delegated to the Debugger class.&lt;\/p&gt;\r\n\t\t * *\/\r\n\t\tpublic function write(msg:String):void \r\n\t\t{\r\n\t\t\tvar messageLines:Array = new Array();\r\n\t\t\tif (msg == &quot;\\n&quot;) \r\n\t\t\t{\r\n\t\t\t\tmessageLines.push(&quot;&quot;);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmessageLines = msg.split(&quot;\\n&quot;)\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t\r\n\t\t\tif (_isTracing)\r\n\t\t\t{\r\n\t\t\t\ttrace(msg);\r\n\t\t\t}\r\n\t\t\tif ( _lineCount == 0 )\r\n\t\t\t{\r\n\t\t\t\tmessageLines.splice(0,0,_lang_productName + &quot;\\t&quot; + _lang_productVersion + &quot; &quot; + DebugVersion.VERSION);\r\n\t\t\t\tmessageLines.splice(1,0, DebugVersion.AUTHOR + &quot;\\t&quot; + DebugVersion.AUTHOR_WEB_SITE);\r\n\t\t\t\tmessageLines.splice(2,0,&quot;\\n&quot;);\r\n\t\t\t}\r\n\t\t\tfor (var msgLinesIndex:uint = 0; msgLinesIndex &lt;= messageLines.length - 1; msgLinesIndex++)\r\n\t\t\t{\r\n\t\t\t\tdispatchMessageEvent(messageLines&#x5B;msgLinesIndex]);\r\n\t\t\t}\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Dispatches a DebuggerEvent.WRITE\r\n\t\t * @see DebuggerEvent\r\n\t\t * @see DebugMessage\r\n\t\t * *\/\r\n\t\tprivate function dispatchMessageEvent(msg:String):void\r\n\t\t{\r\n\t\t\tvar debugMessage:DebugMessage = new DebugMessage();\r\n\t\t\tdebugMessage.text = msg;\r\n\t\t\tdebugMessage.lineNumber = ++_lineCount;\r\n\t\t\tvar e:DebuggerEvent = new DebuggerEvent(DebuggerEvent.WRITE,  debugMessage);\r\n\t\t\tdispatchEvent(e);\r\n\t\t}\r\n\t}\r\n}\r\n\/**\r\n * Singleton enforcer class\r\n * *\/\r\nclass DebuggerPrivateClass\r\n{\r\n\tpublic function DebuggerPrivateClass()\r\n\t{\r\n\t\t\r\n\t}\r\n}\r\n<\/pre>\n<p>[ad name=&#8221;Google Adsense&#8221;]<br \/>\n<strong>DebugConsoleArrowButton Class<\/strong><br \/>\nUI for the scroll buttons. Simple shapes using a triangle to indicate direction of scroll.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage com.lonhosford.util.debug.lite\r\n{\r\n\timport flash.display.Sprite;\r\n\timport flash.events.MouseEvent;\r\n\timport flash.events.TimerEvent;\r\n\timport flash.utils.Timer;\r\n\t\/**\r\n\t * Arrow button UI and logic\r\n\t * *\/\r\n\tpublic class DebugConsoleArrowButton extends Sprite\r\n\t{\r\n\t\tprivate var _container:Sprite = new Sprite();\r\n\t\tprivate var _triangle:DebugTriangleShape = new DebugTriangleShape();\r\n\t\tprivate var _backgroundRect:Sprite = new Sprite();\r\n\t\tprivate var _width:Number;\r\n\t\tprivate var _height:Number;\r\n\t\tprivate var _color:int;\t\t\t\t\t\t\t\t\t\t\/\/ Color of arrow.\r\n\t\tprivate var _borderWidth:Number;\t\t\t\t\t\t\t\/\/ Border width of button.\r\n\t\tprivate var _borderColor:int;\t\t\t\t\t\t\t\t\/\/ Border color of button.\r\n\t\tprivate var _backgroundColor:int;\t\t\t\t\t\t\t\/\/ Background color of button.\r\n\t\tprivate var _direction:Number;\t\t\t\t\t\t\t\t\/\/ Rotation of the UI.\r\n\t\tprivate var _mouseDownStartTimeDelay:Number = 350; \t\t\t\/\/ Initial delay before starting repeating MouseEvent.CLICK events.\r\n\t\tprivate var _mouseDownTimeDelay:Number = 100; \t\t\t\t\/\/ Delay between each MouseEvent.CLICK event.\r\n\t\tprivate var _mouseDownTimer:Timer; \t\t\t\t\t\t\t\/\/ Timer for repeating MouseEvent.CLICK events.\r\n\t\t\/**\r\n\t\t * Constructor\r\n\t\t * *\/\r\n\t\tpublic function DebugConsoleArrowButton()\r\n\t\t{\r\n\t\t\t_mouseDownTimer = new Timer(_mouseDownTimeDelay,0); \r\n\t\t\t_mouseDownTimer.addEventListener(TimerEvent.TIMER,mouseDownTimerEventHandler);\r\n\t\t\t_container.addChild(_backgroundRect);\t\t\t\r\n\t\t\t_backgroundRect.addChild(_triangle);\r\n\t\t\taddChild(_container);\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Handler for TimerEvent.TIMER event. Resets the delay interval once the default delay \r\n\t\t * is reached.\r\n\t\t * *\/\r\n\t\tprivate function mouseDownTimerEventHandler(event:TimerEvent):void \r\n\t\t{\r\n\t\t\tif (_mouseDownTimer.delay == _mouseDownStartTimeDelay)\r\n\t\t\t{\r\n\t\t\t\t_mouseDownTimer.delay = _mouseDownTimeDelay;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tvar e:MouseEvent = new MouseEvent(MouseEvent.CLICK);\r\n\t\t\tdispatchEvent(e);\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Sets enabled state.\r\n\t\t * *\/\r\n\t\tinternal function set enabled(enabledState:Boolean):void\r\n\t\t{\r\n\t\t\talpha = enabledState ? 1 : .25;\r\n\t\t\tif (enabledState)\r\n\t\t\t{\r\n\t\t\t\taddEventListener(MouseEvent.MOUSE_UP,mouseUpEventHandler);\r\n\t\t\t\taddEventListener(MouseEvent.MOUSE_DOWN,mouseDownEventHandler);\r\n\t\t\t\taddEventListener(MouseEvent.MOUSE_OUT,mouseOutEventHandler);\r\n\t\t\t}\t\t\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Handler for MouseEvent.MOUSE_OUT event. Stops the mouse down repeat timer.\r\n\t\t * *\/\r\n\t\tprivate function mouseOutEventHandler(e:MouseEvent):void\r\n\t\t{\r\n\t\t\t_mouseDownTimer.stop();\t\t\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Handler for MouseEvent.MOUSE_UP event. Stops the mouse down repeat timer.\r\n\t\t * *\/\r\n\t\tprivate function mouseUpEventHandler(e:MouseEvent):void\r\n\t\t{\r\n\t\t\t_mouseDownTimer.stop();\t\t\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Handler for MouseEvent.MOUSE_DOWN event. Starts mouse down timer.\r\n\t\t * *\/\r\n\t\tprivate function mouseDownEventHandler(e:MouseEvent):void\r\n\t\t{\r\n\t\t\t_mouseDownTimer.delay = _mouseDownStartTimeDelay;\r\n\t\t\t_mouseDownTimer.start();\r\n\t\t}\r\n\t\t\/**\r\n\t\t * Draw the button UI.\r\n\t\t * *\/\r\n\t\tinternal function draw(\r\n\t\t\tp_width:Number, \r\n\t\t\tp_height:Number, \r\n\t\t\tcolor:int,\r\n\t\t\tborderWidth:Number,\r\n\t\t\tborderColor:int,\r\n\t\t\tbackgroundColor:int,\r\n\t\t\tdirection:Number = 0):void\r\n\t\t{\r\n\t\t\t_width = p_width;\r\n\t\t\t_height = p_height;\r\n\t\t\t_color = color;\r\n\t\t\t_borderWidth = borderWidth;\r\n\t\t\t_borderColor = borderColor;\r\n\t\t\t_backgroundColor = backgroundColor;\r\n\t\t\t_direction = direction;\r\n\t\t\r\n\t\t\t_backgroundRect.graphics.clear();\r\n\t\t\t_backgroundRect.graphics.beginFill(_backgroundColor);\r\n\t\t\t_backgroundRect.graphics.lineStyle(_borderWidth, _borderColor); \r\n\t\t\t_backgroundRect.graphics.drawRect(0, 0, _width - _borderWidth, _height - _borderWidth); \r\n\t\t\t_backgroundRect.graphics.endFill();\r\n\t\t\t\r\n\t\t\t_triangle.draw( _width  , 0,_color, _color);\r\n\t\t\t_triangle.scaleX = _triangle.scaleY = .6;\r\n\t\t\t_triangle.x =  (_triangle.width \/ 2) + ((_width - _triangle.width - _borderWidth) \/ 2) ;\r\n\t\t\t_triangle.y =  (_triangle.height \/ 2) + ((_height - _triangle.height - _borderWidth) \/ 2);\r\n\t\t\t_triangle.rotation = _direction;\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>DebugTriangleShape Class<\/strong><br \/>\nUtility to draw a rectangle shape with a center registration point.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage com.lonhosford.util.debug.lite\r\n{\r\n\timport flash.display.Shape;\r\n\timport flash.display.Sprite;\r\n\t\/**\r\n\t * Utility to draw a triangle shape with a center registration point.\r\n\t * *\/\t\r\n\tpublic class DebugTriangleShape extends Sprite\r\n\t{\r\n\t\t\r\n\t\tpublic function DebugTriangleShape(\r\n\t\t)\r\n\t\t{\r\n\t\t}\r\n\t\tinternal function draw(\r\n\t\t\tsize:Number, \r\n\t\t\tborderWidth:Number,\r\n\t\t\tborderColor:int,\r\n\t\t\tbackgroundColor:int\r\n\t\t\t\t):void\r\n\t\t{\r\n\t\t\tgraphics.clear();\r\n\t\t\tgraphics.beginFill(backgroundColor);\r\n\t\t\tgraphics.lineStyle(borderWidth, borderColor);\r\n\t\t\tsize = size \/ 2;\r\n\t\t\tgraphics.moveTo(-size, size);\r\n\t\t\tgraphics.lineTo(-0, -size);  \r\n\t\t\tgraphics.lineTo(size, size );\r\n\t\t\t\r\n\t\t\tgraphics.endFill();\r\n\t\t\t\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>DebuggerEvent Class<\/strong><br \/>\nEvents for the <code>Debugger<\/code> class.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage com.lonhosford.util.debug.lite\r\n{import flash.events.Event;\r\n\t\/**\r\n\t * Events for the Debugger\r\n\t * @see DebugMessage\r\n\t * @see Debugger\r\n\t * *\/\r\n\tpublic class DebuggerEvent extends Event\r\n\t{\r\n\t\tpublic static const WRITE:String = &quot;debug.DebuggerEvent.Write&quot;;\r\n\t\tpublic var debugMessage:DebugMessage;\r\n\t\tpublic function DebuggerEvent(type:String, debugMessage:DebugMessage)\r\n\t\t{\r\n\t\t\tsuper(type, bubbles);\r\n\t\t\tthis.debugMessage = debugMessage\r\n\t\t}\r\n\t\toverride public function clone():Event \r\n\t\t{\r\n\t\t\treturn new DebuggerEvent(type, debugMessage);\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>DebugMessage Class<\/strong><br \/>\nThe data values sent with the <code>DebuggerEvent<\/code>.<\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage com.lonhosford.util.debug.lite\r\n{\r\n\t\/**\r\n\t * Data for a DebuggerEvent.\r\n\t * @see DebuggerEvent\r\n\t * *\/\r\n\tpublic class DebugMessage\r\n\t{\r\n\t\tpublic var text:String;\r\n\t\tpublic var lineNumber:Number;\r\n\t\tpublic function DebugMessage()\r\n\t\t{\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>DebugVersion Class<\/strong><br \/>\nA place to hold the static values for the code. <\/p>\n<pre class=\"brush: as3; title: ; wrap-lines: false; notranslate\" title=\"\">\r\npackage com.lonhosford.util.debug.lite\r\n{\r\n\t\/**\r\n\t * Common version data.\r\n\t * *\/\t\r\n\tpublic final class DebugVersion \r\n\t{\r\n\t\tpublic static const VERSION:String = &quot;1.00.01&quot;;\r\n\t\tpublic static const AUTHOR:String = &quot;Lon (Alonzo) Hosford&quot;;\r\n\t\tpublic static const AUTHOR_WEB_SITE:String = &quot;https:\/\/www.lonhosford.com&quot;;\r\n\t}\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>By Lon (Alonzo) Hosford I created this debug console for use in learning and teaching Actionscript programming. This is developed in pure Actionscript without component libraries. For that reason it can be used in Flash, AIR, and Flex. It will work in Flash IDE like Flash CS4 or Flex Builder. It also works creating Flash, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[19,12,9,40],"class_list":["post-587","post","type-post","status-publish","format-standard","hentry","category-general","tag-actionscript","tag-air-adobe-integrated-runtime","tag-flex","tag-singleton"],"_links":{"self":[{"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/posts\/587","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/comments?post=587"}],"version-history":[{"count":23,"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/posts\/587\/revisions"}],"predecessor-version":[{"id":3707,"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/posts\/587\/revisions\/3707"}],"wp:attachment":[{"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/media?parent=587"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/categories?post=587"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lonhosford.com\/lonblog\/wp-json\/wp\/v2\/tags?post=587"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}