<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Kristo Vaher</title>
	<atom:link href="http://waher.net/feed" rel="self" type="application/rss+xml" />
	<link>http://waher.net</link>
	<description>inventas vitam iuvat excoluisse per artes</description>
	<lastBuildDate>Sun, 20 Jun 2010 10:10:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>AJAX controller also released as a class</title>
		<link>http://waher.net/archives/331</link>
		<comments>http://waher.net/archives/331#comments</comments>
		<pubDate>Sun, 20 Jun 2010 09:54:57 +0000</pubDate>
		<dc:creator>Kristo Vaher</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://waher.net/?p=331</guid>
		<description><![CDATA[For phpclasses.org purposes I also converted the Smart AJAX Controller into a class, it is available here. While there aren&#8217;t big differences between the two, class structure makes the backend script more seamless and easy to use. Another improvement is the ability to return the result from the server compressed with GZip, thus making the [...]]]></description>
			<content:encoded><![CDATA[<p>For phpclasses.org purposes I also converted the Smart AJAX Controller into a class, it is available <a href="http://www.phpclasses.org/package/6276-PHP-Generate-AJAX-request-responses-in-JSON-format.html" target="_blank">here</a>. While there aren&#8217;t big differences between the two, class structure makes the backend script more seamless and easy to use. Another improvement is the ability to return the result from the server compressed with GZip, thus making the whole communication very lightweight.</p>
]]></content:encoded>
			<wfw:commentRss>http://waher.net/archives/331/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Smart AJAX/JSON/PHP solution with jQuery</title>
		<link>http://waher.net/archives/319</link>
		<comments>http://waher.net/archives/319#comments</comments>
		<pubDate>Tue, 01 Jun 2010 21:45:57 +0000</pubDate>
		<dc:creator>Kristo Vaher</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[user interface]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://waher.net/?p=319</guid>
		<description><![CDATA[I have seen a number of complicated solutions for front-end AJAX development and it has become quite clear such solutions are difficult thing to grasp for someone not that experienced with AJAX. Today I am offering a very simple and easy to extend solution that not only is less than two hundred lines of code [...]]]></description>
			<content:encoded><![CDATA[<p>I have seen a number of complicated solutions for front-end AJAX development and it has become quite clear such solutions are difficult thing to grasp for someone not that experienced with AJAX. Today I am offering a very simple and easy to extend solution that not only is less than two hundred lines of code in total &#8211; together with detailed comments &#8211; but also gives the ropes to jQuery AJAX development and using JSON as the preferred type of returned data from the server. Fear not, this is actually easier than it sounds.</p>
<p>For those of you looking for the files directly, they can grab them <a title="smart-json-ajax-solution.rar" href="http://waher.net/blog/smart-json-ajax-solution.rar">here</a>. Individual source code can be viewed here: <a href="http://waher.net/blog/smart-ajax/index.htm.txt">index.htm</a>, <a href="http://waher.net/blog/smart-ajax/javascript.js.txt">javascript.js</a>, <a href="http://waher.net/blog/smart-ajax/ajax.php.txt">ajax.php</a>. Note that jquery.js file is also required (1.4.2), should you copy-paste from the source code instead of downloading the archive.</p>
<p>The code is licensed under LGPL, so you can use it for personal as well as commercial purposes. All files are commented and a working example is provided within. You do not need a firm grasp of jQuery in order to understand this example and you do not need experience with JSON data format. PHP and jQuery handle the conversions for you. I will not explain everything step by step &#8211; for that refer to the files and the example provided &#8211; but I will give a general overview of what is happening here.</p>
<p>Front-end user-interface has the various actions built through a uiAction() javascript function. This is a general-use function that takes two variables, an &#8216;action&#8217; that acts as an action identifier, and &#8216;data&#8217; variable. Data variable can be whatever you want, it can be a string, integer, array or an object, depending on your needs. Since you will control how the &#8216;data&#8217; variable will be used, it is entirely up to you. In the example files I am calling the uiAction() on a &lt;button&gt; element like this:</p>
<p><em>uiAction(&#8216;alertLowercaseString&#8217;,$(&#8216;#example&#8217;).val());</em></p>
<p>For those of you who know jQuery, know that I am sending the value of an input field with an id of &#8216;example&#8217; to the function. Action&#8217;s name itself is &#8216;alertLowercaseString&#8217; in that case. Then, within uiAction() function in the &#8216;action&#8217;-switch I am executing the function that sends data to AJAX, like this:</p>
<p><em>input['string']=data;<br />
executeAjaxAction(action,input);</em></p>
<p>Action is, by default, the same as action identifier used to call uiAction(). executeAjaxAction() is a function that submits data to PHP backend (but you can customize it, such as have different uiAction() calls execute same function in back-end). &#8216;input&#8217; is an uiAction() specific javascript object. This is defined at the start of the uiAction() function and is used for convenience in order to send specific data to AJAX. &#8216;executeAjaxAction()&#8217; expects &#8216;input&#8217; to be an object or an array, since this is what will be sent to PHP backend. After submitting data to executeAjaxAction() the front-end will connect PHP back-end with AJAX. In this case I am sending an &#8216;action&#8217; of alertLowercaseString. PHP backend will solve the &#8216;input&#8217; into a variable named $inputVariables and again &#8211; as it was in front-end, within a switch you can define what you want to take place in the back-end and what will be returned. In this example it is:</p>
<p><em>$return['action']=&#8217;alert&#8217;;<br />
$return['message']=&#8217;Your string lowercased: &#8216;.strtolower($inputVariables['string']);</em></p>
<p>&#8216;$return&#8217; is an array that is used to create a JSON object from. &#8216;action&#8217; for &#8216;$return&#8217; needs to be always defined, but every other variable can be whatever you want, since &#8211; as before &#8211; you get to decide what data you need to use later on in front end. Basically everything you want to return to front-end should be placed in &#8216;$return&#8217; array. PHP then creates a JSON string of the &#8216;$return&#8217; array and returns it to the browser. executeAjaxAction() function will then call a javascript function parseAjaxReturn(), which will check what action PHP defined for callback (if any) and then &#8211; in this example of &#8216;alert&#8217; as the action &#8211; does the following:</p>
<p><em>alert(json['message']);</em></p>
<p>And this alerts to the user the lowercased string.</p>
<p>This quick explanation may be difficult to understand at first, but I strongly suggest that you take a look at the fully working examples provided within. Files are fully commented and examples provided within are minimal, so you can take this into production use right away should you want.</p>
<p><a title="smart-json-ajax-solution.rar" href="http://waher.net/blog/smart-json-ajax-solution.rar">Download fully working example files here</a></p>
<p>If you have any questions, go ahead and contact me directly or comment this article. I will get back to you as soon as possible.</p>
<p>All the best!</p>
]]></content:encoded>
			<wfw:commentRss>http://waher.net/archives/319/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A simple PHP pathfinder class &#8211; as promised</title>
		<link>http://waher.net/archives/313</link>
		<comments>http://waher.net/archives/313#comments</comments>
		<pubDate>Tue, 25 May 2010 20:55:58 +0000</pubDate>
		<dc:creator>Kristo Vaher</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[pbbg]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://waher.net/?p=313</guid>
		<description><![CDATA[I recently shared a simple PHP and jQuery animated pathfinding tech-demo through my Twitter account and promised to share the simple pathfinding class used for pathfinding calculations. The example shared in Twitter is still available here. This example has a few limits, that is you can easily confuse it by clicking on two tile locations [...]]]></description>
			<content:encoded><![CDATA[<p>I recently shared a simple PHP and jQuery animated pathfinding tech-demo through my Twitter account and promised to share the simple pathfinding class used for pathfinding calculations. The example shared in Twitter is still available <a href="http://waher.net/pathfinder/" target="_blank">here</a>.</p>
<p>This example has a few limits, that is you can easily confuse it by clicking on two tile locations in a row. But in general it works and what I will be using this for will be something a bit different, so this limitation was of no concern to me. However the entire pathfinding calculation takes place on PHP backend. Each map is essentially a square (currently a limitation of pathfinder, but can easily be tweaked) and stored as an associative array, every tile in that array like this:</p>
<p><strong>$map['1x1']['weight']=1.0;</strong></p>
<p>The first key is the coordinate of the single map tile and the weight key is used to store weight of this map tile for calculations. Nothing else is needed (and an example is provided in the files below). For actual game purposes or whatnot you can store additional information on that very map as long as the coordinate and weight are assigned as shown in the example. For example, in my own tech-demo I also store the graphic tile used in the map array.</p>
<p>Finding the actual path is just as simple:</p>
<p><strong>$map=getMap();<br />
require(&#8216;class.pathfinder.php&#8217;);<br />
$path=new PathFinder(); </strong><em>//Create new pathfinder object</em><strong><br />
$path-&gt;setOrigin(1,1); </strong><em>//Set the start location</em><strong><br />
$path-&gt;setDestination(20,20); </strong><em>//Set the destination</em><strong><br />
$path-&gt;setMap($map); </strong><em>//Assign the map to use for calculations</em><strong><br />
$result=$path-&gt;returnPath(); </strong><em>//Returns an array of all the walked steps</em></p>
<p>Working example, as well as commented pathfinder class is available below:<em><br />
</em></p>
<p><a href="http://www.waher.net/blog/pathfinder.rar">Download the class and example file here</a></p>
<p>Please note that this is not a definitive pathfinder. It only takes into account one square ahead and on very large maps I am sure there are more ideal solutions. But for your basic browser based game this is a good starting point and I learned a lot by creating it. This is also easy to expand based on your needs.</p>
<p>If you have any other questions, let me know.</p>
<p>The code is shared entirely free for personal or commercial use.</p>
<p>Cheers!</p>
]]></content:encoded>
			<wfw:commentRss>http://waher.net/archives/313/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Implementing tree traversal architecture for OriginNode</title>
		<link>http://waher.net/archives/309</link>
		<comments>http://waher.net/archives/309#comments</comments>
		<pubDate>Sun, 09 May 2010 11:35:10 +0000</pubDate>
		<dc:creator>Kristo Vaher</dc:creator>
				<category><![CDATA[OriginNode]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[concept]]></category>

		<guid isPermaLink="false">http://waher.net/?p=309</guid>
		<description><![CDATA[In my various old projects for one reason or another a very recursive algorithm was used to fetch data that was structured in a tree. In some cases multiple trees were stored within the same table, which caused problems when trying to implement faster and better algorithms when fetching data from the tree, adding new [...]]]></description>
			<content:encoded><![CDATA[<p>In my various old projects for one reason or another a very recursive algorithm was used to fetch data that was structured in a tree. In some cases multiple trees were stored within the same table, which caused problems when trying to implement faster and better algorithms when fetching data from the tree, adding new nodes to the tree or removing nodes from the tree in general.</p>
<p>In OridinNode the entire system assumes that every tree has a single parent node. But in OridinNode there are also situations where one tree can be a child of another trees node, which causes conflict for the traversal algorithms. To make traversal work every tree needs to have at least one element that is considered &#8216;parent&#8217;. But if a parent happens to be a node from another tree, then it became important to implement a &#8216;ghost node&#8217; to every module that has a parent in another tree. The user never sees such a ghost node, but that ghost node is used to traversing within the tree when fetching data to the actual parent element. To give an example, a website has a tree of pages. One of those pages however displays categories for products. There is no &#8216;main category&#8217; as all of the categories are children of the page node from pages tree, but the categories table does need a ghost parent for quick traversal purposes.</p>
<p>The tree structure model used in OriginNode is a <a href="http://dev.mysql.com/tech-resources/articles/hierarchical-data.html" target="_BLANK">Nested Set Model</a>. Basically every node within the tree is given two values, left and right, which carries their position information within the tree as well as basic information on their children and parents. This allows to completely throw out the recursive set of algorithms that are commonly used and makes it possible to build a whole array of the entire structure with just a few queries. For more detailed description please read through the link I posted above, I will be covering how this will be implemented within the structure of OriginNode below.</p>
<p>In OriginNode, the values often associated with recursive methods will still remain, this means that the nodes in OriginNode will also have information stored on direct ID values of their parents as well as their module identifiers. While those values will not be used to fetch trees, they are still used for other purposes, especially when connecting a number of nodes with one another. Instead of storing this information within the same tables, all this information is stored in a separate table for fetching data.</p>
<p>I have posted the basic table setup of OriginNode before, however the new and (yet again rewritten!) method has changed the structure quite a bit and it requires a revision here. This can be helpful for some of you readers out there who might face a similar challenge in setting up your infosystem architecture for your next project, so I will be giving a revised yet brief overview of the updated structure below.</p>
<p><strong>Node Table</strong><br />
<em>This table stores all nodes that share similar parameters. Every Node Table has a single parent node, but whether this parent is displayed for the user within the UI is up to the developer. This parent node within the table is automatically made invisible if the tree is assigned a parent from another tree. Fields within this node table are as follows:</em></p>
<ul>
<li> <strong>id </strong>= Primary key of the field.</li>
<li> <strong>identifier </strong>= URL friendly string that is optional for the tree. When traversing the OriginNode architecture then both id&#8217;s and identifiers can be used to solving the path. For example, when one fetches data by using a string of &#8216;products/cars/112&#8242;, then OriginNode can find identifiers for products and cars, but not one for 112, in which case it will look for id of 112 instead from among the children of &#8216;cars&#8217; node.</li>
<li> <strong>traversal_left</strong> = This is the left integer value for the tree traversal.</li>
<li> <strong>traversal_right</strong> = This is the right integer value for the tree traversal.</li>
<li> <strong>active </strong>= True or false flag whether the element is returned when data is being fetched from OriginNode.</li>
<li> <strong>period_start</strong> = Timestamp from what time the data is considered &#8216;active&#8217; and thus returned when data is being fetched. This can be used for various purposes, such as pages that are &#8216;released&#8217; at specific dates and periods. If this value is not set on the node, then the start time is ignored and data is always returned (unless restricted by the period_end field).</li>
<li> <strong>period_end</strong> = Timestamp until what time the data is considered &#8216;active&#8217; and thus returned when data is being fetched. This can be used for various purposes, such as pages that are &#8216;closed&#8217; after specific dates and periods. If this value is not set on the node, then the end time is ignored and data is always returned (unless restricted by the period_start field).</li>
<li> <strong>rights_read</strong> = This is a list of user group identifiers which have the right to see and read that node. Every group is a URL-friendly string and stored within square brackets, like [developer][admin], etc.</li>
<li> <strong>rights_edit</strong> = This is a list of user group identifiers which have the right to edit the data within that node. Every group is a URL-friendly string and stored within square brackets, like [developer][admin], etc.</li>
<li> <strong>rights_delete</strong> = This is a list of user group identifiers which have the right to remove that node. Every group is a URL-friendly string and stored within square brackets, like [developer][admin], etc.</li>
<li><strong>f_*</strong> = Every custom field from Node Parameters Table (below) has its value stored in <em><strong>f_</strong></em> prefix fields.</li>
</ul>
<p><strong>Node Parameters Table</strong><br />
<em>This table stores all the custom fields that are stored within the Node Table. Every custom field is stored in Node Table with an f_ index.</em></p>
<ul>
<li><strong>identifier </strong>= String identifier that is also the field name, with a <em><strong>f_</strong></em> prefix, stored in Node Table. This value is enforced to be unique.</li>
<li><strong>type </strong>= this is a type keyword that determines what type of custom field it is. This ranges from simple fields such as checkboxes, radio buttons and dropdowns to WYSIWYG editors, color pickers, and connections with other nodes.</li>
<li><strong>configuration </strong>= This is a serialized array, stored as a string. This carries whatever custom information the field type or its extension require, such as field length, allowed letters and other restrictions.</li>
<li><strong>tab_identifier</strong> = This is the identifier string of the tab this field is displayed under when viewing the node of the Node Table. Fields with same tab identifiers are stored under the same tab. This value is always required or it will never be shown to the user.</li>
<li><strong>fieldset_identifier</strong> = This is the identifier string of the fieldset this field is displayed under  when viewing the node and the tab of the Node Table. Fields with same fieldset identifiers are stored under the same fieldset. This value can be null, which means that the field is not displayed within a fieldset.</li>
<li><strong>weight </strong>= This is the weight of the field. Every node view will be built by taking into account the weights of the fields. First tab in node view will always be the one that has a field with the lowest weight. First fieldset under a tab will be the fieldset that has a field with the lowest weight. And fields with the same tab and fieldset identifiers will also be ordered based on the lowest weight first, and highest last. Basically the heavier a custom field is, the further back it is displayed.</li>
<li><strong>table_display</strong> = Whether this custom field is also displayed in the Module view, in a tree or a list.</li>
<li><strong>table_filter</strong> = Whether this custom field can be filtered in the Module view, in a tree or a list.</li>
<li><strong>table_sortable</strong> = Whether this custom field can be sorted in a Module view, in a tree or a list.</li>
<li><strong>rights_read</strong> = Whether these user groups have the rights to see and read the values of this field. Every group is a URL-friendly string and stored within square brackets,  like [developer][admin], etc.</li>
<li><strong>rights_edit</strong> = Whether these user groups have the rights to edit the values of this field. Every group is a URL-friendly string and stored within square brackets,  like [developer][admin], etc.</li>
<li><strong>value_required</strong> = Whether value within this field is required and cannot be null. This is not applicable to connections custom field types.</li>
<li><strong>value_unique</strong> = Whether value within this field is required to be unique. This is not applicable to connections custom field types.</li>
<li><strong>value_default</strong> = Default value stored within this field. This is not applicable to connections custom field types.</li>
<li><strong>languages_dependant</strong> = Whether this field is languages dependant and has a new field for each of the languages. This means that in the case of &#8211; for example a page title &#8211; there will be three fields instead of one when viewing the node, one for each language. If this is set and the custom field is connections, then the connections will be only made with objects that are not language dependant or are of only the same language as the custom field.</li>
</ul>
<p><strong>Node Connections Table</strong><br />
<em>This table has all the connections stored. In most cases this table is not used when fetching structure from the Node tables. All the connections however are still stored within this table and the traversal left and right values can be restored with the help of this table should something happen with the original tables. All subconnections (of the connections custom field type) are also stored in this table.</em></p>
<ul>
<li><strong>from_module</strong> = module identifier that the connection is from.</li>
<li><strong>from_id</strong> = id of the node from the from_module that the connection is from.</li>
<li><strong>to_module</strong> = module that this connection is created to.</li>
<li><strong>to_id</strong> = id of the node that this connection is created to.</li>
<li><strong>type </strong>= the type of this connection. This can be either [primary] (when the connection is part of the whole tree and deals with linked module nodes for traversal) or [secondary=<em>field_name</em>] (when the connection is not part of main structure and is only used to link another object, the field_name value identifies the custom field that this connection is used for).</li>
</ul>
<p>In general this whole system is a little bit more complicated than the earlier versions of OriginNode concept, but the speed benefits here are rather impressive. Cutting down recursive searches will mean that even larger structures can be built with OriginNode with less problems when fetching large amounts of data. When this is paired with MySQL caching &#8211; which will be supported by OriginNode in &#8216;demand&#8217; mode &#8211; then OriginNode architecture will be able to support even large scale infosystems of hundreds of thousands node objects.</p>
]]></content:encoded>
			<wfw:commentRss>http://waher.net/archives/309/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to use multiple domains within one environment</title>
		<link>http://waher.net/archives/290</link>
		<comments>http://waher.net/archives/290#comments</comments>
		<pubDate>Tue, 04 May 2010 09:17:52 +0000</pubDate>
		<dc:creator>Kristo Vaher</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://waher.net/?p=290</guid>
		<description><![CDATA[This is a quick and unrelated post to all readers out there who pay for hosting services in shared virtualhost environments. I have been asked this question a few times in the past, but I figured it is good to share the tips here. In Estonia there are a number of hosting services for relatively [...]]]></description>
			<content:encoded><![CDATA[<p>This is a quick and unrelated post to all readers out there who pay for hosting services in shared virtualhost environments. I have been asked this question a few times in the past, but I figured it is good to share the tips here. In Estonia there are a number of hosting services for relatively low price, but one of the complications comes when you happen to own numerous domain names and would like these domain names to be run within the same environment. You could essentially run a number of WordPress blogs with entirely different domain names under the same hosting service.</p>
<p>What this needs is that all but one of your domain names should be an alias domain name for your main domain name. Most hosting services allow this without additional cost and in fact allow you to set it up yourself <em>(should this be a problem, contact your hosting services customer support)</em>. You would then own a number of domain names for which you do still have to pay a fee <em>(usually yearly)</em>, but you would only need to pay for only one hosting environment. Drawback of this is that the space and resources used by that environment would then be shared, but as long as you run small scale websites there <em>(blogs and other sites for personal use)</em>, it will not become a problem.</p>
<p>To make this happen you need to set up a new index file on your web server which would be run first by PHP. In this index file you would detect the address that the user was trying to access and then direct them to the proper files or project. In case of wordpress you should rename its <em>index.php</em> to something like <em>wpindex.php</em> <em>(alternative is to direct Apache to use another file for index, however many hosting services disable use of .htaccess commands)</em>. If I wanted my blog <em>waher.net</em> to always show my blog, but would like my other domain <em>wearenixy.net</em> work as an alias domain name for the domain without having to pay extra for hosting services I would set up something like this:</p>
<pre>&lt;?php
    if($_SERVER['SERVER_NAME']=='waher.net' || $_SERVER['SERVER_NAME']=='www.waher.net'){
        include('wpindex.php');
    } else if($_SERVER['SERVER_NAME']=='wearenixy.net' || $_SERVER['SERVER_NAME']=='www.wearenixy.net'){
        include('wearenixy.php');
    }
?&gt;</pre>
<p>If the user types in<em> waher.net</em> they would be redirected to <em>wpindex.php</em> and if the user is redirected through my <em>waher.net</em> alias name <em>wearenixy.net</em>, another script would be executed for that purpose.</p>
<p>This is essentially setting up your hosting service to work as a mini &#8216;domain routing&#8217; service within your own virtualhost.</p>
<p>All the best!</p>
]]></content:encoded>
			<wfw:commentRss>http://waher.net/archives/290/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>About languages, types and other dynamic content filters</title>
		<link>http://waher.net/archives/284</link>
		<comments>http://waher.net/archives/284#comments</comments>
		<pubDate>Sun, 25 Apr 2010 15:35:40 +0000</pubDate>
		<dc:creator>Kristo Vaher</dc:creator>
				<category><![CDATA[OriginNode]]></category>
		<category><![CDATA[architecture]]></category>

		<guid isPermaLink="false">http://waher.net/?p=284</guid>
		<description><![CDATA[After much thought I have introduced another change into OriginNode architecture and how it is built from ground up. An average infosystem nowadays features specific requirements to filter content based on things like what language the user is browsing the website on or what product they are viewing. In order to deal with a potential [...]]]></description>
			<content:encoded><![CDATA[<p>After much thought I have introduced another change into OriginNode architecture and how it is built from ground up. An average infosystem nowadays features specific requirements to filter content based on things like what language the user is browsing the website on or what product they are viewing. In order to deal with a potential catastrophic problem of having to build an immense tree and then duplicate elements between branches of that tree (such as having two products instead of one product for an e-shop just because the website has two languages), another solution was needed to improve usability without cutting down the legs of your new and fancy website before it is even up and running.</p>
<p>Basing it on my own experience and the various infosystems that are out there, regardless of content total size, the objects are always &#8216;filtered&#8217; through two key values. One is a language and the other is a type, of sorts. Language plays a different role from a type (which you might use for a products categorization) because language can change values of a field based on what language is currently displayed. Example is to have a product with the exact same price and weight, but two different names because of language difference. This means that the node needs a field that has a different value for each language in the system, while many other fields remain the same. In OriginNode I am calling that behavior &#8216;language depencancy&#8217; and plan to build it so that you can assign every field to be language dependant, in which case OriginNode generates all the fields required to fulfil that need.</p>
<p>But types are an entirely different monster. Types can be various statuses that you need to assign to products for filtering purposes, for example to separate your products into &#8216;special offer&#8217;, &#8216;best-selling&#8217; and &#8216;regular&#8217; groups. Creating a new module for that purpose is unnecessary, because nodes share similar properties. OriginNode has a couple of hardcoded filters that are already used, such as active flag and period when the object is returned, but there is always a need for dynamic types that are also displayed within OriginNode itself. For a public site one could indeed create a new dropdown and deal with filtering simply by using that on public frontend, but for those dynamic types to be also displayed as tabs within OriginNode another solution was needed. So far the best option seems to be to treat those dynamic types as module-based language dependancy. While languages apply for the entire infosystem, types do not. Types are assigned to each module in the system and can be used to filter nodes within OriginNode itself by using tabs when viewing the module. To deal with conflict of interest tabs-wise with languages and types, then languages always take priority and would be shown as tabs. Types however would be displayed as a separate dropdown filtering option.</p>
<p><em>In unrelated news, one of my country&#8217;s more known content management systems has gone open-source after many years of development. The code itself is tired and old-school and looks like it requires a major rewrite, but for what its worth this only shows the value of open source technologies in todays market. While being open source never guarantees quality, it definitely helps.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://waher.net/archives/284/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Media vs. Michael Schumacher</title>
		<link>http://waher.net/archives/280</link>
		<comments>http://waher.net/archives/280#comments</comments>
		<pubDate>Wed, 21 Apr 2010 16:22:48 +0000</pubDate>
		<dc:creator>Kristo Vaher</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[F1]]></category>
		<category><![CDATA[media]]></category>

		<guid isPermaLink="false">http://waher.net/?p=280</guid>
		<description><![CDATA[Anyone who has paid attention to waves of media has noticed &#8211; especially when it comes to sports &#8211; that media loves seeing giants fall. This has been so throughout the years, but is especially evident with two sportsmen who can be considered the very example of legends in the sport they took part in. [...]]]></description>
			<content:encoded><![CDATA[<p>Anyone who has paid attention to waves of media has noticed &#8211; especially when it comes to sports &#8211; that media loves seeing giants fall. This has been so throughout the years, but is especially evident with two sportsmen who can be considered the very example of legends in the sport they took part in. Michael Jordan played two seasons for Washington Wizards and barely performed on B level. Media quickly jumped at the throat of who is arguably one of the greatest ever to play basketball simply because he seemingly never faltered during his career, even having ended his years with Chicago Bulls with three titles in a row. Michael Jordan is and was a controversial figure, a strong and often fearless (and fierce) challenger and competitor who was out there to win no matter what. His success overshadowed his shortcomings, you cannot argue with his numbers and what he did to the sport. But with his return to sports he was far from his &#8216;great days&#8217; and led a mediocre team in the middle of the pack, even falling out playoff run in the later season.</p>
<p>He was hit with sharp criticism and his decision to return was questioned, especially by every single one who always had something against Jordan and never had the chance to do so before. You cannot argue with a king who rules, but once they give up the throne and fall short of a great comeback years later they become mortal. An everyman, just another player among players, often surpassed by the modern greats with rare flashes of greatness from the old days.</p>
<p><img class="alignnone" title="Michael Schumacher" src="http://waher.net/media/schumi.jpg" alt="" width="465" height="349" /></p>
<p>If that scenario sounds similar, it is because the most successful Formula 1 race driver of all time walks the very same path. Michael Schumacher returned handful years after he retired from the sports when he finished a successful run with Ferrari, winning five titles for Ferrari in eleven years and finishing higher than third in all other cases except one. A champion with 91 wins. Few years later, now 41 years old, he returned to the sport with much fanfare. Similarly to Jordan, he joined a team he was not part of during his championship days and similarly to Jordan, the team is not a serious championship contender, at least not yet. But that aside, driving a silver Mercedes and paired with a young german Nico Rosberg seemed like the second best thing. Fans of Schumacher were excited and media pushed fanfares to the forefront with such an effort that one would think Schumacher would win the series with a golf cart.</p>
<p>Today, four races later, media has turned the tables they themselves set, right against Michael Schumacher. Despite many great figures in the sport supporting Schumacher, it has made a very little impact, because media &#8211; as it so often does &#8211; smells blood and acts on it. As some might know, Schumacher was never beloved by media, but similarly to Jordan you could not argue against a champion who does get the job done. Schumachers titles in 2001 and 2002, against David Coulthard and teammate Rubens Barrichello, had him score twice as many points as the driver finishing second. His work together with Ross Brawn (lead engineer) and Jean Todt (team manager) throughout the years built Ferrari into the most successful Formula 1 team in sports history.</p>
<p>But media is quick to change its mind, Ferrari days were forgotten almost the very first moment he drove out of pits with his silver Mercedes. It has not made much of a difference that Schumachers return has only lasted for four races, two of which were failures that no one could do anything about. In the second race of the season another driver collided with his car at the very beginning, which forced him to make a stop in pits for mechanical repairs. In the third race, despite a swift rise in positions at the start, he retired because of mechanical failure. The fourth race was full of chaotic rain and rear wing related problems which led to issues with traction. But once media smells blood, they care very little for the details, his great defensive work against fellow drivers to hold back faster teams was quickly forgotten.</p>
<p>Thus Schumacher is painted red by the media, to be hit by bulls of fellow media.</p>
<p>I cannot help but feel affected by all this, even though it should matter very little. Schumacher was an inspiration for me when he was struggling to get wins for Ferrari. He joined with them for 1996 season when I was in my early teens. It took five years for him to finally achieve a championship and I followed his career every step of the way. Seeing media attempt a payback in a situation, where no one could have realistically expected anything much better, leaves a sour taste in my mouth.</p>
<p>But I also know that Schumacher is not one of us. Media will not kill his spirits, even though it is quite clear that they won&#8217;t stop trying. I know he will not return to his old form at such an age, but I know he will prove media wrong. Just give him time, so far everyone who really matters in the sport has said as much for they know better. His return has already been half the victory, Formula 1 has not seen this much positive media attention since Schumachers dueling days with Mika Hakkinen and McLarens.</p>
<p>And that, in its own sense, is a championship for the sport of Formula 1.</p>
<p>-K</p>
]]></content:encoded>
			<wfw:commentRss>http://waher.net/archives/280/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Technical overview of the architecture</title>
		<link>http://waher.net/archives/268</link>
		<comments>http://waher.net/archives/268#comments</comments>
		<pubDate>Sun, 11 Apr 2010 21:17:01 +0000</pubDate>
		<dc:creator>Kristo Vaher</dc:creator>
				<category><![CDATA[OriginNode]]></category>
		<category><![CDATA[architecture]]></category>

		<guid isPermaLink="false">http://waher.net/?p=268</guid>
		<description><![CDATA[This post has been deprecated and information within about the tables does not reflect the updated structure of OriginNode. More accurate post is here. As I was developing the architecture for OriginNode I realized that for the entire system to work in ways I am hoping it would, the entire system itself should be built [...]]]></description>
			<content:encoded><![CDATA[<p><em>This post has been deprecated and information within about the tables does not reflect the updated structure of OriginNode. More accurate post is <a href="http://waher.net/archives/309">here</a>.</em></p>
<p>As I was developing the architecture for OriginNode I realized that for the entire system to work in ways I am hoping it would, the entire system itself should be built upon the very same architecture that OriginNode is used for building. As I had started with a custom user interface and MVC structure I realized that this would not only lead me to having to fix problems on two fronts at the same time, but also would lose out on the possibility to use the entire architecture and user interface itself as an example of what is possible with OriginNode.</p>
<p>As I have previously explained, OriginNode is essentially a tree based architecture building tool that consists of three &#8216;module&#8217; views (tree, branch and leaves) and &#8216;node&#8217; views with its custom values. But while it is a tree based architecture, it can work in areas that do not necessarily require a tree (in case public site of OriginNode is not required and the public API is used to pull information for other purposes).</p>
<p><a href="http://waher.net/originnode/logo.jpg"><img class="alignnone" title="Logo" src="http://waher.net/originnode/logo_thb.jpg" alt="" width="320" height="214" /></a></p>
<p>To achieve that goal I needed the system to have essentially two type of tables: module table and module fields table. Module table would include identifiers and hardcoded &#8211; system required &#8211; values for every node in the table as well as custom fields.</p>
<p>Every module is actually nothing more than a collection of nodes that share similar properties and their relations between one another. Modules are simply used to make it easier for the user to navigate the system, keeping things neatly organized.</p>
<p>A bare-bones module table consists currently of these fields:</p>
<ul>
<li>id (as a unique identifier of nodes stored)</li>
<li>identifier (a &#8216;keyword&#8217; that is used for translations of this object or as a URL node for public site)</li>
<li>active (system flag that is used, by default, whether the node is served to the public engine, -1 value turns off active flag and period_start and period_end)</li>
<li>period_start (timestamp, similar to active flag, to set a start period when the node is served to the public engine)</li>
<li>period_end (timestamp, similar to active flag, to set an end period when the node is served to the public engine)</li>
<li>language (OriginNode can function in single and multilanguage mode, this essentially acts as a language filter for all nodes stored in the table)</li>
<li>type (other than dynamically generated languages, a separate type can also be assigned for the object that is used when generating tabs)</li>
<li>parent_module (if this node has a parent in this same module or in another module, this is the identifier of that module)</li>
<li>parent_id (the id of the parent)</li>
<li>user_rights_read (groups of users in OriginNode system that can view and read the node)</li>
<li>user_rights_edit (groups of users that can edit the node)</li>
<li>user_rights_delete (groups of users that can delete the node)</li>
<li>CUSTOM FIELDS (other fields in this table come from another table)</li>
</ul>
<p>Every module can have custom fields for all the nodes stored within. These custom fields can be created by the developer before user starts adding data to the system. All of those fields are stored in a separate table, fields in that table are given below:</p>
<ul>
<li>id (id of the field, used only for reference)</li>
<li>identifier (unique MySQL compatible keyword, used as a field in the main module table with a custom prefix. This keyword is also used to translate the field based on the keyword)</li>
<li>type (field type, for example: checkbox, radio button, dropdown, multiple selection, text field, text area, password, WYSIWYG field (TinyMCE editor), object connection (to create reference &#8216;links&#8217; with other nodes), picture connection (to add media))</li>
<li>configuration (Additional data for the field that is stored as an array. This is specific information for the fields customization, used by the field extension. (and detailed for each field types documentation))</li>
<li>storage (The field type that is generated to the main module table for storage (integer, string etc). Data can also be stored in an external module in case of a data collection, such as group of pictures)</li>
<li>tab_identifier (every node is displayed in a completely dynamic interface, this field defines what tab this field is displayed under)</li>
<li>fieldset_identifier (custom fields can also be set into fieldsets under tabs, all fields with the same fieldset_identifier will appear in the same fieldset)</li>
<li>priority (general priority value, this only applies to fields that have the same tab and fieldset)</li>
<li>table_display (whether this field is displayed in main module list, where all nodes are shown)</li>
<li>table_filter (whether this field can be filtered, only applies to some types of fields)</li>
<li>table_sortable (whether nodes can be sorted based on this field)</li>
<li>user_rights_read (groups of users that can view this field)</li>
<li>user_rights_edit (groups of users that can edit this field)</li>
<li>value_required (whether this field requires a value or not, otherwise the node cannot be created or edited)</li>
<li>value_unique (whether this value has to be unique when compared to nodes with the same language (if defined))</li>
<li>languages_dependant (whether this field consists of actually more than one field. If a public site has two languages, say &#8216;english&#8217; and &#8216;german&#8217;, then a field that is languages dependant will actually show two fields instead of one, when editing the node. One would be for english language and another would be for german. This is used when you want the same products database, but perhaps want different descriptions based on languages)</li>
</ul>
<p>Now this description may seem a bit unclear and is quite a lot on the technical side, but it is good to keep in mind that OriginNode takes care of managing all that by itself. This flexibility of modules and nodes applies to every type of module user may come up with and the types of fields can be extended with plugins, allowing for endless opportunities. While there are a few restrictions with this type of system &#8211; and mind you much less than would be the case with most architecture frameworks of this type out there &#8211; it is important to keep in mind that any technicality of such restriction can be handled on the public side of the system. OriginNode will serve best information possible for the user of the API on public side and the developer of the public site can do with it as they wish, adding further options based on clients specific requirements.</p>
<p>Thus the end result can be extended both ways.</p>
<p>The above information is not yet final, however the basic architecture &#8211; the way it is right now &#8211; is not a concept anymore and the current build of OriginNode works based on the system described above.</p>
]]></content:encoded>
			<wfw:commentRss>http://waher.net/archives/268/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>As promised, screenshot of the tabs design for OriginNode</title>
		<link>http://waher.net/archives/260</link>
		<comments>http://waher.net/archives/260#comments</comments>
		<pubDate>Fri, 09 Apr 2010 23:06:36 +0000</pubDate>
		<dc:creator>Kristo Vaher</dc:creator>
				<category><![CDATA[OriginNode]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[user interface]]></category>

		<guid isPermaLink="false">http://waher.net/?p=260</guid>
		<description><![CDATA[This was a bit of a struggle, I went through a near-dozen different design ideas for the user interface tabs before settling on this simple tabs user interface shown below.]]></description>
			<content:encoded><![CDATA[<p>This was a bit of a struggle, I went through a near-dozen different design ideas for the user interface tabs before settling on this simple tabs user interface shown below.</p>
<p><img class="aligncenter" title="Tabs" src="http://waher.net/originnode/pic3.jpg" alt="" width="412" height="296" /></p>
]]></content:encoded>
			<wfw:commentRss>http://waher.net/archives/260/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Initial style and design of OriginNode</title>
		<link>http://waher.net/archives/248</link>
		<comments>http://waher.net/archives/248#comments</comments>
		<pubDate>Tue, 06 Apr 2010 16:18:17 +0000</pubDate>
		<dc:creator>Kristo Vaher</dc:creator>
				<category><![CDATA[OriginNode]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[user interface]]></category>

		<guid isPermaLink="false">http://waher.net/?p=248</guid>
		<description><![CDATA[First of all, apologies for not posting anything for a while. Work has held me busy and a lot of my free time is currently used to stay away from the computer. I am trying to stay away from burning out, a lot of my work these days tends to be routine and less of [...]]]></description>
			<content:encoded><![CDATA[<p><em>First of all, apologies for not posting anything for a while. Work has held me busy and a lot of my free time is currently used to stay away from the computer. I am trying to stay away from burning out, a lot of my work these days tends to be routine and less of a challenge and somewhat different from the fields I am interested in. Other than the design update in this blog, I have also removed a lot of non-essential posts from here and hope to focus exclusively on software development in the future.</em></p>
<p>The following pictures are a work in progress and everything is subject to change at a moments notice. I originally came up with the design when I was trying to come up with a sleek look for another application I was working on in the very little free time I have. It&#8217;s nothing innovative &#8211; I am not a designer &#8211; but the idea is for it to be simple, yet modern. I recently finished building the fluid HTML/CSS/JS architecture for this design and getting it working in all major browsers. Next step will be to work on getting the design and engine cooperate.</p>
<p><a href="http://waher.net/originnode/pic1.jpg"><img title="Log-in screen" src="http://waher.net/originnode/pic1thb.jpg" alt="" width="320" height="239" /></a></p>
<p><a href="http://waher.net/originnode/pic2.jpg"><img title="Basic User Interface" src="http://waher.net/originnode/pic2thb.jpg" alt="Basic User Interface" width="320" height="124" /></a></p>
<p>Some notes:</p>
<ul>
<li>The icons will be changed, I don&#8217;t own the rights for those icon pictures</li>
<li>Tabs for the open window are not yet visible. Tabs will be placed on a silver bar below the title field.</li>
<li>Basic content styles need tweaking and editing still.</li>
</ul>
<p>In other news, the basic architecture is well on its way. I am on vacation, but on a couple of evenings I&#8217;ve managed to set some time aside and work on OriginNode. Everything is going well, the base architecture of how everything will communicate and how the user interface updates will be handled is already set and written in code. Even tested somewhat. I will go into further detail in the future, but there is still a lot to be done before anything can be said in definite.</p>
<p>Comments and critique on the current design would also be welcome. I might be away for a few days, celebrating my birthday, but no feedback will be lost on me.</p>
<p>Cheers!</p>
]]></content:encoded>
			<wfw:commentRss>http://waher.net/archives/248/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
