<?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>mFabrik - mobile sites, apps, HTML5 and CMS software development &#187; javascript</title>
	<atom:link href="http://blog.mfabrik.com/tag/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.mfabrik.com</link>
	<description>Freedom delivered.</description>
	<lastBuildDate>Wed, 03 Aug 2011 09:47:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>AJAX proxy view with Python, urllib and Plone</title>
		<link>http://blog.mfabrik.com/2011/08/02/ajax-proxy-view-with-python-urllib-and-plone/</link>
		<comments>http://blog.mfabrik.com/2011/08/02/ajax-proxy-view-with-python-urllib-and-plone/#comments</comments>
		<pubDate>Tue, 02 Aug 2011 08:26:42 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[access control]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[allow-access-origin]]></category>
		<category><![CDATA[cors]]></category>
		<category><![CDATA[cross domain]]></category>
		<category><![CDATA[getjson]]></category>
		<category><![CDATA[grok]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[restful]]></category>

		<guid isPermaLink="false">http://blog.mfabrik.com/?p=1365</guid>
		<description><![CDATA[Old web browsers do not support Allow-acces-origin HTTP header needed to do cross-domain AJAX requests (IE6, IE7). Below is an example how to work around this for jQuery getJSON() calls by Detecting browsers which do not support this using jQuery.support API Doing an alternative code path through a local website proxy view which uses Python [...]]]></description>
			<content:encoded><![CDATA[<div class="body">
<p>Old web browsers do not support <a class="reference external" href="https://developer.mozilla.org/en/HTTP_access_control">Allow-acces-origin HTTP header</a> needed to do cross-domain AJAX requests (IE6, IE7).</p>
<p>Below is an example how to work around this for jQuery getJSON() calls by</p>
<ul class="simple">
<li>Detecting browsers which do not support this using jQuery.support API</li>
<li>Doing an alternative code path through a local website proxy view which uses Python <tt class="docutils literal">urllib</tt> to make server-to-server call and return it as it would be a local call, thus working around cross-domain restriction</li>
</ul>
<p>This example is for Plone/Grok, but the code is easily port to other Python web frameworks.</p>
<div class="note">
<p class="last"><em>Note: This is not a full example code. Basic Python and Javascript skills are needed to interpret and adapt the code for your use case.</em></p>
</div>
<p>Javascript example</p>
<pre class="literal-block">/**
 * Call a RESTful service vie AJAX
 *
 * The final URL is constructed by REST function name, based
 * on a base URL from the global settings.
 *
 * If the browser does not support cross domain AJAX calls
 * we'll use a proxy function on the local server. For
 * performance reasons we do this only when absolutely needed.
 *
 * @param {String} functionName REST function name to a call
 *
 * @param {Object} Arguments as a dictionary like object, passed to remote call
 */
function callRESTful(functionName, args, callback) {

    var src = myoptions.restService + "/" +functionName;

    // set to true to do proxied request on every browser
    // useful if you want to use Firebug to debug your server-side proxy view
    var debug = false;

        console.log("Doing remote call to:" + src)

        // We use jQuery API to detect whether a browser supports cross domain AJAX calls
        // http://api.jquery.com/jQuery.support/
        if(!jQuery.support.cors || debug) {
                // http://alexn.org/blog/2011/03/24/cross-domain-requests.html
                // Opera 10 doesn't have this feature, neither do IExplorer &lt; 8, Firefox &lt; 3.5

                console.log("Mangling getJSON to go through a local proxy")

                // Change getJSON to go to our proxy view on a local server
                // and pass the orignal URL as a parameter
                // The proxy view location is given as a global JS variable
                args.url = src;
                src = myoptions.portalUrl + "/@@proxy";
        }

        // Load data from the server
        $.getJSON(src, args, function(data) {
                // Parse incoming data and construct Table rows according to it
                console.log("Data succesfully loaded");
                callback(data, args);

     });

}</pre>
<p>The server-side view:</p>
<pre class="literal-block">import socket
import urllib
import urllib2
from urllib2 import HTTPError

from five import grok
from Products.CMFCore.interfaces import ISiteRoot
from mysite.app import options

class Proxy(grok.CodeView):
    """
    Pass a AJAX call to a remote server. This view is mainly indended to be used
    with jQuery.getJSON() requests.

    This will work around problems when a browser does not support Allow-Access-Origin HTTP header (IE).

    Asssuming only HTTP GET requests are made.s
    """

    # This view is available only at the root of Plone site
    grok.context(ISiteRoot)

    def isAllowed(self, url):
        """
        Check whether we are allowed to call the target URL.

        This prevents using your service as an malicious proxy
        (to call any internet service).
        """

        allowed_prefix = options.REST_SERVICE_URL

        if url.startswith(allowed_prefix):
            return True

        return False

    def render(self):
        """
        Use HTTP GET ``url`` query parameter for the target of the real request.
        """

        # Make sure any theming layer won't think this is HTML
        # http://stackoverflow.com/questions/477816/the-right-json-content-type
        self.request.response.setHeader("Content-type", "application/json")

        url = self.request.get("url", None)
        if not url:
            self.request.response.setStatus(500, "url parameter missing")

        if not self.isAllowed(url):
            # The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeate
            self.request.response.setStatus(403, "proxying to the target URL not allowed")
            return

        # Pass other HTTP GET query parameters direclty to the target server
        params = {}
        for key, value in self.request.form.items():
            if key != "url":
                params[key] = value

        # http://www.voidspace.org.uk/python/articles/urllib2.shtml
        data = urllib.urlencode(params)

        full_url = url + "?" + data
        req = urllib2.Request(full_url)

        try:

            # Important or if the remote server is slow
            # all our web server threads get stuck here
            # But this is UGLY as Python does not provide per-thread
            # or per-socket timeouts thru urllib
            orignal_timeout = socket.getdefaulttimeout()
            try:
                socket.setdefaulttimeout(10)

                response = urllib2.urlopen(req)
            finally:
                # restore orignal timeoout
                socket.setdefaulttimeout(orignal_timeout)

            # XXX: How to stream respone through Zope
            # AFAIK - we cannot do it currently

            return response.read()

        except HTTPError, e:
            # Have something more useful to log output as plain urllib exception
            # using Python logging interface
            # http://docs.python.org/library/logging.html
            logger.error("Server did not return HTTP 200 when calling remote proxy URL:" + url)
            for key, value in params.items():
                logger.error(key + ": "  + value)

            # Print the server-side stack trace / error page
            logger.error(e.read())

            raise e</pre>
</div>
<p class="signature">
<a href="http://mfabrik.com/@@zoho-contact-form"><img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/mfabrik-24.png"></a> <a href="http://mfabrik.com/@@zoho-contact-form">Get developers</a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="vertical-align:middle;border:0"/></a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml">Subscribe mFabrik blog in a reader</a> <a href="http://twitter.com/mfabrik"> <img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2011/08/02/ajax-proxy-view-with-python-urllib-and-plone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple image roll-over effect with jQuery</title>
		<link>http://blog.mfabrik.com/2011/05/26/simple-image-roll-over-effect-with-jquery/</link>
		<comments>http://blog.mfabrik.com/2011/05/26/simple-image-roll-over-effect-with-jquery/#comments</comments>
		<pubDate>Thu, 26 May 2011 09:18:00 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[jquery]]></category>
		<category><![CDATA[plone]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[button]]></category>
		<category><![CDATA[effect]]></category>
		<category><![CDATA[hover]]></category>
		<category><![CDATA[image]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[link]]></category>
		<category><![CDATA[mouseout]]></category>
		<category><![CDATA[mouseover]]></category>
		<category><![CDATA[roll over]]></category>
		<category><![CDATA[rollover]]></category>
		<category><![CDATA[tinymce]]></category>

		<guid isPermaLink="false">http://blog.mfabrik.com/?p=1268</guid>
		<description><![CDATA[Here is a simple jQuery method to enable image roll-over effects (hover). This method is suitable for content editors who can add images only through TinyMCE or normal upload -  naming image files specially is the only requirement. No CSS, Javascript or other knowledge needed by the person who needs to add the images with [...]]]></description>
			<content:encoded><![CDATA[<div class="body">
<p>Here is a simple jQuery method to enable image roll-over effects (hover). This method is suitable for content editors who can add images only through TinyMCE or normal upload -  naming image files specially is the only requirement. No CSS, Javascript or other knowledge needed by the person who needs to add the images with roll-overs.</p>
<p>Just include this script on your HTML page and it will automatically scan image filenames, detects image filenames with special roll-over marker strings and then applies the roll-over effect on them. Roll-over images are preloaded to avoid image blinking on slow connections.</p>
<p>The script:</p>
<pre class="literal-block">/**
 * Automatic image hover placement with jQuery
 *
 * If image has -normal tag in it's filename assume there exist corresponding
 * file with -hover in its name.
 *
 * E.g. http://host.com/test-normal.gif -&gt; http://host.com/test-hover.gif
 *
 * This image is preloaded and shown when mouse is placed on the image.
 *
 * Copyright Mikko Ohtamaa 2011
 *
 * http://twitter.com/moo9000
 */

(function (jQuery) {
        var $ = jQuery;

        // Look for available images which have hover option
        function scanImages() {
                $("img").each(function() {

                        $this = $(this);

                        var src = $this.attr("src");

                        // Images might not have src attribute, if they
                        if(src) {

                                // Detect if this image filename has hover marker bit
                                if(src.indexOf("-normal") &gt;= 0) {

                                        console.log("Found rollover:" + src);

                                        // Mangle new URL for over image based on orignal
                                        var hoverSrc = src.replace("-normal", "-hover");

                                        // Preload hover image
                                        var preload = new Image(hoverSrc);

                                        // Set event handlers

                                        $this.mouseover(function() {
                                                this.src = hoverSrc;
                                        });

                                        $this.mouseout(function() {
                                                this.src = src;
                                        });

                                }
                        }
                });
        }

        $(document).ready(scanImages);

})(jQuery);</pre>
</div>
<p class="signature">
<a href="http://mfabrik.com/@@zoho-contact-form"><img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/mfabrik-24.png"></a> <a href="http://mfabrik.com/@@zoho-contact-form">Get developers</a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="vertical-align:middle;border:0"/></a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml">Subscribe mFabrik blog in a reader</a> <a href="http://twitter.com/mfabrik"> <img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2011/05/26/simple-image-roll-over-effect-with-jquery/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Passing dynamic settings to Javascript in Plone</title>
		<link>http://blog.mfabrik.com/2011/04/19/passing-dynamic-settings-to-javascript-in-plone/</link>
		<comments>http://blog.mfabrik.com/2011/04/19/passing-dynamic-settings-to-javascript-in-plone/#comments</comments>
		<pubDate>Tue, 19 Apr 2011 12:37:58 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[grok]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[viewlet]]></category>

		<guid isPermaLink="false">http://blog.mfabrik.com/?p=1246</guid>
		<description><![CDATA[Here is described a way to pass data from site or context object to a Javascripts easily. For each page, we create a &#60;script&#62; section which will include all the options in a Javascript filled in by Python code. The object is automatically created from a Python dict using JSON library. We create the script [...]]]></description>
			<content:encoded><![CDATA[<div id="passing-dynamic-settings-to-javascripts">
<div>
<p>Here is described a way to pass data from site or context object to a Javascripts easily. For each page, we create a <tt>&lt;script&gt;</tt> section which will include all the options in a Javascript filled in by Python code. The object is automatically created from a Python dict using JSON library.</p>
<p>We create the script tag in &lt;head&gt; section using a Grok viewlet registered there.</p>
<p>viewlet.py:</p>
<pre># -*- coding: utf-8 -*-
"""

    Viewlets related to application logic.

"""

# Python imports
import json

# Zope imports
from Acquisition import aq_inner
from zope.interface import Interface
from five import grok
from zope.component import getMultiAdapter

# Plone imports
from plone.app.layout.viewlets.interfaces import IHtmlHead

# The viewlets in this file are rendered on every content item type
grok.context(Interface)

# Use templates directory to search for templates.
grok.templatedir('templates')

# The generated HTML snippet going to &lt;head&gt;
TEMPLATE = u"""
&lt;script type="text/javascript"&gt;
    var %(name)s = %(json)s;
&lt;/script&gt;
"""

class JavascriptSettingsSnippet(grok.Viewlet):
    """ Include dynamic Javascript code in &lt;head&gt;.

    Include some code in &lt;head&gt; section which initializes
    Javascript variables. Later this code can be used
    by various scripts.

    Useful for settings.
    """

    grok.viewletmanager(IHtmlHead)

    def getSettings(self):
        """
        @return: Python dictionary of settings
        """

        context = aq_inner(self.context)
        portal_state = getMultiAdapter((context, self.request), name=u'plone_portal_state')

        return {
            # Pass dynamically allocated site URL to the Javascripts (virtual host monster thing)
            "staticMediaURL" : portal_state.portal_url() + "/++resource++yourcompany.app",
            # Some other example parameters
            "schoolId" : 3,
            "restService" : "http://yourserver.com:8080/rest"
        }

    def render(self):
        """
        Render the settings as inline Javascript object in HTML &lt;head&gt;
        """
        settings = self.getSettings()
        json_snippet = json.dumps(settings)

        # Use Python string template facility to produce the code
        html = TEMPLATE % { "name" : "youroptions", "json" : json_snippet }

        return html</pre>
</div>
</div>
<p class="signature">
<a href="http://mfabrik.com/@@zoho-contact-form"><img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/mfabrik-24.png"></a> <a href="http://mfabrik.com/@@zoho-contact-form">Get developers</a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="vertical-align:middle;border:0"/></a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml">Subscribe mFabrik blog in a reader</a> <a href="http://twitter.com/mfabrik"> <img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2011/04/19/passing-dynamic-settings-to-javascript-in-plone/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Including widget specific Javascripts in Plone using Python conditions</title>
		<link>http://blog.mfabrik.com/2011/04/13/including-widget-specific-javascripts-in-plone-using-python-conditions/</link>
		<comments>http://blog.mfabrik.com/2011/04/13/including-widget-specific-javascripts-in-plone-using-python-conditions/#comments</comments>
		<pubDate>Wed, 13 Apr 2011 09:27:51 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[behavior]]></category>
		<category><![CDATA[compress]]></category>
		<category><![CDATA[content type]]></category>
		<category><![CDATA[dexterity]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[minimize]]></category>
		<category><![CDATA[static media]]></category>
		<category><![CDATA[widget]]></category>
		<category><![CDATA[zope]]></category>

		<guid isPermaLink="false">http://blog.mfabrik.com/?p=1215</guid>
		<description><![CDATA[Here is described a way to include Javascript for certain widgets or certain pages only in Plone CMS Javascripts are processed through portal_javascripts utility automatically, making them suitable for production deployment (minimized, cached). Plone does all this for you. Also the same rules apply for CSS and portal_css tool. A special condition is created in [...]]]></description>
			<content:encoded><![CDATA[<p>Here is described a way to include Javascript for certain widgets or certain pages only in <a href="http://plone.org">Plone</a> CMS</p>
<ul>
<li>Javascripts are processed through <em>portal_javascripts</em> utility automatically, making them suitable for production deployment (minimized, cached). Plone does all this for you. Also the same rules apply for CSS and <em>portal_css</em> tool.</li>
<li>A special condition is created in Python code to determine whether to include the script or not on a page: it checks whether we are on a page needing the script and then signals portal_javascript which in turn puts the script to HTML &lt;head&gt; section</li>
<li>Javascripts are served from a <em>static</em> media folder in a Plone add-on utilizing <a href="http://grok.zope.org">Grok</a> framework. Static media folder is mapped to unique <em>resource</em> names spaces (++resource++yourpythonmodule.name), so that there are no file conflicts between different add-ons.</li>
<li>These instructions mainly are designed for <a href="http://plone.org/products/dexterity">Dexterity content type subsystem</a>, but can be used with any content types by replacing the behavior check with a marker interface check</li>
</ul>
<p>Dexterity content types can use Dexterity <em>behaviors </em>control panel to add new behaviors on your content types. One such a behavior is to include certain Javascript files when these content types are viewed or edited.</p>
<p>The example here shows how to include a Javascript if the following conditions are met</p>
<ul>
<li>You are developing a Plone add-on as a Python package (as oppose, to say, edit files directly through-the-web)</li>
<li>Content type has a certain Dexterity behavior applied on it</li>
<li>Different files are served for view (visitors) and edit modes (content editing interface)</li>
</ul>
<div>
<p><em>Note: There is no easy way currently directly check whether a certain widget and widget mode is active on a particular view. Thus, we do some assumptions and checks manually if we are on &#8220;edit&#8221; view.</em></p>
<p>Plone <em>portal_javascripts </em>is a site specific registry. Available javascripts are kept in the site database, so that you can fine-tune their settings on-line, through-the-web through Zope application server management interface. When Plone add-on is installed, a subsystem called GenericSetup can import database setting changes on XML based profiles. There is a tool called portal_setup which allows you easily to export, import or put parts of this setting updates to your add-on installer.<em><br />
</em></p>
</div>
<p>We import Javascript files to portal_javascripts using GenericSetup file jsregistry.xml:</p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;object name="portal_javascripts"&gt;

        &lt;!-- View mode javascript --&gt;
        &lt;javascript
                id="++resource++yourcompany.app/integration.js"
                authenticated="False"
                cacheable="True" compression="safe" cookable="True"
                enabled="True" expression="context/@@integration_javascript"
                inline="False"
                /&gt;

        &lt;!-- Edit mode javascript --&gt;
        &lt;javascript
                id="++resource++yourcompany.app/integration.edit.js"
                authenticated="False"
                cacheable="True" compression="safe" cookable="True"
                enabled="True" expression="context/@@edit_integration_javascript"
                inline="False"
                /&gt;

&lt;/object&gt;</pre>
<p>Then we create the special conditions using Grok views and Python code. This code would go to <em>yourcompany/app/browser/views.py</em> Python module:</p>
<pre># Zope imports
from Acquisition import aq_inner
from zope.interface import Interface
from five import grok
from zope.component import getMultiAdapter

from yourcompany.app.behavior.lsmintegration import IYourWidgetIntegration

class IntegrationJavascriptHelper(grok.CodeView):
    """ Used by portal_javascripts to determine when to include our
        custom Javascript integration code.

    This view is referred from the expression in jsregistry.xml.
    """

    # The view is available on every content item type
    grok.context(Interface)
    grok.name("integration_javascript")

    def render(self):
        """ Check if we are in a specific content type.

        Check that the Dexerity content type has a certain
        behavior set on it through Dexterity settings panel.

        Alternative, just check for a marker interface here.
        """

        # render() methot is a the only traversable
        # Grok CodeView method. It can be used for rendering
        # HTML code, but also for utility views
        # to return raw Python data

        try:
            # Check if a Dexterity behavior is available on the current context object
            # - if it is not, behavior adapter will raise TypeError
            avail = IYourWidgetIntegration(self.context)
        except TypeError:
            return False

        # If called directly from the browser like
        # http://localhost:8080/Plone/integration_javascript
        # will return HTTP 204 No Content

        return True

class EditModeIntegrationJavascriptHelper(IntegrationJavascriptHelper):
    """ Used by portal_javascripts to determine when to include our custom Javascript
        integration code *on edit pages* only.

    Subclass the existing checked and add more limiting conditions.
    """
    grok.name("edit_integration_javascript")

    def render(self):
        """
        @return True: If this template is rendered "Edit view" of the item
        """

        if not IntegrationJavascriptHelper.render(self):
            # We are not even on the correct content type
            return False

        # This is a hacked together as Plone does not provide a real
        # mechanism to separate edit views to other views.
        # We simply check if the current view URI ends with "edit"

        path = self.request.get("PATH_INFO", "")

        if path.endswith("/edit") or path.endswith("/@@edit"):
            return True

        return False</pre>
<p>Question: how much Grok is included with Plone 4.1: at least parts of its are, but would this example work with vanilla Plone 4.01 without including five.grok manually as a dependency?
<p class="signature">
<a href="http://mfabrik.com/@@zoho-contact-form"><img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/mfabrik-24.png"></a> <a href="http://mfabrik.com/@@zoho-contact-form">Get developers</a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="vertical-align:middle;border:0"/></a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml">Subscribe mFabrik blog in a reader</a> <a href="http://twitter.com/mfabrik"> <img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2011/04/13/including-widget-specific-javascripts-in-plone-using-python-conditions/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Everyone loves and hates console.log()</title>
		<link>http://blog.mfabrik.com/2011/03/15/everyone-loves-and-hates-console-log/</link>
		<comments>http://blog.mfabrik.com/2011/03/15/everyone-loves-and-hates-console-log/#comments</comments>
		<pubDate>Tue, 15 Mar 2011 13:35:40 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[commit hook]]></category>
		<category><![CDATA[compress]]></category>
		<category><![CDATA[console]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[ie]]></category>
		<category><![CDATA[internet explorer]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[plone]]></category>
		<category><![CDATA[preprocessor]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[safari]]></category>
		<category><![CDATA[webkit]]></category>

		<guid isPermaLink="false">http://blog.mfabrik.com/?p=1119</guid>
		<description><![CDATA[console.log()  is the best friend of every Javascript junkie. However, the lack of it isn&#8217;t. console.log() function is only available in Webkit based browsers and with Firebug in Firefox. It&#8217;s the infamous situation that someone leaves console.log() to Javascript code, doesn&#8217;t notice its presence, commits the file and suddenly all Javascript on the production server [...]]]></description>
			<content:encoded><![CDATA[<p>console.log()  is the best friend of every Javascript junkie. However, the lack of it isn&#8217;t. console.log() function is only available in Webkit based browsers and with Firebug in Firefox. It&#8217;s the infamous situation that someone leaves console.log() to Javascript code, doesn&#8217;t notice its presence, commits the file and suddenly all Javascript on the production server stops working for Internet Explorer users&#8230;.</p>
<p>To tackle the lack of console.log() problem there are several approaches.</p>
<h2>Use dummy placeholder if console is missing</h2>
<p>This snippet wraps console.log (need to repeat for console.error etc.):</p>
<pre>// Ignore console on platforms where it is not available
if (typeof(window["console"]) == "undefined") { console = {}; console.log = function(a) {}; }</pre>
<p>Pros</p>
<ul>
<li>Easy</li>
</ul>
<p>Cons</p>
<ul>
<li>Need to add to every Javascript file</li>
<li>Messes with global namespace</li>
</ul>
<h2>Use module specific log function</h2>
<p>This makes your code little bit ugly, more Java like. Each Javascript module declares their own log() function which checks the existence of console.log() and outputs there if it&#8217;s present.</p>
<pre>mfabrik.log =function(x) {
 if(console.log) {
 console.log(x);
 }
}

mfabrik.log("My log messages")</pre>
<p>Pros</p>
<ul>
<li>Easy to hook other logg</li>
<li>You can disable all logging output with one if</li>
</ul>
<p>Cons</p>
<ul>
<li>Not as natural to write as console.log()</li>
<li>Need to add to every Javascript module</li>
</ul>
<h2>Preprocess Javascript files</h2>
<p>Plone (Kukit / KSS) uses this approach. All debug Javascript is  hidden behind conditional comments and it is filtered out when JS files  are bundled for the production deployment. (<a href="http://codespeak.net/svn/kukit/kss.core/trunk/kss/core/pluginregistry/_concatresource/compression/javascript.py">The preprocessing code is here in Python for those who are interested in it</a>).</p>
<pre>if (_USE_BASE2) {
 // Base2 legacy version: matchAll has to be used
 // Base2 recent version: querySelectorAll has to be used
 var _USE_BASE2_LEGACY = (typeof(base2.DOM.Document.querySelectorAll) == 'undefined');
 if (! _USE_BASE2_LEGACY) {
 ;;;     kukit.log('Using cssQuery from base2.');</pre>
<p>Pros</p>
<ul>
<li>Makes production Javascript files lighter</li>
<li>Make production Javascript files more professional &#8211; you do not deliver logging statements indented for internal purposes for your site visitors</li>
</ul>
<p>Cons</p>
<ul>
<li>Complex &#8211; preprocessing is required</li>
</ul>
<h2>Commit hooks</h2>
<p>You can use Subversion and Git commit hooks to check that committed JS files do not contain console.log. For example, Plone repositories do this for the Python statement  import pdb ; pdb.set_trace() (enforce pdb breakpoint).</p>
<p>Pros</p>
<ul>
<li>Very robust approach &#8211; you cannot create code with console.log()</li>
</ul>
<p>Cons</p>
<ul>
<li>Prevents also legitimate use of console.log()</li>
<li>Github, for example, lacks possibility to push client-side commit hooks to the repository cloners. This means that every developer must manually install commit hooks themselves. Everything manual you need to do makes the process error prone.</li>
</ul>
<h2>Other approaches?</h2>
<p>Please tell us!
<p class="signature">
<a href="http://mfabrik.com/@@zoho-contact-form"><img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/mfabrik-24.png"></a> <a href="http://mfabrik.com/@@zoho-contact-form">Get developers</a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="vertical-align:middle;border:0"/></a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml">Subscribe mFabrik blog in a reader</a> <a href="http://twitter.com/mfabrik"> <img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2011/03/15/everyone-loves-and-hates-console-log/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Lazily load elements becoming visible using jQuery</title>
		<link>http://blog.mfabrik.com/2011/03/09/lazily-load-elements-becoming-visible-using-jquery/</link>
		<comments>http://blog.mfabrik.com/2011/03/09/lazily-load-elements-becoming-visible-using-jquery/#comments</comments>
		<pubDate>Wed, 09 Mar 2011 09:57:52 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[comments]]></category>
		<category><![CDATA[discussion]]></category>
		<category><![CDATA[disqus]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[lazy load]]></category>
		<category><![CDATA[static]]></category>
		<category><![CDATA[varnish]]></category>

		<guid isPermaLink="false">http://blog.mfabrik.com/?p=1078</guid>
		<description><![CDATA[It is a useful trick to lazily load comments or such elements at the bottom of page. Some elements may be loaded only when they are scrolled visible. All users are not interested in the information and do not necessary read the article long enough to see it By lazily loading such elements one can [...]]]></description>
			<content:encoded><![CDATA[<p>It is a useful trick to lazily load comments or such elements at the bottom of page. Some elements may be loaded only when they are scrolled visible.</p>
<ul>
<li>All users are not interested in the information and do not necessary read the article long enough to see it</li>
<li>By lazily loading such elements one can speed up the initial page load time</li>
<li>You save bandwidth</li>
<li>If you use AJAX for the dynamic elements of the page you can more easily cache your pages in static page cache (Varnish) even if the pages contain personalized bits</li>
</ul>
<p>For example, Disqus is doing this (see <a href="http://api.jquery.com/jQuery.ajax/">comments in jQuery API documentation</a>).</p>
<p>You can achieve this with <a href="http://remysharp.com/2009/01/26/element-in-view-event-plugin/">in-view plug-in for jQuery</a>.</p>
<p>Below is an example for Plone triggering <span style="text-decoration: underline;"><em>productappreciation_view</em></span> loading when our placeholder <em>div</em> tag becomes visible.</p>
<pre>...
&lt;head&gt;
  &lt;script type="text/javascript" tal:attributes="src string:${portal_url}/++resource++your.app/in-view.js"&gt;&lt;/script&gt;
&lt;/head&gt;
...
&lt;div id="comment-placefolder"&gt;

 &lt;!-- Display spinning AJAX indicator gif until our AJAX call completes --&gt;

 &lt;p&gt;
 &lt;!-- Image is in Products.CMFPlone/skins/plone_images --&gt;
 &lt;img tal:attributes="src string:${context/@@plone_portal_state/portal_url}/spinner.gif" /&gt; Loading comments
 &lt;/p&gt;

 &lt;!-- Hidden link to a view URL which will render the view containing the snippet for comments --&gt;                       
 &lt;a rel="nofollow" style="display:none" tal:attributes="href string:${context/absolute_url}/productappreciation_view" /&gt;

 &lt;script&gt;

 jq(document).ready(function() {

   // http://remysharp.com/2009/01/26/element-in-view-event-plugin/                                        
   jq("#comment-placeholder").bind("inview", function() {

     // This function is executed when the placeholder becomes visible

     // Extract URL from HTML page
     var commentURL = jq("#comment-placeholder a").attr("href");

     if (commentURL) {
     // Trigger AJAX call
       jq("#comment-placeholder").load(commentURL);
     }

   });                                     

 });     
 &lt;/script&gt;
&lt;/div&gt;</pre>
<p class="signature">
<a href="http://mfabrik.com/@@zoho-contact-form"><img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/mfabrik-24.png"></a> <a href="http://mfabrik.com/@@zoho-contact-form">Get developers</a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="vertical-align:middle;border:0"/></a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml">Subscribe mFabrik blog in a reader</a> <a href="http://twitter.com/mfabrik"> <img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2011/03/09/lazily-load-elements-becoming-visible-using-jquery/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Integrating jQuery UI 1.8 with Plone 4</title>
		<link>http://blog.mfabrik.com/2011/02/23/integrating-jquery-ui-1-8-with-plone-4/</link>
		<comments>http://blog.mfabrik.com/2011/02/23/integrating-jquery-ui-1-8-with-plone-4/#comments</comments>
		<pubDate>Wed, 23 Feb 2011 13:15:22 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[jquery ui]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[tabs]]></category>
		<category><![CDATA[tal]]></category>

		<guid isPermaLink="false">http://blog.mfabrik.com/?p=1003</guid>
		<description><![CDATA[We had some problems integrating jQuery UI to Plone 4. Looks like jQuery UI wants to define jQuery.tabs() and Plone 4 wants to do this also (form_tabbing.js).  After loading jQuery UI, Edit page tabs stopped working. The solution is to build a custom jQuery UI download bundle without Tabs feature includes. Then you should be [...]]]></description>
			<content:encoded><![CDATA[<p>We had some problems integrating jQuery UI to Plone 4.</p>
<p>Looks like jQuery UI wants to define jQuery.tabs() and Plone 4 wants to do this also (form_tabbing.js).  After loading jQuery UI, Edit page tabs stopped working.</p>
<p>The solution is to build a custom <a href="http://jqueryui.com/download">jQuery UI download bundle</a> without <em>Tabs</em> feature includes. Then you should be able to simple drop jQuery UI to any page:</p>
<pre> &lt;metal:head define-macro="javascript_head"&gt;    
 &lt;link rel="stylesheet" tal:attributes="href string:${context/portal_url}/jquery-ui-1.8.9.custom/css/ui-lightness/jquery-ui-1.8.9.custom.css" type="text/css" /&gt;
 &lt;script type="text/javascript" tal:attributes="src string:${context/portal_url}/jquery-ui-1.8.9.custom/js/jquery-ui-1.8.9.custom.min.js"&gt;&lt;/script&gt;
 &lt;script type="text/javascript" src="yourjqueryuiscript.js"&gt;&lt;/script&gt;
 &lt;/metal:head&gt;</pre>
<p>Maybe jQuery object is the next battlefield of namespace conflicts&#8230;
<p class="signature">
<a href="http://mfabrik.com/@@zoho-contact-form"><img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/mfabrik-24.png"></a> <a href="http://mfabrik.com/@@zoho-contact-form">Get developers</a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="vertical-align:middle;border:0"/></a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml">Subscribe mFabrik blog in a reader</a> <a href="http://twitter.com/mfabrik"> <img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2011/02/23/integrating-jquery-ui-1-8-with-plone-4/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Cross-platform mobile application development and payments</title>
		<link>http://blog.mfabrik.com/2009/09/30/cross-platform-mobile-application-development-and-payment/</link>
		<comments>http://blog.mfabrik.com/2009/09/30/cross-platform-mobile-application-development-and-payment/#comments</comments>
		<pubDate>Wed, 30 Sep 2009 09:55:30 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[android]]></category>
		<category><![CDATA[blackberry]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[locationing]]></category>
		<category><![CDATA[payment]]></category>
		<category><![CDATA[series 60]]></category>
		<category><![CDATA[symbian]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[appaccelerator]]></category>
		<category><![CDATA[appstore]]></category>
		<category><![CDATA[bango]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[deviceatlas]]></category>
		<category><![CDATA[fennec]]></category>
		<category><![CDATA[gallery]]></category>
		<category><![CDATA[mozilla]]></category>
		<category><![CDATA[nokia]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[phonegap]]></category>
		<category><![CDATA[pre]]></category>
		<category><![CDATA[rhomobile]]></category>
		<category><![CDATA[sms]]></category>
		<category><![CDATA[titanium]]></category>
		<category><![CDATA[upload]]></category>
		<category><![CDATA[web run-time]]></category>
		<category><![CDATA[webkit]]></category>

		<guid isPermaLink="false">http://blog.twinapex.fi/?p=277</guid>
		<description><![CDATA[We have been piloting multi-platform mobile application development and payments in few client projects. Target platforms usually include iPhone, Android, Blackberry and Nokia Series 60. Also there are two notable usual cases which need to be specially handled Image uploads Payments for subscribed content Sounds easy, right? Well it isn&#8217;t&#8230; Below are some notes for [...]]]></description>
			<content:encoded><![CDATA[<p>We have been piloting multi-platform mobile application development and payments in few client projects. Target platforms usually include iPhone, Android, Blackberry and Nokia Series 60. Also there are two notable usual cases which need to be specially handled</p>
<ul>
<li>Image uploads</li>
<li>Payments for subscribed content</li>
</ul>
<p>Sounds easy, right? Well it isn&#8217;t&#8230; Below are some notes for our due diligence work which you fellow developers might find interesting.</p>
<h2>SDKs</h2>
<p>Mobile phone vendors are jealously and don&#8217;t want to co-operate with each other. Building application which works in all handsets is major headache.</p>
<p>We found some reasonable candidates for cross-platform mobile development doing HTML and Javascript. HTML and Javascript pages are converted to native application using a wrapper technology (a.k.a. appaccelerator). Doing Flash Lite or Java ME can be pretty much forgotten nowadays as they won&#8217;t run on the most hyped platform, iPhone. Flash Lite has poor support for anything except content authoring due to primitive and limited APIs. Java ME provides horrible user experience.</p>
<p>(X)HTML is the only common language spoken by mobile phones. Thus, there has been a rise of &#8220;appaccelerators&#8221;, technologies which allow to create mobile applications with HTML(5) and Javascript.</p>
<ul>
<li><a href="http://www.phonegap.com/">Phonegap:</a> iPhone, Android, Blackberry and possibly S60 in the future. <strong>Pluses:</strong> BSD license, very active community. <strong>Minuses:</strong> <a href="http://groups.google.com/group/phonegap/browse_thread/thread/5760d86c91970441/f0305e400b362933#f0305e400b362933">bad documentation, difficult deployment process</a>.</li>
<li><a href="http://www.appcelerator.com/">Titanium</a>: iPhone, Android.<strong> Pluses: </strong>Professional, Apache license. <strong>Minuses:</strong> Too tightly coupled with Appacclerator Inc. company.</li>
<li><a href="http://www.rhomobile.com/">Rhomobile</a>: iPhone, Android, Blackberry, S60, Windows Mobile. <strong>Pluses:</strong> Professional, tries to build open source community, the widest platform support. <strong>Minuses:</strong> Dual licensing and tightly coupled with Rhomobile Inc.</li>
<li><a href="http://www.forum.nokia.com/Technology_Topics/Web_Technologies/Web_Runtime/">Nokia Web-runtime</a>: Nokia S60 and some other Symbian based phones. <strong>Pluses: </strong>Professional, good documentation. <strong>Minuses: </strong>Not open source, impossible to extend, Nokia has little interest to make this cross-platform, Nokia doesn&#8217;t like updating old models and web-runtime is useable only in the latest S60 5th edition models.</li>
<li>Palm Pre supports web applications natively. However Palm Pre application business is still taking a shape.</li>
</ul>
<p>All these wrap the browser component (WebKit) and provide some extra Javascript APIs when your web pages as executed under the application mode.</p>
<ul>
<li>Locationing</li>
<li>Contacts</li>
<li>SMS</li>
<li>Client-side database</li>
<li>and so on&#8230;</li>
</ul>
<p>Rhomobile has little different use cases  from the rest of the bunch as it provides client-side programming using Ruby and less focuses on Javascript/web applications.</p>
<h2>Payments and in-application purchases</h2>
<p>There are four major way to do mobile payments &#8220;inside&#8221; the application for bought content and subscriptions. The price tag on the application itself is left out on this discussion as the application stores themselves take care of it.</p>
<ul>
<li>Credit card</li>
<li>SMS</li>
<li>App Store payment (thus far Apple only)</li>
<li>Direct operator payments &#8211; you have a service provider (Bango) which can directly charge items to the operator phone bill based on handset identification.</li>
</ul>
<p>App Store payment is the most attractive as it provides the best end user experience.  It allows you to use App Store payment mechanism inside the application. It is safe and no need to hassle with external payment providers. However, App Store payment can be used only for content consumed directly inside the application. You cannot use it e.g. for ordering a pizza. I think this might be related to recent EU legislation forbidding SMS payments for services not consumed in the phone itself.</p>
<p>SMS payment is ok for little payments. Operators take big cut of the revenue, generally 30% &#8211; 70% depending on the country. Short code fees usually start from 500€ set-up fee + 500€ / month. SMS cannot be often send as a background, but the user is presented the normal SMS editor which reduces the user experience somehow.</p>
<p>For credit card payments there exists several providers. Credit card has the cheapest entry fees, but the downside is that the user needs to have the credit card. This excludes teenager audience.</p>
<p>Direct operator payments are not very well supported yet globally. Most western operators support them. The operator also takes a big share and the fixed fee is pretty high.</p>
<p>My favorite payment provider thus far is<a href="http://www.bango.com"> Bango</a> which provides credit card payment starting 9€ / mo. and scales up to worldwide SMS payments which cost few grannies per month.</p>
<p>In most cases, the payment experience will not be smooth. You need to open the phone main browser on the payment provider page to do the payment. This usually will close your own application. Rarely you can do the payment inside the application <em>and</em> support multiple platforms. After doing the payment most platforms allow you to close the browse and reopen your application using a special URL handler.</p>
<p><a href="http://en.wikipedia.org/wiki/Mobile_payment">Wikipedia mobile payments</a> page is also useful.</p>
<h2>Image upload</h2>
<p>&lt;input type=&#8221;file&#8221;&gt; won&#8217;t work on iPhone and some other platforms  as those don&#8217;t have user browsable file system. Also the file dialog usually doens&#8217;t have image preview making it useless.</p>
<p>Phonegap has a branch which supports images picking using iPhone&#8217;s own gallery browser.</p>
<p>In any case, there is not yet cross-platform solution for this.</p>
<h2>Future prospects</h2>
<p>In some time-frame we will get rid of the need to wrap HTML applications natively as the web browser applications will support all HTML5 features without extensions and probably have some proprietary extensions for mobile specific features like SMS. We already have had some taste for this:</p>
<ul>
<li>The first taste of this is <a href="http://hacks.mozilla.org/2009/06/geolocation/">Mozilla&#8217;s Fennec mobile browser which has locationing support</a>.</li>
<li>iPhone&#8217;s Safari already supports <a href="http://developer.apple.com/safari/library/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/Introduction/Introduction.html">client-side storage</a> and <a href="http://girliemac.com/blog/2009/01/23/webkit-comparison-on-css3/">CSS3</a>.</li>
<li>All phones have support for dial-in links. The format of the link may vary. <a href="http://deviceatlas.com/">DeviceAtlas</a> is good place to hunt for this information.</li>
<li>Nokia browser supports send SMS links</li>
<li>Nokia browser supports downloadable map markers (to the map application of the phone itself)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2009/09/30/cross-platform-mobile-application-development-and-payment/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Scripting Google analytics for multidomain site</title>
		<link>http://blog.mfabrik.com/2009/07/15/scripting-google-analytics-for-multidomain-site/</link>
		<comments>http://blog.mfabrik.com/2009/07/15/scripting-google-analytics-for-multidomain-site/#comments</comments>
		<pubDate>Wed, 15 Jul 2009 10:41:00 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[google analytics]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[language]]></category>
		<category><![CDATA[multilingual]]></category>
		<category><![CDATA[seo]]></category>
		<category><![CDATA[tld]]></category>
		<category><![CDATA[top level domain]]></category>

		<guid isPermaLink="false">http://blog.twinapex.fi/?p=206</guid>
		<description><![CDATA[We are running few Plone sites which use top level domain (TLD) to identify the site language. Like many other CMSs out there,  Plone has only one box to enter Google Analytics script snippet.  It is often desirable to use different tracker for different domain and different language combinations, but Google itself doesn&#8217;t provide any [...]]]></description>
			<content:encoded><![CDATA[<p>We are running few Plone sites which use top level domain (TLD) to identify the site language.</p>
<p>Like many other CMSs out there,  Plone has only one box to enter Google Analytics script snippet.  It is often desirable to use different tracker for different domain and different language combinations, but Google itself doesn&#8217;t provide any fancy generator to create complex page tracking code.</p>
<p>Page tracker code, though looks little difficult when spit out by Google Analytics, is just normal Javascript.  You can make the condition to choose the appropriate page tracker id in Javascript itself using document.location property and this way you don&#8217;t need to mess with your page templates to create separate tracking Javascript snippet slots.</p>
<p>Here is an example what you can toss in to Plone <em>site setup</em> -&gt; <em>site</em> -&gt; <em>JavaScript for web statistics support</em>:</p>
<pre>&lt;script type="text/javascript"&gt;
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
&lt;/script&gt;

&lt;script type="text/javascript"&gt;
try {
// Choose page tracker id according to domain
  var domains = document.location.hostname.split(".");
  var tld = domains[domains.length-1];
if(tld == "fi") {
  // .fi
  pageTracker = _gat._getTracker("UA-8819100-1");
} else {
  // .com
  pageTracker = _gat._getTracker("UA-8819100-4");
}
pageTracker._trackPageview();
} catch(err) {
}

&lt;/script&gt;</pre>
<p>This is used on <a href="http://www.twinapex.com">www.twinapex.com</a> and <a href="http://www.twinapex.fi">www.twinapex.fi</a> sites.</p>
<p>Use console.log(err) to output possible Javascript in catch {} errors using Firebug.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2009/07/15/scripting-google-analytics-for-multidomain-site/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Python-like urlparser module for Javascript</title>
		<link>http://blog.mfabrik.com/2008/11/29/python-like-urlparser-module-for-javascript/</link>
		<comments>http://blog.mfabrik.com/2008/11/29/python-like-urlparser-module-for-javascript/#comments</comments>
		<pubDate>Sat, 29 Nov 2008 01:56:42 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[fragment]]></category>
		<category><![CDATA[hostname]]></category>
		<category><![CDATA[href]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[location]]></category>
		<category><![CDATA[parse]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[url]]></category>
		<category><![CDATA[urlparse]]></category>
		<category><![CDATA[urlparser]]></category>

		<guid isPermaLink="false">http://blog.redinnovation.com/?p=152</guid>
		<description><![CDATA[I had to deconstruct and reconstruct URLs from pieces when doing advanced Javascripting for Plone. I found this nice library from Denis Laprise. However, it had a bug with fragment extractor and lacked reconstruction possibilies. So I decided to make a new version. Download urlparse.js version 0.2. thank you Couple of examples: var p = [...]]]></description>
			<content:encoded><![CDATA[<p>I had to deconstruct and reconstruct URLs from pieces when doing advanced Javascripting for Plone.</p>
<p>I found this <a href="https://code.poly9.com/trac/browser/urlparser/urlparser.js">nice library</a> from <span class="c">Denis Laprise. However, it had a bug with fragment extractor and lacked reconstruction possibilies. So I decided to make a new version.</span></p>
<p><a href="http://snipplr.com/view/10139/urlparse--pythonlike-url-parser-and-manipulator/">Download urlparse.js version 0.2</a>. thank you <img src='http://blog.mfabrik.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Couple of examples:</p>
<pre>var p = new Poly9.URLParser('http://user:password@poly9.com/pathname?arguments=1#fragment');
p.getHost() == 'poly9.com';
p.getProtocol() == 'http';
p.getPathname() == '/pathname';
p.getQuerystring() == 'arguments=1';
p.getFragment() == 'fragment';
p.getUsername() == 'user';
p.getPassword() == 'password';

var p = new Poly9.URLParser("http://localhost:8080/path);

p.setQuerystring("foo=bar");
p.setFragment("anchor");
p.setPort(7070);

var url = p.getURL() // http://localhost:7070/path?foo=bar#anchor</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2008/11/29/python-like-urlparser-module-for-javascript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

