tag:blogger.com,1999:blog-44379639459850340172008-07-26T07:59:20.555-06:00The Way of CodingScotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comBlogger32125tag:blogger.com,1999:blog-4437963945985034017.post-32924775380094477342008-07-23T19:36:00.005-06:002008-07-23T20:02:44.795-06:00Silverlight 2.0I was at a monthly .NET usergroup meeting yesterday. Larry Clarkin (<a target="_blank" href="http://larryclarkin.com/">http://larryclarkin.com/</a>) was there, and he was kind enough to give out quite a few copies of Visual Studio 2008. I was one of the ones who needed a copy. Never had the justification to buy it personally. Actually I am using 2005 at work too, but anyways...<br /><br />He talked about Silverlight 2. It has quite a few unique features that make it interesting enough to start "playing" around with. The most interesting aspect to me is the subset of the .NET framework embedded into the Silverlight runtime, which in turn means you can write Silverlight programs in C#/VB.NET (as well as a few other languages). Another plus is that it has built-in form controls. Put those two together and it could be interesting to make some rich web applications with not much difficulty. All this time I though it was just a Flash clone.<br /><br />Check out <a target="_blank" href="http://silverlight.net/">silverlight.net</a> for more of the specifics.Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-53369187266779249542008-05-15T20:17:00.005-06:002008-05-15T20:38:45.824-06:00Learning About .NET Web Access ClassesI mentioned about wanting to start a business in my previous post. Well it looks like I might have my chance. While it isn't exactly what I was thinking of in my previous post, I foresee many opportunities to flex my programming muscle in this endeavor. Plus, I will be starting up with a good friend, so there is a good chance our motivation will actually produce some results.<br /><br />A piece of software I am starting to research/design/create will be an internal application we will use to automatically extract some government provided public data. The current issue is time. With the amount of data and the requirement of using their web interface, it is not worth the time needed to do it by hand. The only other option would be to buy the data from the government, but that's just an unnecessary cost seeing as there is a free option available.<br /><br />So I will be writing a program in C# to automatically access a few websites and download the needed data in chunks. I have never delt with .NET's web access objects, so I started looking at what they have to offer today.... which looks like a lot.<br /><br />I modified an example from here:<br />http://msdn.microsoft.com/en-us/library/456dfw4f.aspx<br /><br />To do a simple test to see how reading a web page works in .NET.<br /><br />My revised code below:<br /><strong>Take note of the two windows form controls (webBrowser1) and (textbox1).</strong><br /><pre><br />//due to the finally statement, these variables need to be created outside the try block<br />WebRequest request = null;<br />WebResponse response = null;<br />Stream dataStream = null;<br />StreamReader reader = null;<br />try<br />{<br /> // Create a request for the URL. <br /> request = WebRequest.Create("http://page_to_access");<br /> <br /> // If required by the server, set the credentials.<br /> request.Credentials = CredentialCache.DefaultCredentials;<br /><br /> // Get the response.<br /> response = request.GetResponse();<br /> <br /> // Display the status.<br /> textBox1.Text = ((HttpWebResponse)response).StatusDescription;<br /> <br /> // Get the stream containing content returned by the server.<br /> dataStream = response.GetResponseStream();<br /> <br /> // Open the stream using a StreamReader for easy access.<br /> reader = new StreamReader(dataStream);<br /> <br /> // Read the content.<br /> string responseFromServer = reader.ReadToEnd();<br /> <br /> // Display the content.<br /> webBrowser1.DocumentText = responseFromServer;<br />}<br />catch (Exception error)<br />{<br /> Console.Write(error.ToString());<br />}<br />finally<br />{<br /> // Clean up the streams and the response.<br /> if (reader != null)<br /> {<br /> reader.Close();<br /> }<br /> if (response != null)<br /> {<br /> response.Close();<br /> }<br />}<br /></pre><br /><br />All it does is just request a webpage (only with get data) and then stream the response to a string. After that it takes the string and inserts it into the standard WebBrowser control. <br /><br />Next up I will setup/research:<br />- Searching the results from a web request.<br />- POSTing data to a page as apposed to using the get string<br />- Downloading files that are available from a webpage<br /><br />Should be interesting!Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-52592688070852103962008-05-04T17:46:00.004-06:002008-05-04T18:10:57.262-06:00JavaScript Tip: Submit Form On Enter KeyA common practice with search forms is to have them submit when the enter key is pressed, instead of requiring the user to use their mouse to press the submit button (or using tab key to tab to the submit button).<br /><br />Here is a simple way to do that in JavaScript:<br />First, define a input box:<br /><pre><br />&lt;input name="txtsearchentries" id="txtsearchentries" type="text" size="13" value="" /&gt;<br /></pre><br /><br />Second, create a function to be placed in the head area of the webpage:<br />//see if the user pressed the enter key while using a specific control<br /><pre><br />function submitSearchOnEnter(variable)<br />{<br /> var keyCode;<br /><br /> //get whatever key was just pressed<br /> //try to account for different methods of getting<br /> //event keys depending on implementation<br /> if(window.event)<br /> {<br /> keyCode = window.event.keyCode;<br /> }<br /> else if(variable)<br /> {<br /> keyCode = variable.which;<br /> }<br /><br /> //if the key was the enter key, perform the necessary function<br /> if(keyCode == 13) //13 = enter key<br /> {<br /> //here is where you process the form item or call a function to do that<br /> searchEntries(); //call search<br /> }<br />}<br /></pre><br /><br />Third, you need to assign the function above to to be an event handler:<br /><pre><br />//assign an event handler to the search box so we can have it<br />//submit when user presses enter<br />document.getElementById('txtsearchentries').onkeyup = submitSearchOnEnter;<br /></pre><br />That's it. Should be able to assign it similarly to other fields on the page too, but then you would need to think of how to create separate functions to handle each.Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-63173562869527957562008-05-01T20:51:00.004-06:002008-05-01T21:05:56.663-06:00Work and WorkWork has been frustrating me lately. I work with some people who have big ideas and not that much technical knowledge. Well that isn't the problem more then I have been working on things for multiple departments (outside of my core area) and they seem to all keep coming up with ideas for their respective projects. My boss is a nice guy and likes to please everyone, but that is pushing me towards feature creep hell. Ok, I'm exaggerating, but if you have ever had a job in software development you know the feeling.<br /><br />On a side note, I've been thinking more about the idea of my own software/web related business. I started looking into Code Igniter (codeigniter.com), which is an open source php framework that should help me save time in personal projects. Sure, I have a multitude of ideas, but getting that effort after work or on the weekends to actually accomplish something is difficult.<br /><br />頑張るよ as they say in Japan (will try my best!).Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-5785195004252560192008-04-10T19:27:00.007-06:002008-04-10T20:03:26.696-06:00Objects in JavascriptJavascript does not use a standard class model. It uses objects that are like associative array structures of data, or so I have read. Regardless of how it works, you can make a class-ish type construct in Javascript.<br /><br />I'll try to go over the basics here to help anyone who is interested.<br /><br />Objects are defined by creating a new function. Inside the function you can define variables and methods that are attached to the primary function. The primary function is really like the constructor for the object as well.<br /><br />For example:<br /><pre><br />function ObjectExample(constructorParameter1, constructorParameter2)<br />{<br /> //define a variable and assign a constructor value to it<br /> this.variable1 = constructorParameter1;<br /> this.variable2 = constructorParameter2;<br /> <br /> //you can also define variables with var, but they act differently<br /> var variable3 = this; //assigns an instance pointer to a "constructor" variable<br /><br /> //defines a function that is attached to the object<br /> //this function has one parameter<br /> //pretend that this.variable1 is a reference to a div element<br /> this.statusIndicator = function(statusText)<br /> {<br /> //make sure an element reference was returned before trying to set properties<br /> if(this.variable1 != null)<br /> {<br /> document.getElementById(this.variable1).innerHTML = statusText;<br /> }<br /> }<br /><br /> //you can also have a function with zero parameters<br /> this.aBoringFunction = function()<br /> {<br /> alert('YO!');<br /> }<br /><br /> //you can call an instance function from inside the "constructor" (aka. primary function)<br /> this.aBoringFunction(); //every time an instance is created we will get a pop-up<br />}<br /></pre><br /><br /><br />To use the object we just defined we would do something like this:<br /><pre><br />//create a new instance<br />var newObjectInstance = ObjectExample('7', divReference);<br /><br />//execute a object function<br />newObjectInstance.statusIndicator('Hello...');<br /><br /></pre><br /><br /><br />That's about it, let me know if I missed something, or there was an error. I typed the code out rather then copying something I know works for readability reasons.Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-26984384020417029312008-04-10T19:03:00.004-06:002008-04-10T19:26:25.087-06:00Javascript RantI've been working on something recently where I decided to have most of the program run in a client's browser. It's basically a blog system that works with that asp- xml-to-access-db class I released on here as an LGPL piece of code. The clients browser sends/requests information in XML to the server script and everything turned out peachy. I'm overall extremely happy with it.<br /><br />Now that I'm done writing the script. I learned quite a bit more about Javascript that I didn't know in the past. The initial few days of working with it were tragic. I'm not too fond of Javascript's "object" model and lack of a standard class model. While javascript works and provides a good deal of functionality, it feels "dirty." Maybe my fellow "old school" programmers can understand.<br /><br />Besides the object model, the DOM in general is a pain to work with, and hard to find information about (that works in multiple browsers). Inconsistencies, things that logically should work don't, and, trying ~5 different suggested methods to do something, but finding out that only 1/ 5 seems to actually work.<br /><br />If you don't agree with me, have you ever tried encapsulating XMLHttpRequest in a "class" object? There are a few gotchas that I stumbled on, which I hope to talk about in the future. <br /><br />My tip of the day about Javascript: Objects are functions are objects can be variables with no data hiding what-so-ever...Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-55877656403508502022008-03-29T00:44:00.006-06:002008-03-29T00:53:18.922-06:00Typos!I was just looking through my blog. I noticed quite a few typos and some terrible English. Ugh. Fixed what I saw, but I imagine there could be quite a bit more disbursed throughout the older posts.<br /><br />I must have been writing some of these posts in a daze or something. Honestly, I am a native English speaker if you thought otherwise! <br /><br />My educated guess as to the problem:<br />- My interest in Japanese is screwing up my language thought process a bit.<br />- The library of programming syntaxes I try to force into my memory.<br />- Not proofreading my posts 3+ times before posting them.Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-91501984973291844462008-03-01T08:56:00.009-06:002008-03-29T00:22:30.145-06:00DLL Files And .NET ClickOnce DeploymentI want to deploy one of my .NET apps as a ClickOnce application. The issue is that I am connecting to Oracle (see previous posts <a href="http://www.thewayofcoding.com/2008/02/c-net-programming-tip-connecting-to.html">here</a> and <a href="http://www.thewayofcoding.com/2008/03/c-net-programming-tip-oracle-connection.html">here</a>). Connecting to Oracle requires at least, 4 DLL files that generally have to be in the same directory as the EXE file. The issue is that when the program is published, the DLLs are not referenced in any way, so the program won't work.<br /><br />Then I read about adding the files to the project, so that ClickOnce and the Publish processor will figure out that the DLLs are required and add them to the manifest.<br /><br />Here is the process in Visual Studio 2005:<br />1. Put the 4 DLL files in their own directory in your solution directory (for ease of use mostly).<br />2. Add all four files to your project by going to "Project->Add Existing Item..."<br />3. Click on each DLL file in the solution explorer and then change their property: "Copy To Output Directory" to "Copy Always".<br /><br />That's it! Now when I publish or even run the application I don't have to worry about if the DLL files are where they should be.Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-36938092967962493082008-03-01T08:37:00.007-06:002008-03-29T00:26:13.941-06:00C# .NET Programming Tip: Oracle Connection RevisedNow that I have had more time to work with Oracle, I found a better way to connect then described in my <a target="_blank" href="http://www.thewayofcoding.com/2008/02/c-net-programming-tip-connecting-to.html">previous post</a>. With this new method you can connect to multiple instances in one program by getting rid of that tnsnames file.<br /><br /><span style="font-weight: bold;">*Remember that a project reference to System.Data.OracleClient must be added:</span><br /><pre><br />OracleConnection dbConnection;<br /><br />string connectionString = "Server=(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = *******)(PORT = 1521))(CONNECT_DATA = (SID = *****)));Persist Security Info=true;User Id=*****;Password=*****;";<br /><br />dbConnection = new OracleConnection(connectionString);<br /></pre><br /><br />It's really that simple. The key here is that the connection string must use the "Server" attribute instead of the "Data Source" one. I ran upon that while looking at the specification on Microsoft's MSDN documentation site.<br /><br />It's basically a tnsnames string with a few more attributes like user id and password. Just remember that:<br />host is the name of your server or ip address, sid is the name of your database meaning the *** part of ***.world, and of course the user id and password are your login credentials.<br /><br />There is another helpful step that <a href="http://www.thewayofcoding.com/2008/03/dll-files-and-net-clickonce.html">I will be posting about</a>. It relates to ClickOnce and the 4 DLL files that you need to connect to Oracle.Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-79714715577221682072008-02-21T06:47:00.004-06:002008-03-29T00:28:48.971-06:00C# .NET Programming Tip: TypesFiguring out a variable's type has become more important since now variables can be boxed by their parent class(s) (Where all can be "Object"). It's nice because it allows for one generalized function to work with many types that perform an action on a common attribute, or first figure out what the object is and then perform the action.<br /><br />That is one of the instances where figuring out a variables type is important.<br /><br />.NET has a built-in function called GetType() which figures out what type a variable is.<br /><pre><br />//loop through the controls in the panel anf figure out which of the checkboxes are checked<br />foreach (Control panelControl in newCheckListQuestionPanel.Controls)<br />{<br /> //only continue if this control is a checkbox<br /> if (panelControl.GetType().ToString().Equals("System.Windows.Forms.CheckBox") == true)<br /> {<br /> if (((CheckBox)panelControl).Checked == true)<br /> {<br /> //do something here if the control is checked<br /> }<br /> }<br />}<br /></pre>Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-66095804366037820952008-02-17T10:16:00.008-06:002008-03-29T00:37:21.146-06:00C# .NET Programming Tip: Connecting to an Oracle DatabasePlease view <a href="http://www.thewayofcoding.com/2008/03/c-net-programming-tip-oracle-connection.html">this post</a> for a better way to connect to Oracle.<br /><br />Ugh, I spent a good 6 hours figuring out how to do this! Hopefully this post can save someone some time. <br /><br />Connecting to an Oracle database requires driver files from Oracle. This is true no matter what you use in Visual Studio, it true for System.Data.ODBC or whatever else. This little factoid took me a while to figure out, as I didn't want to believe that I had to install a 200mb piece of software from Oracle just to connect to one of their databases.<br /><br />Well thankfully I didn't have to install their standard client. They offer an "instant client" that is quite a bit smaller. They even offer a lite version of the instant client, which is the one I decided to use. The bad thing about it is even that is around 20mb in size. <br /><br />You can download it here:<br /><a target="_blank" href="http://www.oracle.com/technology/software/tech/oci/instantclient/index.html">http://www.oracle.com/technology/software/tech/oci/instantclient/index.html</a><br /><br />Even downloading that I had issues. I tried downloading the 11.1.0.6.0 version of the Instant Client Lite, but I kept getting errors on their website, so I just settled for 10.2.0.3.<br /><pre><br />*Instant Client Package - Basic Lite: Smaller version of the Basic, with only English error messages and Unicode, ASCII, and Western European character set support (10.2 only)<br />instantclient-basiclite-win32-10.2.0.3-20061115.zip (10,360,970 bytes)<br /></pre><br />You only need the one zip file. The other ones like SDK and ODBC are not necessary unless you want to specifically use ODBC. This file above allows you to connect with using System.Data.OracleClient. In Visual Studio go to the menu item "Project->Add Reference..." and find System.Data.OracleClient in there and check it. All of the computers I have tried have the reference available (.NET 2.0 version). <br /><br />If for whatever reason it is not in there, Microsoft has their old .NET 1.1 version for download on their site <a target="_blank" href="http://www.microsoft.com/downloads/details.aspx?familyid=4f55d429-17dc-45ea-bfb3-076d1c052524&amp;displaylang=en">HERE</a>. Good luck finding the 2.0 version though.<br /><br />The instant client zip file you downloaded has a few files in it.<br /><br />We need these four:<br /><span style="font-weight: bold;">oci.dll</span><br /><span style="font-weight: bold;">orannzsbb10.dll</span><br /><span style="font-weight: bold;">oraocci10.dll</span><br /><span style="font-weight: bold;">oraociicus10.dll</span><br /><br />Place those into the directory of your project EXE. Most likely that will be in the "Project_folder/bin/debug". Of course once you publish your EXE, you will have to place the DLLs in their proper place. <br /><br />There is one other file you must have. It's called "tnsnames.ora" and is another thing that wasted a lot of my time figuring out. It basically tells the dlls where and how to connect to the database.<br /><br />Here is an example of a tnsnames.ora file:<br /><pre>AAAA.WORLD =<br />(DESCRIPTION =<br />(ADDRESS = (PROTOCOL = TCP)(HOST = XXXXXXXXXX)(PORT = 1521))<br />(CONNECT_DATA = (SID = AAAA)))<br /></pre>AAAA.WORLD is the Oracle database you are trying to connect to. The SID parameter is for older versions of Oracle. Just put the first part of your database name in there. The database at my job is using version 8 of Oracle, so the newer parameter called "SERVICE_NAME" would not work. The HOST parameter is where you put your IP address, or server name (say you have an oracle server named DBNINJA, just put that in there). The PORT 1521 is the default for Oracle, so if you have troubles, make sure your database administrator didn't change the port.<br /><br />What I'm hoping to figure out eventually is how to input this information in the connection object in Visual Studio, without having this file (ed: done, see <a href="http://www.thewayofcoding.com/2008/03/c-net-programming-tip-oracle-connection.html">newer post</a>). This thing doesn't make sense, because programs should be able to connect to more then one database instance. Anyways, I'll have to do more research on that and post my finding here in the future. This whole tnsnames.ora file seems like a bad idea.<br /><br />Now here is how to connect to the database in Visual Studio 2005:<br /><pre><br />using System.Data.OracleClient;<br /><br />...<br /><br />StringBuilder tableList = new StringBuilder();<br /><br />try<br />{<br /> using (OracleConnection testConnection = new OracleConnection("Data Source=AAAA.WORLD;Persist Security Info=true;User Id=******;Password=******;"))<br /> {<br /> testConnection.Open();<br /><br /> using (OracleCommand testCommand = testConnection.CreateCommand())<br /> {<br /> testCommand.CommandText = "SELECT TABLE_NAME FROM ALL_CATALOG";<br /> testCommand.Prepare();<br /><br /> using (OracleDataReader testReader = testCommand.ExecuteReader())<br /> {<br /> while (testReader.Read())<br /> {<br /> tableList.Append("Table: " + testReader.GetString(0) + "\r\n");<br /> }<br /> }<br /> }<br /> <br /> testConnection.Close();<br /> }<br />}<br />catch (Exception error)<br />{<br /> System.Windows.Forms.MessageBox.Show(error.ToString());<br />}<br /><br />txtDisplay.Text = tableList.ToString();<br /><br /></pre><br />Notice that the data source points to the same place as the tnsnames.ora file. Also, the connection string here is where you place your username and password. After creating the connection object, you open the connection and perform some sql with a command object.<br /><br />Also take note that I am using ... "using" statements. These automatically close and unset the objects after they have been used. It saves a lot of hassle!<br /><br />The SQL statement "SELECT TABLE_NAME FROM ALL_CATALOG" fetches a list of every table that is available to the user and returns the name of each one.<br /><br />The StringBuilder tableList I am using is just a faster way of concatenating strings.<br /><br />That's it for now. I'm sure I will be doing a lot more with Oracle in the future, so I will probably have a lot more to write about here as well.Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-67717161142899529862008-02-16T16:10:00.005-06:002008-03-29T00:39:55.028-06:00C# .NET Programming Tip: Keeping A History With PropertiesThe program I am writing at work's primary functionality is a checklist. One of the requested features is the ability to record what actions a user performs on the checklist. So there needs to be some additional code that updates a history table whenever a user makes any changes to the checklist. <br /><br />Let's define when a history event should fire off:<br />When the user makes a new checklist.<br />When the user updates any property of the checklist.<br />When a user archives a checklist (eg: discard in so many works).<br /><br />Making a history entry when the user makes a new checklist or archives a checklist is easy. There would generally be only one function for each, so just before or after adding or archiving the checklist from the database, the history process is called.<br /><br />What about when the user updates a single field in a checklist? It is important to track those changes, because a single little change is generally the most important (he said, she said situation).<br /><br />In my program checklistprocessor, checklist, checklistitem, history, and database are all separate objects. So what would be an easy way to update each property individually and also record the before/after state in a history entry?<br /><br />Use properties!<br /><br />Here is an example of one such property:<br /><pre><br />class CheckListItem<br />{<br /> private int id;<br /> private int checkListId; //foreign key to CheckList<br /> private string notes;<br /> ...<br /><br /> //will hold a reference that is received from a calling object<br /> private Database dbConnection;<br /><br /> public string Notes<br /> {<br /> get { return this.notes; }<br /> set<br /> {<br /> //create history entry for this change<br /> History.add(id, checkListId, this.notes, value);<br /> <br /> //update instance variable<br /> this.notes = value;<br /> <br /> //update database with new value<br /> dbConnection.queryNoResult("UPDATE ... WHERE... ;")<br /> }<br /> }<br /><br /> ...<br /></pre><br />Remember that C# is case sensitive. That means we can have a Notes property and a notes class variable. It makes things a lot simpler naming wise and is, from what I have read, an unofficial standard practice.<br /><br />As you can see from the code, all the checklist has to do to update a checklistitem variable called "notes" is call the property Notes. Everything else is handled by the set method.Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-27631985849759195102008-02-16T13:07:00.005-06:002008-03-29T00:40:54.617-06:00C# .NET Programming Tip: FlowLayoutPanel Mouse Scroll Wheel Not WorkingAhh, some if you may notice that the mouse scroll wheel doesn't work by default with FlowLayoutPanels. Yeah, this little thing has frustrated me for a while.<br /><br />I usually check the Internet for solutions to problems I have been having. Most likely someone has posted on a message board about the same problem and the problem was solved. Sadly, this method of finding information can lead to numerous dead ends as people don't post the solution (eg: "Hey I figured it out!") and fail to say what they did. Or the solution they figure out isn't "good." Of course, programming blogs are also a good resource with generally higher quality information, but they don't seem to be as prevalent in search engines for some reason. Maybe blogs are generally lower traffic?<br /><br />Like I said before, one such issue I was having was with FlowLayoutPanels and the mouse scroll wheel not scrolling them when the panels had scroll bars. Doing a search on the internet came up with close to nothing. Most "solutions" were to create your own functions to catch MouseEventArgs from the Form and perform the scroll on the FlowLayoutPanel yourself with scrolling code. Far from the best solution...<br /><br />It didn't make sense. The panels have all of the events necessary to scroll themselves, but they were not working. Then I came into some luck and found someone talking about the same problem I was having. They suggested that the FlowLayoutPanels were not able to get focus, so that's why they would not scroll. Pure genius! They added one line of code to the Click event to whatever panel they wanted to scroll. Not really ideal as the user would have to know to click on the panel before they could scroll it. I took it one step further. Check out the code below.<br /><pre><br />private void newCheckListQuestionPanel_Click(object sender, EventArgs e)<br />{<br /> newCheckListQuestionPanel.Focus(); //allows the mouse wheel to work after the panel is clicked<br />}<br />private void newCheckListQuestionPanel_MouseEnter(object sender, EventArgs e)<br />{<br /> newCheckListQuestionPanel.Focus(); //allows the mouse wheel to work after the panel has had the mouse move over it<br />}<br /></pre><br />In Visual Studio, select the panel in the visual design window, and click the Events button in the properties window to find a list of events the control can do. I added events for Click and MouseEnter. Click probably isn't necessary, as <span style="font-weight: bold;">MouseEnter is really the star of the show here.</span> Everytime the user moves the mouse over the FlowLayoutPanel, the control receives focus, allowing the mouse wheel to work!<br /><br /><span style="font-weight: bold;">Yeah, it's that simple.</span>Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-55145316344338378422008-02-16T12:11:00.005-06:002008-02-16T13:05:27.682-06:00C# .NET Programming Tip: Using the Tag property of controlsI've been doing C# programming at my job lately. Throughout the process I've hit a few little walls that were difficult to find answers for and thought writing down the solutions here would be good for myself any anyone who happens to find this by-way-of search engine. So as I come upon these little bits of useful harder-to-find information, I'll write something here about it.<br /><br />Creating windows form controls programmatically and passing data between class instances was one such issue. I did a number of searches on Google and didn't really find much help. The main suggestion was to create an EventArgs class that passes events or some such thing. That was a really involved process that didn't seem like it was worth the effort to implement.<br /><br />I then created my own static global event class where anything in the program could pass an unlimited number of parameters. Once the parameters were accessed, they were deleted from the static Dictionary that stored everything. Well actually it was a Dictionary inside a Dictionary (parameterSetName -> (Dictionary that holds all parameters)). So it was a one shot wonder.<br /><br />Let me give a little background information about why I needed to implement it:<br />I had a number of classes that generate their own windows controls to select or edit themselves. For example, A "checklist container" created controls to allow the user to select one specific checklist. The function was called with a reference to a FlowLayoutPanel. Then when the user clicked a button to select one specific checklist, the container class would call a function inside the selected checklist instance to tell it to display edit controls for itself. The problem was passing that FormLayoutPanel reference to the checklist function from an event function that I linked to the buttons that were dynamically generated. <br /><br />There was really no easily noticeable way to do it. Every button the Container class created was all linked up into one Event function. The way .NET works is that you can create your own event function, but only two specific parameters are passed (one is the control itself, in the sender parameter).<br /><br />So that is why I created that static global parameter class. The thing is I ran into another roadblock that made the global parameter class useless. They way I designed it is that the parameters were deleted from the Dictionary object once some function accessed them, but what if I wanted a form that did a similar process, but did not completely replace the current controls with something new (eg: the single checklist edit controls needed to perform actions like reading data from textboxes that were created at runtime. The function that would take events from the buttons on the edit form had no way of accessing textboxes at this point.<br /><br />I go back on Google and Yahoo! and do a few more searches. This time I come upon the Tag property of Windows Form Controls. It's an object variable that you can put anything into and it works perfectly for what I was trying to do.<br /><br />By this point you probably are having a hard time understanding what I am talking about. So here are a few code examples to help you out:<br /><br />The way my program works is that checklist has multiple checklist items and each checklist item has a few windows form buttons that should do things.<br /><br />This is a button that would fire off a request to update a database data from a textbox:<br /><pre><br />Button btnNotesChance = new Button();<br />btnNotesChance.Text = "Update Notes";<br />btnNotesChance.AutoSize = true;<br />pnlTxtBoxes.Controls.Add(btnNotesChance);<br />btnNotesChance.Name = "clintsbx-" + i.ToString(); //save a name so we can know who calls the event handler<br />btnNotesChance.Tag = txtNotes; //save the handle to the notes textbox into the button's "tag" variable<br />btnNotesChance.Click += new EventHandler(displayChecklistAsControls_Event);<br /></pre><br /><br />Notice the Name property. I give it a unique identifier clintsbx-#, so that way I can know which "Update Notes" button was clicked in the function displayChecklistAsControls_Event. I'll get to the event function later. Also notice the Tag property. That stores the handle to the button's related TextBox "txtNotes" object (windows form textbox). So now when the button is clicked we will know who called the update and what textbox to take the information from!<br /><br />Here is an excerpt from the event function:<br /><pre><br />private void displayChecklistAsControls_Event(Object sender, EventArgs e) //event handler for the checklist selector buttons<br />{<br /> //fetch the calling control<br /> Control senderControl = (Control)sender;<br /><br /> //take the calling control's name and split it up into two parts, one means the type of control and the other means<br /> //the index of the control (eg: ollststatu-4 means the 4th listbox for checklistitem status)<br /> string [] nameData = senderControl.Name.Split(Convert.ToChar("-"));<br /><br /> //turn the second array value into an integer<br /> int itemSelected = Convert.ToInt32(nameData[1]);<br /></pre><br /><br />As you can see there the sender variable is key. We can use that to get access to the button that called the event. Then we can take the Name of the control and the Tag of the control and do what we need to do.<br /><br />I perform a Switch on the first nameData item to decide which set of controls called the event. Here is some code below for "update notes" I have been talking about.<br /><pre><br />case "clintsbx":<br />//take the notes textbox data and save it to the corresponding checklistitem notes field<br />//utilizes the button's tag element to save a reference to the corresponding textbox<br />string selectedItemText = ((TextBox)((Button)senderControl).Tag).Text;<br />//only update if the user made some type of change<br />if (checkListItems[itemSelected].Notes.Equals(selectedItemText) == false)<br />{<br /> //update the instance and database with this text data<br /> checkListItems[itemSelected].Notes = selectedItemText;<br />}<br />break;<br /></pre><br /><br />It takes the button's Tag property and turns that into a reference to the textbox. Then it is able to access the Text property of the textbox and then update the database.<br /><br /><span style="font-weight:bold;">Problem solved!</span>Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-77728832487570297472008-01-27T20:08:00.002-06:002008-03-29T00:44:12.754-06:00Is object orientated scripting worth the effort?I'm currently creating a movie review website in PHP an SQLite. I'm taking a very object orientated approach.<br /><br />For example, all database access goes through an object. Adding a review is as simple as calling a function with the proper data.<br /><br />Here is the function header:<br /><pre>addReview($assocArrayReviewData, $assocArrayReviewBlockData)<br /></pre>Each parameter is an associative array that corresponds to fields in the database. While I don't want to get into too much detail, the second variable is actually an array of arrays, where each one holds a block of review information (eg: "What the box says", "funny quotes", "My thoughts").<br /><br />The best thing about is is that once I create the administration interface I can just call that one function with the correct parameters and bam, a new review.<br /><br />The class also has a built-in search function (that could be used on the internal or external site).<br /><br />My next class that I created for primarily for the administration area. It's an html tag class object. You might me thinking, what's the point of mimicking html tags? Well in my never ending quest to separate html from code, this object can be instantiated instead of writing html dispersed through the script code. Please forgive me on the naming. I'm not quite sure what to call the class yet. I first called a "form" class, then a "control" class, and then once I realized it could be used for anything... the "htmlTag" class. Well anyways, it does what I want it to do regardless of what it is called.<br /><br />Here is a quick example of code that would call it:<br /><pre><br /><span style="font-weight: bold;">$test = new HtmlTag('test', 'form');</span><br /><span style="font-weight: bold;">$test->setAttribute('method', 'post');</span><br /><span style="font-weight: bold;">$test->createSubControl('button1', 'input');</span><br /><span style="font-weight: bold;">$test->subControl('button1')->setAttribute('type', 'button');</span><br /><span style="font-weight: bold;">$test->subControl('button1')->setAttribute('value', 'Click Here!');</span><br /><span style="font-weight: bold;">echo $test->toHtml();</span><br /></pre><br />Any idea what it does?<br /><br />It creates this:<br /><pre><span style="font-weight: bold;"><form name="test" method="post"></form><br /><span style="font-weight: bold;"><input name="button1" value="Click Here!" type="button"></span><br /><span style="font-weight: bold;"></span></span><br /></pre>Pretty cool, eh? The whole class is a beefy ~220 lines. haha<br />Now I can create forms programmatically that can have an unlimited number of parent/children/sub-children to them. So a form can hold a select box, that holds option tags... etc.<br /><br />Here is a bit of the class file:<br /><pre><br /><span style="font-weight: bold;">class HtmlTag</span><br /><span style="font-weight: bold;">{</span><br /><span style="font-weight: bold;"> //strings:</span><br /><span style="font-weight: bold;"> private $controlType; //stores the type of control (this should correspond to an actual html tag)</span><br /><span style="font-weight: bold;"> private $innerHtml; //hold any text or whatever inside the control's start and end tags</span><br /><span style="font-weight: bold;"> </span><br /><span style="font-weight: bold;"> //associative arrays:</span><br /><span style="font-weight: bold;"> private $attributes; //hold all of the attributes of the control (eg: onsubmit='' onclick='' style=''...)</span><br /><span style="font-weight: bold;"> </span><br /><span style="font-weight: bold;"> private $subControls; //holds sub controls (eg: form has controls inside it, select control has options inside it)<br /><br />..................<br /><br /> function &amp;subControl($name)<br /> {<br /> return $this->subControls[$name];<br /> }<br /><br />}<br /></span><span style="font-weight: bold;"> </span><br /></pre>The subControl function is key to accessing children and sub-children of the main object. I wanted to keep the array subControls private, so that function is necessary.<br /><br />Now that I have that class created I will start designing the administration interface, that now, is just a shell that accesses these two classes.<br /><span style="font-weight: bold;"></span>Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-32553619999592099202007-08-10T21:10:00.000-06:002007-08-10T21:55:29.069-06:00Drupal: CMS Migration To A ServerI've been modifying Drupal (drupal.org) for a neighborhood organization website. It took a little research as, like most similar open-source projects, the documentation leaves something to be desired. I now have the site to a point where I want to put it up on the Internet. I have some hosting, so I got the domain... and bam, it's on the web right? Well no.<br /><br />I feel it is necessary to make a general process overview as it took a good deal of research and tweaking to get it working:<br />-I have "reseller hosting." That means I can host multiple domains with the space/bandwidth that comes with the yearly fee. I bought the neighborhood domain, added a special hosting plan (defines storage, bandwidth, and other properties), and tried configuring the dns information<br /><br />-Seeing as I have not done too much with the whole domainname-dns-nameserver-whatever configuration process I had some trouble figuring it out. What I ended up doing was having my domain name registrar create 2 name servers from the IPs that link to the hosting server(s). Then I used the hosting's name servers as well. ns1.site.com, ns2.site.com, ns1.hosting.com, ns2.hosting.com... all being able to process the name translation. On the hosting side for "editing DNS Zones" I set it up with ns1.nameservice.com as NS records, the IP as and 'A' record, the www as a cname for site.com.... etc. Most of the data was preconfigured by cPanel, but for some reason I had to change a few things from the defaults to get it working properly. This whole aspect will take a lot more research to understand fully.<br /><br />-Copy by hand or install Drupal from cPanel (assuming your host uses cPanel)<br /><br />-If you are developing on a windows machine, make sure you reconfigure your temporary directory from c:\windows\temp to /tmp. Drupal will most likely make a folder for you. I didn't do this the first time and it made a crappy "c:\windows\www" folder on the server that was a pain to remove.<br /><br />-Login into your local mysqladmin (assuming you use that to manage your sql databases) and make a backup of your local Drupal database. I had to set the compatibility to an earlier version of mysql. For some reason at the default options for the export would not work.<br /><br />-If you installed from cPanel, drop all of the tables in the pre-created Drupal database before you import the backup file. Otherwise, create a sql user and database for Drupal (make sure to add the user to the database access list). Configure the settings.php file in the Drupal files to reflect the database information (there is a connection string in the php file).<br /><br />-Copy over any themes or modules that you added to your local Drupal install. I didn't bother with the hassle that is the sites directory... Just put the modules and theme into the standard directory instead.<br /><br />-Configure your www-root .htaccess file on the server to reflect things like url rewriting, default page (index.php), and standardizing the site path (only allowing www.site.com, not site.com or vice versa). More specifically the properties DirectoryIndex, RewriteEngine, RewriteCond, and RewriteRule<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_4AXQMiy0n-g/Rr0zIPWwbLI/AAAAAAAAAGM/gyEj1wmywRI/s1600-h/orch_ex_s1s.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp3.blogger.com/_4AXQMiy0n-g/Rr0zIPWwbLI/AAAAAAAAAGM/gyEj1wmywRI/s320/orch_ex_s1s.jpg" alt="" id="BLOGGER_PHOTO_ID_5097286569907219634" border="0" /></a>Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-62077420905199662012007-03-03T00:02:00.000-06:002007-03-03T01:02:25.955-06:00Using blogger.com as a website instead of a blogThanks to the new functionality I am able to use the free blogger.com blogs as a website. It's all thinks to functionally they added after Google acquired them. For example I created a custom template for my sister's graphic/fashion/photography design website. In this post I'll go over the basics that allow this to work.<br /><br />1. Google allows custom domain names. This means the whole website can have a professional look and feel because all links connected to the site will look like www.nameofsite.com/revrefvrv/dfvdfvd... etc.<br /><br />2. The use of labels, conditional statements, and the database data that blogger allows to be accessed through the template system.<br /><br /><br />To make a standard website I started with the simplest of the pre-created templates modifying it to suit my needs. I removed a lot of the functionality like comments, backlinks, and whatever else.<br /><br />For a basic website you first need some links to blocks of site content. I generally hard code them into the template. Now if you've used the new blogger template system on a lower level (eg. the code level and not the drag and drop stuff) you will notice a few quips. They process any hard coded html data depending on where you put it, so you have to be careful what/where you place directly code into the template. Otherwise you can add "html/JavaScript" widgets to add whatever code functionality you want. The only problem with this is that all of that code you add is stored in the database and not the template. That kind of irritates me because it's a pain to backup.<br /><br />So I will add something like this where I want the menu to be:<br /><pre> &lt;div class='divmenu'&gt;<br /> &lt;span class='spanmenuitem'&gt;<br /> &lt;a href='http://www.site.com/search/label/Whats%20New'&gt;What's New&lt;/a&gt;<br /> &lt;/span&gt;<br /> &lt;span class='spanmenuitem'&gt;<br /> &lt;a href='http://www.site.com/search/label/Fashion%20Design'&gt;Fashion Design&lt;/a&gt;<br /> &lt;/span&gt;<br /> &lt;/div&gt;<br /></pre><br /><br />As you can see, those are just hard coded links. It uses the label search functionality to find all posts that have that specific label attached to it.<br /><br />So now you have links to site content on every page. Now we want to have a special page display only when the user goes to www.site.com... aka. the index page.<br />You will have to find the post section of the template:<br /><pre><br />&lt;b:widget id='Blog1' locked='true' title='Blog Posts' type='Blog'&gt;<br />&lt;b:includable id='main' var='top'&gt;<br /> &lt;div id='divcontentsection'&gt;<br /> &lt;!-- display the index page, or something else --&gt;<br /> &lt;b:if cond='data:blog.url == data:blog.homepageUrl'&gt; <br /> &lt;div id='divindexpage'&gt;<br /> This is the index page!<br /> &lt;/div&gt;<br /> &lt;b:else/&gt;<br /> &lt;b:loop values='data:posts' var='post'&gt;<br /> &lt;b:include data='post' name='post'/&gt;<br /> &lt;/b:loop&gt; <br /> &lt;/b:if&gt;<br /> &lt;b:include name='nextprev'/&gt;<br /> &lt;/div&gt;<br />&lt;/b:includable&gt;<br /></pre><br /><br />Key points to note is the conditional statement checking 'data:blog.url == data:blog.homepageUrl'. Every time the website is accessed it checks to see if the current page is the index page if it is it will display some html code, otherwise it will process site site as it generally would (show posts).<br /><br /><br />Now we have to figure out how to use labels to process the site content like a website would. I will talk through what I wanted to accomplish. After that will be the block of code that accomplishes the task.<br /><br />* When a user clicks on a hard coded link to "Graphic Design", I wanted it to display a list of post titles only related to graphic design, no actual content. Each title could be clicked on to go to that specific post. That means you need to have "Enable Post Pages?" set to YES in Settings->Archiving. Every post made has a unique link associated with it. It allows us to to use conditional statements to figure out to display the post content or not depending on what page they are on.<br /><br />* I wanted to create html breadcrumbs. This is a goofy term for links that show your level of deepness in the site. For example "Home > Graphic Design > Ninjas" show what path the user took to get where they are. Each one can be clicked on so they can jump back. This is easily possible with blogger as you will see in the code later.<br /><br />* Another thing is that I still want regular blog functionality in the site. When the user clicks on the "Whats New" link they should be shown all posts (title, content, everything...). All this takes is a quick check of what label the post has before it is processed.<br /><br />Here is the code of the post includable that's linked to from the previous code shown:<br /><pre><br />&lt;b:includable id='post' var='post'&gt;<br /> &lt;div class='post'&gt;<br /> &lt;!-- this post functionality only works if there is ONE label --&gt;<br /> &lt;!-- look for special cases like whats new, we want that to display like a regular blog --&gt;<br /> &lt;!-- if it is a special case, display the content as well as the title+link --&gt;<br /> &lt;b:loop values='data:post.labels' var='label'&gt;<br /> &lt;b:if cond='data:label.name == "Whats New"'&gt;<br /> &lt;div class='divpostbody'&gt;<br /> &lt;p&gt;<br /> &lt;b:if cond='data:post.dateHeader'&gt;<br /> &lt;h2&gt;&lt;data:post.dateHeader/&gt;&lt;/h2&gt;<br /> &lt;/b:if&gt;<br /> &lt;h3&gt;&lt;a expr:href='data:post.url'&gt;&lt;data:post.title/&gt;&lt;/a&gt; - &lt;data:post.timestamp/&gt;&lt;/h3&gt;<br /> &lt;p&gt;<br /> &lt;data:post.body/&gt;<br /> &lt;/p&gt;<br /> &lt;/p&gt;<br /> &lt;div style='clear: both;'/&gt; &lt;!-- clear for photos floats --&gt;<br /> &lt;/div&gt;<br /> &lt;b:else/&gt; <br /> &lt;!-- if this is not a single item, display only the title and link of each item --&gt;<br /> &lt;b:if cond='data:post.url == data:blog.url'&gt;<br /> &lt;!-- START display breadcrumb links --&gt;<br /> &lt;h4&gt;<br /> &lt;a expr:href='data:blog.homepageUrl'&gt;Home&lt;/a&gt; | <br /> &lt;b:loop values='data:post.labels' var='label'&gt;<br /> &lt;a expr:href='data:label.url'&gt;&lt;data:label.name/&gt;&lt;/a&gt;<br /> &lt;/b:loop&gt; | <br /> &lt;a expr:href='data:blog.url'&gt;&lt;data:post.title/&gt;&lt;/a&gt;<br /> &lt;/h4&gt;<br /> &lt;!-- END display breadcrumb links --&gt;<br /><br /> &lt;h3&gt;&lt;data:post.title/&gt;&lt;/h3&gt;<br /> &lt;div class='divpostbody'&gt;<br /> &lt;p&gt;&lt;data:post.body/&gt;&lt;/p&gt;<br /> &lt;div style='clear: both;'/&gt; &lt;!-- clear for photos floats --&gt;<br /> &lt;/div&gt;<br /> &lt;b:else/&gt;<br /> &lt;h3&gt;&lt;a expr:href='data:post.url'&gt;&lt;data:post.title/&gt;&lt;/a&gt;&lt;/h3&gt; <br /> &lt;/b:if&gt;<br /> &lt;/b:if&gt;<br /> &lt;/b:loop&gt; <br /> <br /> &lt;/div&gt;<br />&lt;/b:includable&gt;<br /></pre><br /><br />It took me about 2 days to research and code the necessary functionality. Blogger's current documentation on their template system leaves something to be desired. Hopefully they will improve on that. Anyways, that's about it for the template! Now you should have a fully functional informational website that still has blogging functionality.<br /><br />The code is a pain to paste into here, so if you have some troubles getting it to work, let me know.Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-42388077082206987322007-03-02T23:34:00.000-06:002007-03-02T23:53:01.142-06:00No surprise, the custom CMS was put on the back burnerAs I mentioned in the previous post I had my custom CMS site reasonably functional. From that time as I worked with the director, I found out that they were using a CMS system already. No point in trying to reinvent the wheel as it's said. It's called Sohoadmin and it works pretty well all things considered. I would not call it that user friendly, but seeing as I am doing volunteer work I don't want to spend 2-3 months creating my own thing that I would also then have to provide technical support to in the future.<br /><br />It's been an interesting process so far getting them where they need to be. The person who they were working with before isn't very motivated to help them and it was showing (he hosts the server too). I wanted to get Sohoadmin upgraded to the newest version, but when he tried to do that it did not work correctly resulting in me sticking some band aids on the site to get it somewhat functional again. <br /><br />Now we are to the point that we bought our own hosting and are in the process of getting the .org name transfered to us. We have the site completely functional with the .net name, but seeing as the .org has been advertised so much it's best that we use that instead.<br /><br />Eventually I foresee this organization I am volunteering at being able to be in control of their own web presence. It should save them a lot of time and heart ache by cutting out the middle man.<br /><br />I recently started working on my CMS site again. I want to get it completed just for the fun of it. Right now I have the article functionality about half way there. Next up would be the image gallery functionality. Onward!Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-21005863679629637392007-02-03T22:09:00.000-06:002007-02-04T17:11:56.951-06:00CMS/site project status1149 lines of code so far. That's not including and database file initialization code or other things such as the css for the public site.<br /><br /><span style="font-weight:bold;">Completed ("somewhat tested"):</span><br />- Add/edit main page links<br />- Add/edit/delete main page basic html content blocks<br />- Visual template system and the final visual look of the site.<br />- Public index.php looks "done" visually. The main links work and display all basic - content blocks when clicked (ordered by 'zorder'). It's just lacking sub links (articles and galleries).<br /><br /><span style="font-weight:bold;">To Be Completed:</span><br />- Delete main page links (I haven't decided if I want it to do a recursive deletion of all content associated with it or not).<br />- Add/edit/delete articles (aka. multipage basic html content blocks).<br />- Add/edit/delete image galleries.<br />- Make the admin pages secure.<br />- Testing, testing, and more testing!<br /><br />I've been thinking of not bothering with an image gallery aspect. The multi page articles would have similar abilities to a photo gallery. The only difference is that it could not support the thumbnail->large image functionality.<br /><br />Edit: I was thinking of adding a global error handler that pipes all errors into a 50 - 100 item large database table. This table would be viewable from one of the admin pages. It would save a lot of effort debugging second-hand problem information.<br /><br /><br /><span style="font-weight:bold;"><br />Here is a sample of the site:</span><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_4AXQMiy0n-g/RcVgkLOgspI/AAAAAAAAAA0/1WWRv7dzozo/s1600-h/cfweb1.gif"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_4AXQMiy0n-g/RcVgkLOgspI/AAAAAAAAAA0/1WWRv7dzozo/s400/cfweb1.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5027530733634237074" /></a>Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-58010133003561850112007-02-02T18:08:00.000-06:002007-02-02T18:45:30.135-06:00Accessing page content from the front and back-end of a siteAs I'm programming this database driven website, I've come into a few irritating little issues. Today I'll talk about a few methods to access page content (images) from the back-end. <br /><br />I've created a way to create and edit page content with a browser based WYSIWYG editor. The problem is after the first time the data is submitted to the server, all images are set with a path that now only works from the root directory of the website. So when a user tries to edit some page content with images in the WYSIWYG editor they see broken images (aka. "The dreaded Red X").<br /><br />I thought of a few ways to fix the problem. I'll also mention which method I actually used in the end.<br /><br />1. Have the PHP script handle the path conversions. This would mean two functions or so with a few replacements using regular expressions. So when the fetched data is sent to the user all of the html image tags are modified. When or if the user sends the data back they are remodified (excluding any new images the user is submitting). This is probably the safest bet.<br /><br />2. Create a synaptic link if the server is on Linux/Unix. For example if the site root is www/, the site editor is in www/editor, and the content is in www/images. You would create the synaptic link in the www/editor directory linking to www/images directory. Probably the easiest solution by far, but I want my site to work on both Windows and Linux/Unix servers if possible. I'm developing the site on Windows, so I did not try this, but I'm pretty sure it would work. I also know that windows has a way to create similar links, but it seems like a pain to use so I didn't bother.<br /><br />3. Use JavaScript to handle the temporary conversion. This is the route I picked. I was just looking for something quick that worked and this was it. Well it wasn't exactly quick because I spent a few minutes researching what function I needed to use and exactly how it works. The tutorials I saw were lacking...<br /><br />Here is an example of the code that will do the initial edit, so the user can see the images in the WYSIWYG editor:<br /><pre><br />function fixImagePaths(textAreaId)<br />{<br /> var tempHtmlData = document.getElementById(textAreaId).value;<br /> tempHtmlData = tempHtmlData.replace(/(&lt;img\s.*src=")(images\/[^"]*"\s.*&gt;)/gi, '$1/../$2');<br /> document.getElementById(textAreaId).value = tempHtmlData;<br />}</pre><br /><br />The KEY problem that took me a few minutes to figure out was that the first parameter (the regular expression) in the replace function can't have any type of quotes around it. If you've never heard of regular expressions, I highly suggest that you read up on them. They are extremely useful in a multitude of applications. Anyways, what that function does is take data from a wysiwyg html textarea and search through the whole thing for img tags. When it finds one that has a src directory that starts with "images/" it replaces it with "/../images", this gets the browser to jump back a directory to find the right path to the image folder.<br /><br />I have this function execute on the body onload event. I'll also have a second similar function execute on the form onsubmit event. This solution seemed a bit easer then the php one. Well that's it for now!Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-61882859592794715442007-01-30T09:46:00.000-06:002007-01-30T10:04:19.454-06:00Finally got moving on something...From the previous posts it's easy to notice that I've been searching for an efficient way to code large web projects. While I am still open to frameworks and such I had something happen that kind of "brought me back to my roots." I have the job of making a website for a not-for-profit organization in my area. I decided that they should have something easy to update, so that means a data driven site with a back-end. I don't want to use premade systems because they have too many things I don't want included. I therefore decided to go with what I've worked with in the past which is straight PHP.<br /><br />More specifically PHP5+ and the SQLite database engine. PHP5 perfects a good deal of useful features over the older versions such as the class/object model. It also adds support built-in for the file based SQLite engine. For what I am creating, SQLite takes out a lot of the unnecessary complexity of using MySQL.<br /><br />I've got the database and general site design "done". I also have a nice chunk of the back-end working. I integrated an open source browser based wysiwyg html editor, so updating the site will be a breeze. I also plan on adding functionality for multi-page events/articles and image galleries.<br /><br />I'm pretty happy with the results so far. It might be taking me longer by designing and coding a basic content management system myself, but I get the exact result I want without the added fluff of premade stuff.<br /><br />I might be going into more detail later, so look forward to that!Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-2767479683910494242007-01-11T14:05:00.000-06:002007-01-11T21:05:45.859-06:00Getting a Symfony development enviroment running on windowsNothing is ever easy... Anyways, to get a computer ready to start developing with the Symfony PHP framework you have a few options. You can take the long, long route and install apache, php, and a database server. With that you have to do a good deal of configuration to get everything working together. You could also download WAMP or XAMPP, which are just prepackaged versions. I haven't used XAMPP, so I can't say how you would get that working.<br /><br />The best reason for using WAMP is that it is self contained in c:\wamp folder by default. You can also start and stop all of the server processes (Apache & MySQL) anytime by just closing the tray icon. It's great so you don't have unnecessary processes running all of the time.<br /><br />The main problem is that WAMP and Symfony don't work "out of the box." No surprise there.<br /><br /><br /><br />This is the process I used to get WAMP working with Symfony:<br />Download WAMP (1.6.6) and install:<br /><a href="http://www.wampserver.com/en/" target="_blank">http://www.wampserver.com/en/</a><br /><br /><br />Open a browser to http://localhost/<br />WAMP should display it's default webpage with links to phpmyadmin and etc.<br />If you are going to use MySQL it might be a good idea to change its root account to have a password. You can use phpmyadmin to do that, just click the link to it on the WAMP localhost page. <br /><br />There will be a problem once you change the password. Phpmyadmin won't be able to reconnect to MySQL until you edit this file:<br />C:\wamp\phpmyadmin\config.inc.php: <br />Search for this line below in the file and put your password between the '':<br />$cfg['Servers'][$i]['password'] = '';<br /><br /><br />Extract the Symfony Sandbox to c:\wamp\www for testing later:<br /><a href="http://www.symfony-project.com/get/sf_sandbox.tgz" target="_blank">http://www.symfony-project.com/get/sf_sandbox.tgz</a><br />If that link doesn't work, just go to http://www.symfony-project.com/ and checkout the download page.<br /><br />Read this tutorial for some needed info:<br /><a href="http://www.symfony-project.com/trac/wiki/SymfonyOnWAMP" target="_blank">http://www.symfony-project.com/trac/wiki/SymfonyOnWAMP</a><br /><br />It basically said to:<br />Open c:\wamp\Apache2\bin\php.ini<br />Search for and remove the comment symbol ';', change 'On' to 'Off', or just edit the lines to be the same as these below.<br />extension=php_xsl.dll<br />magic_quotes_gpc = Off<br />register_globals = Off<br />include_path = ".;c:\php\includes;c:\wamp\php\pear"<br /><br /><br />The magic_quotes_gpc and register_globals parts were not in the tutorial, but WERE NECESSARY for me to change. I was getting a 500 internal server error before I set those values to Off.<br /><br /><br />Install PEAR for PHP (taken from that Wiki article directly):<br />1. Start -> Run -> cmd<br />2. Cd into the PHP directory (e.g. C:\wamp\php)<br />3. Invoke go-pear.bat. Follow through the options (default should work fine).<br />If you have a problem when running the bat file like "Warning: Cannot use a scalar value as an array," in php 5.2.0 the file was broken for windows. You can check out this <a href="http://www.phpwomen.org/wordpress/2006/11/06/bundled-go-pearphar-broken-in-52-windows-releases/" target="_blank">website</a> for more info. You can just download the new version of the file from svn <a href="http://cvs.php.net/viewvc.cgi/pearweb/public_html/go-pear.phar?view=log" target="_blank">here</a>.<br /><br /><br />Open C:\wamp\Apache2\conf<br />Remove the comment character '#' from this line:<br />LoadModule rewrite_module modules/mod_rewrite.so<br /><br /><br />Point a browser to http://localhost/sf_sandbox/web/<br />You should get a page that says something like:<br />Congratulations!<br />If you see this page, it means that the creation of your symfony project on this system was successful....<br /><br /><br /><br />A few more notes to get the Symfony sandbox example working:<br /><a href="http://www.symfony-project.com/tutorial/my_first_project.html" target="_blank">http://www.symfony-project.com/tutorial/my_first_project.html</a><br />Edit symfony.bat in the sf_sandbox folder that you extracted to c:\wamp\www<br />Change the line:<br />set PHP_COMMAND=php.exe<br />to<br />set PHP_COMMAND=c:\wamp\php\php.exe<br /><br />I'm still having some problems with the example, but it is *kind of* working so far. I had to edit both php.ini files with all of the previous modifications.Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-90240405342194674442007-01-10T14:16:00.000-06:002007-01-10T14:46:11.565-06:00Looking for faster development methodsOver the past week or two I've been researching ways to develop server-side web based applications as fast as possible (time is money, haha). I am in the initial stages of starting a little side business with a friend and one of our possible clients is looking for a large system to handle online ordering of their products. If you know anything about developing and programming a complex system, it takes a lot of planning as well as a good deal of time to actually create it. My "developer ideals" won't allow my to create something of poor quality, so I've been reluctant to take on large things in the past. I've been pushing myself more lately to produce results the results I strive for with more speed. Well more like I've been trying to learn new methods and techniques where I can keep my quality level high, but just get things done faster.<br /><br />While I've programmed in PHP before, I know that I would need to create a large amount of generic functionality to handle an ordering system. This would include the front end where the customer places orders as well as the back end where the company processes the order, allows for product creation/update/deleting and whatever else. <br /><br />I'm not really going to do much with that order system right now, because it is only a possibility for us. What I need to do is find a tool that provides the best method of implementing server-side web based applications. My requirements at this time are free, reliable output, ease of use, and speed of implementation. <br /><br />I've looked at Visual Web Developer 2005 Express with MySQL. The problem as I mentioned in a previous post is that to use the .net 2.0 pre-made functionality I have to use an unproven user made library. Not something I want to do.<br /><br />Over the past two days I was researching Ruby On Rails. It looks interesting and should have a good deal of support in the future, but at least to me doesn't seem like it would be something I would want to use to code a client's application. At least not until I learn a lot more about it.<br /><br />A few minutes ago I found <a href="http://www.symfony-project.com/content/about.html" target="_blank">Symfony</a>. It's a framework based on PHP5 and is said to be of "clean design and code readability." So now I will be looking into that. If it's true this might be what I am looking for. If not I may just get started on designing/creating my own generic framework.Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-76769357847688999972007-01-08T22:03:00.000-06:002007-01-08T22:24:13.654-06:00A bit disappointed so far...I started playing around with Visual Web Developer Express 2005 (VWD). I had originally planned on using VWD with MySQL. The problem is that to use the new stuff in ASP.NET 2.0 like the pre-made authentication you have to use Microsoft's own SQL server, or try to get some convoluted method of making MySQL work as the provider. I'm sure that I could eventually get it working, but in the end it would not provide me the free easy to use fast development solution I was looking for in asp.net and MySQL. I had a plan to develop a dynamic small business website with user authentication, but I see now that it probably won't be with VWD Express and MySQL. If I have to reinvent the wheel for everything I'd rather just use PHP and MySQL.<br /><br />That being said, I still plan on messing around with VWD and Microsoft's SQL Express.<br /><br />I might be doing some research about Ruby On Rails to see if that would better meet my needs.<br /><br /><br /><a href="http://sprinj.com/ideas/view/5-a-mysql-membership-and-role-provider-for-aspnet-20" target="_blank">Using VWD and MySQL link</a>Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.comtag:blogger.com,1999:blog-4437963945985034017.post-27872776917857803962007-01-07T13:44:00.000-06:002007-01-07T13:51:52.999-06:00Learning asp.net visuallyMicrosoft has a great site with video tutorials <a href="http://www.asp.net/learn/videos/default.aspx?tabid=63" target="_blank">here</a>. They cover various aspects of visual web developer in VB and C#. They can't cover topics in too much detail, but more then enough to be worth while. Plus they are free....Scotthttp://www.blogger.com/profile/13027732573817084053noreply@blogger.com