Stephen Rhyne http://blog.stephenrhyne.com Tutorials I create, stuff I find, ideas I want to share posterous.com Thu, 29 Dec 2011 11:21:00 -0800 Super simple JS templates with String.prototype.tmpl using Ruby/coffeeScript syntax — Gist http://blog.stephenrhyne.com/super-simple-js-templates-with-stringprototyp http://blog.stephenrhyne.com/super-simple-js-templates-with-stringprototyp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
String.prototype.tmpl = function(obj){
var str, keys, _do;

//store string
str = this.toString();

//if no object just return string
if(!obj || typeof obj !== "object"){
return str;
}

//get keys in object
keys = Object.keys(obj);

//loop through keys and replace place holders
_do = function(key){
var rgx = new RegExp("#{"+key+"}", "g");
str = str.replace(rgx, obj[key]);
};

keys.forEach(_do);

return str;
}


//just a simple test
function test(){
var tests, template, report, assert;

tests = [];
resultStr = "string : #{str}\n"+
"object : #{obj}\n"+
"Should be : #{result}\n"+
"Passed : #{passed}\n\n";

report = "";

assert = function(test){
test.result = test.str.tmpl(test.obj);
test.passed = test.result === test.should_be;
test.obj = JSON.stringify(test.obj);
report += resultStr.tmpl(test);
};

tests.push({
str : "Hello, #{value}",
obj : { value : "world" },
should_be : "Hello, world"
});

tests.push({
str : "Welcome #{first_name} #{last_name}!",
obj : { first_name : "Stephen", last_name : "Rhyne" },
should_be : "Welcome Stephen Rhyne"
});

tests.forEach(assert);

console.log(report);

}
//was going to use anon but node.js console didn't like it!
test();

So I wanted to create a super small string interpolator for JavaScript. I really didn't need a full on JS template library. Just a simple helper method that would let me pass an object to a string. You can write a string with "a #{placeholder}" then pass an object to the string with a placeholder key and value..

Example :

"Hi, #{name} you have #{count} credits left".tmpl({ name : "John", count : 10 });

Of course this is somewhat of a contrived example. However, one can see how useful it becomes when you have a long string that you want to reuse with many records.

I borrowed the placeholder syntax from CoffeeScript/Ruby. I am using forEach so some JS engines will not recognize that as a native Array method. Perhaps someone want to commit a more vanilla loop instead!

I'm interested to see other super powerful prototype helpers developers have created. What's your favorite?

-Stephen

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne
Fri, 28 Oct 2011 12:27:00 -0700 Integrate Zendesk forum posts into any website or application. http://blog.stephenrhyne.com/srhynesidd-github http://blog.stephenrhyne.com/srhynesidd-github

Sidd

Sidd, short for Siddhārtha Gautama, is a plug-in for jQuery. It allows you to integrate Zendesk forum posts into your web site/application.

Demo?

I put most of my initial development into building an extensible & flexible plugin so the demos are a little paltry right now. Here's a small demo

Configuration Options:

state

Set the current state to either 0 or 1. This is used for the showMenus method. I suggest leaving it to 0

url

The URL of your Zendesk. This could be your custom domain, e.g., http://support.mydomain.com or just http://name.zendesk.com. This is a required parameter and no default is set

data

To save on http requests & increase performance, you can use json method to copy your entire Zendesk forum posts model to a json string to be saved in a local server file. Must have window.JSON support

Methods :

Init

Use the init method first! This will bind all the sidd plugin methods and data to a desired "scope" element In the below example we are using document as our scope, I recommend using a SINGLE element for the scope.

Init Example :

$(document).sidd("init",{
        url : "http://domain.zendesk.com" 
        // or your mapped domain "http://support.mydomain.com"
    },function(){
        //do something
    });

data

This is your model "getter" method. Use this to filter and return desired Zendesk forum entries saved in $.data(scope).sidd You can filter by any key in forum entry json object! As of 6/2011 that's [body,created_at,flag_type_id, forum_id, hits, id, is_highlighted, is_locked, is_pinned, is_public, organization_id, pinned_index, position, posts_count, submitter_id, title, updated_at, votes_count], AND!.. dom_tag (more about dom_tags later)

Example :

var data = $(document).sidd("data",{
                current_tags : ["login", "access"],
                forum_id : 23422
            });

A Note about the domtag filter.. This is a wonderful feature! Here's how it works. You add tags to your Zendesk forum posts like _wrapper, _nav, _my_other_id and so on. The "" prepended tags (optional) represent id's IN YOUR DOM. Now you have a way to attach zendesk forum data or tooltips to specific parts of your application.

Example :

var data = $(document).sidd("data",{
                         dom_tag : "_"  //or a full id like "_wrapper"
                        },true);

          $.each(data.dom_tags, function(index,selector){

                //get the element by dom_tag
            var el = _this.find(selector+":visible").eq(0), 

                //get the entries containing this dom id
                entries = $.grep(data.filtered,function(obj){
                                return obj.dom_tags.indexOf(selector) !== -1;
                            });
        });

Check out the showMenus code to see how the dom_tag filter is used.

get

This method builds on top of the data method and adds an easy way to perform an action after filtering your posts.

Example :

$(document)
    .sidd("get",{
            body : "password"
        },function(data){
            $.each(data.filtered,function(){});
    })
    .data("chainable",true); //you can still chain from sidd ;)

showMenus

This method takes advantage of the "dom_tag" filter. (Read more above under the data method for an in depth explaination.) The showMenus method will create tooltips next to each element with an DOM id that MATCHES a zendesk tag! It's easiest to understand with a demo.

Example : $(document).sidd("showMenus",{dom_id : "_wrapper"});

The above example will... * filter your zendesk entries that have a tag of "_wrapper" * attempt to find $("#wrapper:visible") * Create a tooltip containing a menu of forums/entry links with an page offset near the $("#wrapper:visible") element!

Note : each menu get's a class of 'sidd-menu'. (See the sidd-menu css file for some nice tooltip styling.) However, You can pass your own $(menu) to the showMenus configuration object to be cloned for each tooltip! So you don't have to use the sidd-menu class.

Example:

$(document).sidd("showMenus",{
    dom_id : "_wrapper", 
    menu : $("<div/>",{"class" : "myownClassName", title : "zendesk-help"})
});

removeMenus

Removes all of the current menus on the page. Currently there is now way to remove only certain items from the menu stack

Example:

$(document).sidd("removeMenus");

toggleMenus

Toggles the menus in the given scope.

Example:

$(document).sidd("toggleMenus");

methods

Returns an array of all of sidd's public methods for easy reference

json

returns a json string of your entire Zendesk forum model to teh console. The purpose of this is to reduce the number of http requests you make to zendesk upon invoking the init function. The number of requests is based on the number of forums you have.

Example:

$(document).sidd('json'); 
    //then c&p the output to say sidd.json

    //then init sidd using the local json model file..
    $.getJSON("../server/sidd.json",function(json){
        $(document).sidd("init",{
            url : "http://support.mymapped_domain.com", //you pass the url anyways for menu links
            data : json
        });
    });

    //or you could use localstorage, amplify.js, or lawnchair to save and recover later!

    localstorage["sidd"] = $(document).sidd('json');

    //later 
    var data = JSON.parse(localstorage["sidd"] || "[]"), 
        config = {url : "http://support.mymapped_domain.com"};
    if(data.length !== 0)
    {
        config[data] = data;
    }
    $(document).sidd("init",config);

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne
Fri, 07 Oct 2011 11:33:00 -0700 Smore - Design beautiful online flyers and publish instantly http://blog.stephenrhyne.com/smore-design-beautiful-online-flyers-and-publ http://blog.stephenrhyne.com/smore-design-beautiful-online-flyers-and-publ

We are Fireplace

We’re two dedicated designers and devs (yes, both of us do both) that love building beautiful and useful products.

We’re currently in TechStars Seattle 2011 and enjoying every moment!

Go ahead and follow us on Twitter.

Shlomi Atar

Lives and breathes the web. Pixel perfect web ninja.

Gilad Avidan

Opinionated hacker with feelings. Product addict and purist.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne
Wed, 23 Mar 2011 12:54:00 -0700 Namespace those anonymous jQuery event callbacks! http://blog.stephenrhyne.com/namespace-those-anonymous-jquery-event-callba http://blog.stephenrhyne.com/namespace-those-anonymous-jquery-event-callba

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne
Sun, 14 Nov 2010 20:29:00 -0800 A better way to update DOM attributes using jQuery http://blog.stephenrhyne.com/a-better-way-to-update-dom-attributes-using-j http://blog.stephenrhyne.com/a-better-way-to-update-dom-attributes-using-j

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// 1. DOUBLE BAD!!

    $("#myLink").attr("name","srhyne");
    $("#myLink").attr("href","http://stephenrhyne.com";
    $("myLink").html("stephenrhyne.com");

// 2. IN MY OPINION STILL VERY BAD..

    $("#mylink")
        .attr("name","srhyne")
        .attr("href","http://stephenrhyne.com")
        .html("stephenrhyne.com")

// 3. NOT AS UBER JQUERY DEVELOPER COOL BUT BETTER! (You don't need $ for everything!)
       
    var myLink = $("#myLink")[0];
        myLink.name = "srhyne";
        myLink.href = "http://stephenrhyne.com";
        myLink.html = ("stephenrhyne.com");

// 4. I link using just plain DOM scripting in #3. but I hate not being able to chain.
// I like this much better..


$.fn.domExtend = function(obj){
$.extend(this[0],obj);
return this;
    };
$(function(){
$("#myLink").domExtend({
name : "srhyne",
href : "http://stephenhyne.com",
innerHTML : "stephenrhyne.com"
});
});

// 5. Of course this is the same as going like this..

     var myLink = $("#myLink")[0],
         changes = {
             name : "srhyne",
href : "http://stephenhyne.com",
innerHTML : "stephenrhyne.com"
         };
      $.extend(myLink,changes);

// 4 AND 5 ARE acceptable to me.

//<a href="http://test.com" name="test" id="myLink" class="thisLink">Change ME!</a>

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne
Sat, 16 Oct 2010 21:46:00 -0700 Name-spacing your jQuery Collections http://blog.stephenrhyne.com/name-spacing-your-jquery-collections http://blog.stephenrhyne.com/name-spacing-your-jquery-collections

It’s a well known jQuery no-no to constantly recall jQuery selectors like so..

$("#id").bind("click",function(){       
    //do something  
});         
//way later in the project  
$("#id").bind("mouseenter",function(){ 
    //do something      
});

But, what I consider an even bigger no-no is having all your jQuery collection variables just dumped out right after a .ready() call.

$(function(){       
    var $wrapper = $("#wrapper"),           
        $col1 = $wrapper.children("#col1"),             
        $col2 = $wrapper.children("#col2"),             
        $a = $wrapper.find("a.action"); //end so on     
});

The problem with declaring your collections are…

  • You are making your functions that deeper in the call stack look waaaay up the scope to find the variable you reference.
  • As your project grows so does your need for selectors and this lack of name-spacing makes your declarations VERY confusing.

My favorite way of keeping track of these selectors is by putting them into objects that I then append to the jQuery object. Like this…

$.extend({
    dom : { 
        window : $(window).scroll(doSomthing),          
        rep_grid : $("#rep_grid").click(doSomething),           
        buttons : {                 
            blue : $("a.blue").data("off",true),                
            red : $("a.red").data("off",false)          
        }       
    }   
});     
//Not to far off your Hungarian Notation style you 
//can now use your selectors like this..    
//NOTE: This is just an example. It means nothing. 
//It's just an example...       
$.dom.buttons.blue.click(function(){
    var window_height = $.dom.window.height();      
    $.dom.rep_grid.css("height",window_height);     
});

Perhaps, you don’t like the Java'esque verbose name-spacing syntax that this sort of practice creates. But, I’m confident you will change your mind as your project grows. By the way consider the added benefits of having your selectors in an object. You can use hasOwnProperty, for in loops, etc.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne
Fri, 30 Jul 2010 08:18:11 -0700 Article: Mogotest | Web Testing Made Easier http://blog.stephenrhyne.com/article-mogotest-web-testing-made-easier http://blog.stephenrhyne.com/article-mogotest-web-testing-made-easier

Mogotest | Web Testing Made Easier
http://mogotest.com/

(Sent from Flipboard)

Sent from my iPad

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne
Tue, 20 Jul 2010 09:13:24 -0700 50 Useful JavaScript and jQuery Techniques and Plugins http://blog.stephenrhyne.com/50-useful-javascript-and-jquery-techniques-an http://blog.stephenrhyne.com/50-useful-javascript-and-jquery-techniques-an http://www.noupe.com/javascript/50-useful-javascript-and-jquery-techniques-an...


Sent from my iPad

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne
Sat, 12 Jun 2010 09:44:12 -0700 Deep Profiling jQuery Apps http://blog.stephenrhyne.com/deep-profiling-jquery-apps http://blog.stephenrhyne.com/deep-profiling-jquery-apps http://ejohn.org/blog/deep-profiling-jquery-apps/#postcomment


Sent from my iPad

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne
Thu, 10 Jun 2010 09:43:26 -0700 JSLint on Mac + TextMate integration http://blog.stephenrhyne.com/jslint-on-mac-textmate-integration http://blog.stephenrhyne.com/jslint-on-mac-textmate-integration http://www.phpied.com/jslint-on-mac-textmate/

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne
Fri, 12 Feb 2010 09:48:02 -0800 Early look at PDiPhone app I'm building. http://blog.stephenrhyne.com/early-look-at-pdiphone-app-im-building http://blog.stephenrhyne.com/early-look-at-pdiphone-app-im-building
Photo

Stephen Rhyne 206.412.5334

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne
Mon, 08 Feb 2010 13:09:04 -0800 9 Useful jQuery Calendar And Date Picker Plugins For Web Designers http://blog.stephenrhyne.com/9-useful-jquery-calendar-and-date-picker-plug http://blog.stephenrhyne.com/9-useful-jquery-calendar-and-date-picker-plug

I'm going to be adding some "snapshot" functionality to our web app "WebPDI". I found these resources useful. 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne
Mon, 08 Feb 2010 09:15:42 -0800 Facebook Hopes to Revolutionize PHP with “Hip Hop” http://blog.stephenrhyne.com/facebook-hopes-to-revolutionize-php-with-hip http://blog.stephenrhyne.com/facebook-hopes-to-revolutionize-php-with-hip

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne
Sun, 27 Dec 2009 18:42:00 -0800 APItite || Really Easy Zoho CRM API Development http://blog.stephenrhyne.com/apitite-really-easy-zoho-crm-api-development http://blog.stephenrhyne.com/apitite-really-easy-zoho-crm-api-development

http://stephenrhyne.com/apitite/apitite-docs-zoho-crm-api.html


Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne
Mon, 07 Dec 2009 12:04:57 -0800 Phonegap Seminar @codebits.eu from Brian LeRoux http://blog.stephenrhyne.com/phonegap-seminar-codebitseu-from-brian-leroux http://blog.stephenrhyne.com/phonegap-seminar-codebitseu-from-brian-leroux

Anyone interested in mobile application development should watch this video! I am getting more and more involved with this project. We are using Phonegap for an upcoming native iphone app

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne
Wed, 25 Nov 2009 12:59:00 -0800 Easy Zoho Creator Form CSS with ZCStyles (Free on ZC Marketplace) http://blog.stephenrhyne.com/easy-zoho-creator-form-css-with-getformstyle http://blog.stephenrhyne.com/easy-zoho-creator-form-css-with-getformstyle

Just whipped up a little ZC function that makes it super easy to customize the look of  ALL your forms in all your applications. I got tired of having to make markup changes in many, many html views and links when using the form customization parameters.

Get it here on the marketplace

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne
Thu, 05 Nov 2009 09:01:50 -0800 Tutorial : Consuming RESTful Resources (XML & JSON) in Zoho Creator http://blog.stephenrhyne.com/tutorial-consuming-restful-resources-xml-and http://blog.stephenrhyne.com/tutorial-consuming-restful-resources-xml-and

This post is in response to this Zoho Creator Forum Post

Using Zoho Creator's XML parsing capabilites.. Sounds daunting but it really isn't. Here's a small example of how you get your file, then turn it into an XMLLIST which then acts almost exactly like a regular list in Zoho Creator.


Let's walk through one..

Now this will be a getURL() example...

1. Create your REST URL call. This is the URL the getURL() goes OUT TO to retrieve the XML... Here's an example...

url = "http://mywebservice.com/api/dataform?param1=&param2=&param3=";

2. Now, we create a map variable to hold our response from the getURL() function. The false value tells the getURL to return a detailed response. THIS WE WANT for parsing XML.

    mapVariable = getUrl(url,false);

3. Now that we have our response in the mapvar, we need to grab the "string" response that came back when we called the getUrl() function. We do this by "getting" the "responseText" key. This is exactly the same way you grab a key out of other maps.

    stringResponse = mapvar.get("responseText");

4. Ok, now we have the whole XML response saved in the "stringResponse" variable. But at this point the XML isn't really actually XML it's actually a long "string" value. (Note: if you run an "info" log message on your stringResponse variable right now. YOU WON'T see the XML elements and you might think you did something wrong. YOU DIDN'T ZC doesn't show the XML markup in log messages unless you convert to XML then back to string. Ok, that was a TMI, but I just thought I would let you know.)

5. Ok let's convert that "string" value of stringResponse to XML!

xmlResponse = stringResponse.toXML();

6. Now, here's the hardest concept to understand I think for new users. Now that we have the REAL XML we need to message it a little bit so that we can get it in a format that's more usable in Zoho Creator.  

What we need to do is "target"/put our focus on the XML nodes that we want to use in our data. Basically, we want to POINT to the nodes of the records we want to create a list out of..Let's take a look at some examples....

<result>

     <data>

         <row></row>

         <row></row>

        <row></row>

   </data>

</result>

So in the above example the <rows> are what we want to import into Zoho Creator. So let's point our XPATH to that node "address".

result/data/row

Ok, let's do another example.. What if you just wanted to get the data OF THE FIRST <row>. Let's say our xml looked like this....

<result>

    <data>

         <row>

             <first_name>Rick</first_name>

             <last_name>James</last_name>

             <email>rjames@imrickjames.com</email>

         </row>

         <row></row>

        <row></row>

   </data>

</result>

In the above example we would just want to make our xpath.....

result/data/row[1]

this would xpath would return only the nodes inside <row> one.

7. Ok, once you have targeted the data nodes that you want to create a list out of, let's shorten our XML to reflect the desired path..

startPath = xmlResponse.executeXPath("result/data/row[1]");

For the rest of this example. Let's just go with all the <row>'s and use this XML... . so again our xpath for our startPath URL would be result/data/row

<result>

    <data>

         <row>

             <first_name>Rick</first_name>

             <last_name>James</last_name>

             <email>rjames@imrickjames.com</email>

         </row>

         <row>

            <first_name>Charlie</first_name>

             <last_name>Murphy</last_name>

             <email>cmurphy@charliemurphy.com</email>

         </row>

        <row>

            <first_name>Stephen</first_name>

             <last_name>Baldwin</last_name>

             <email>sbaldwin@realitytv.com</email>

        </row>

   </data>

</result>

 

8. Ok, now let's convert the XML to an XMLlist! Converting your data to a Zoho Creator XMLList() let's you ITERATE/LOOP through your desired XML nodes USING the built in "for each element" functionality already used for other lists.

xmllist = startPath.toXmlList();

9. Now we have our list!  We can do all sorts of great wonderous things once you have your XML data in this format.

Let's create "for each element" loop

    for each r in xmllist
    {
    }

10. Inside our loop we have to EXECUTE the xpath for each row's child nodes so that we can get the data out of it.

Here's how... 

    for each r in xmllist
    {

          firstName = r.executeXPath(''/row/first_name/text()');

           lastName = r.executeXPath(''/row/last_name/text()');

           email = r.executeXPath(''/row/email/text()');

    }

11. Notice that my Xpath's in my executeXpath() functions START WITH the node we LEFT OFF of in step 7 when we targeted our XML node!

12. Ok, so you have your data in the XML list and you know how to get the data into variables.. What else can you do?

Example 1. check to see if these email addresses are already in your Zoho Creator app form and IF THEY AREN'T in the desired form then INSERT that xml row into the desired Zoho form!

get all the email addresses....

getForm = form1[email != ""];

emailList = getForm.email.getAll();

 

    for each r in xmllist
    {

          firstName = r.executeXPath(''/row/first_name/text()');

           lastName = r.executeXPath(''/row/last_name/text()');

           email = r.executeXPath(''/row/email/text()');

           if(!emailList.contains(email))

           {

              insert into form1

              [

                  Added_User = zoho.loginuser

                 first_n ame = first_name

                 last_name = last_name

                  email = email

               ]

           }

    }

I hope this helps all of you that want to use this functionality but have struggled to wrap your head around it. I know it took me a little while to get used to.

Also, there are many other great things you can do with the Xpath functionalty. LIKE....

1. create a for each loop inside a loop

2. create node agnostic xpaths

3. MY FAVORITE stop using Xpath completely on XMLlists by converting your xml_list to a "list map"/associative array. See this post. 

Here is a great simple Xpath resource

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne
Wed, 21 Oct 2009 10:52:30 -0700 Zoho Creator Dev Community http://blog.stephenrhyne.com/zoho-creator-dev-community http://blog.stephenrhyne.com/zoho-creator-dev-community

This is in reply to : Snake eating it's own tail?

First,

Let us give credit to the developers who set the precedent of sharing knowledge and assisting others early on..(years back). I think it's safe to say that if they hadn't set this precedent we might not have this great ebb and flow of responses like we do today.

Second,
Smart developers/ businesses (I think most ZC developers) gives away scarcity to sell the even more scarce resource more often. What I mean by this...A good developer understands that by giving away some scarcity  (knowledge, open source app, resources, tips), he increases his following, professional position, client trust, etc. This leads to the sale of more of the most scarce resource. This would be a developers billable time.

Do you think that a person like Gaev is getting less business because he has over 1200 ZC posts? Many of these posts are him helping other developers like me AND new beginners just learning to declare a variable. No, he is definitely not getting less business.

Let's take this to a more macro level. John Resig, creator of jQuery. I think it's safe to say that he is making more money now after giving away, creating jQuery then he would have keeping this tool to himself and sharing it with only his clients or his employer Mozilla. Don't you think? I know this is sort of a ridiculous example. But it gets my point across.

I think that Gaev and other ZC developers alike have learned to take the broader view in regards to getting ZC jobs. By all of us adding a wealth of content to the forums the Zoho Creator products grows in popularity which in turns brings more business to all the developers. Yes, I am sure there are times where a new developer that hasn't "paid his dues" gets a "Marketplace" project when maybe he isn't the best developer for the job. But, most savvy prospects can review work and see ZC forum posts to discern who's right for the job.

Zoho Creator has invested much time, money, resources into creating a "one stop shop" for Zoho Creator. ZC apps, wiki, forum, marketplace - these are all a click away. For this reason the opportunity cost for a developer to share his Zoho Creator knowledge isn't as high.

In contrast a Web Designer/Developer on his own would need a strong presence on many job boards, a nicely setup blog with tons of traffic from potential clients, a group of Twitter users (who have their own target audience) periodicially RT'ing your good ZC forum posts, as well as many other intangible assets.

Here's how I think the Zoho Creator community is setup.

 The first group of people are DIY'ers. They are almost always NOT a developer working for/as a development company. They are simply men and women looking to solve a business problem. They ARE NOT competition for developers and are sometimes future business! So it makes sense to help them. Many of them are the type who will NEVER use a developer and THIS IS OK TO ME. However, on many of my Zoho Creator poject starts the first 10 minutes of the conversation is about the Zoho Creator application they started but got stuck somewhere on.

The second group of people on the forums are people who are "kicking the tires" of Zoho Creator to get an idea about Zoho Creator's capabilities. They might be an employee or IT worker for a business.  These people are SOON TO BE OR FUTURE BUSINESS AS WELL. These are the sort of people we as third party developers need to engage with a lot to show/ convince them of how Zoho Creator can solve their problems.

The third group is the developer community.. They help other DIY'ers, "tire kickers", and other developers with their projects.

Stephen Rhyne
Owner
Rhyne Design
@srhyne

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne
Sat, 17 Oct 2009 13:16:51 -0700 Zoho Creator Map Function (Advanced) http://blog.stephenrhyne.com/zoho-creator-map-function-advanced http://blog.stephenrhyne.com/zoho-creator-map-function-advanced

 This is a follow up post to the following two other posts....

1. Map Tutorial (Beginners)

2. Map Tutorial (Intermediate) 

In this post I am going to talk about some more advanced ideas concepts in regards to using maps and lists together.

If you are reading this you are already aware of the power of using lists and maps together to create powerful DS scripts.


I'm going to cover HOW TO COMBINE A ZC MAP AND A ZC LIST TO CREATE MULTI-DIMENSIONAL ARRAYS( Think form records stored in script format).

In PHP it's very easy to create a multi-dimensional array (many map variables inside a big list) and encode

this into JSON... A PHP multidimensional associative array looks like this....

$client_array = array(

     "client_address"=>array(

       "street"=>"PO Box 1000",

        "city"=>"Seattle",

         "state"=>"WA",

          "zip"=>"98122"

      ),

     "contact_info"=>array(

     "mobile"=>"555-1212",

      "email"=>"john@acme.com"

     )

);

In the above PHP example the $client_array would be a ZC Deluge Script list() where list.size() == 2.

the client_address and client_info arrays would be ZC Deluge Script map()'s


Stephen, Why would I want to make a multi-dimensional array in Zoho Creator? 

1. Store records in script format to be added to a new application upon loading it for the first time. (instead of XML or a getURL() call)

2. Convert cumbersome XMLList()'s to an easy list/map format...

Replace  _.executeXPath("/row/blah/blah/text()"); with a simple map.get("key"); 

NOTE: Try executing an XPath on an xmlList you called through a function! Your Xpath variable will come back null! This solves that problem/bug. (Let me know if you have solved this issue in the past.)

3. Store huge amounts of structured records data IN a variable to be looped through later. 


Reason for coming up with this idea.

Recently I have been doing a lot of Zoho Creator API work with PHP & jQuery/Javascript coding using the JSON feed instead of XML... and I LOVE IT!

JSON is such a great data format and it's so easy to traverse over/iterate through the records in JSON..

Example: Traversing over JSON in Javascript

for (i = 0; i < length; i++) {
                    var name = suppliers[i].name;
                    var address = suppliers[i].address;
                    var zoho_id = suppliers[i].zoho_id;
                    });

Now back to Zoho Creator Maps! Zoho Creator Maps ARE VALID JSON when you output them to string..

But, at first I was completely unable to traverse over ZC Maps like you do in regular scripting (like the above JS example).

If you have noticed there is no "for each" option in the map manipulations on the script builder menu AND there isn't really a clear cut way to store key,value pairs in a regular list. (You could mess with indexes or create text deliminators and stuff but it's sort of a bad way of doing things.)

So I tried putting map() variables inside a list. This way I could store my maps inside a format that Zoho Creator permits looping.

If you try to put a map() variable inside a list this is what you get.......

Error at line : 13
Unsupported type given as argument

BUT! What if you convert your map variable to a STRING! Then your list is just holding text (text that is perfectly willing to be converted back into a map later AND is perfectly willing to be saved in a list!)

Let's look at an example of how we can create a MULTI-DIMENSIONAL ARRAY in Zoho Creator....


Creating a multi-dimensional array in Zoho Creator

list test.array_encode()
{
    start_list = {"node1", "node2", "node3", "node4"};
    end_list = List();
    for each r in start_list
    {
        map = map();
        map.put("field1", 1);
        map.put("field2", 2);
        map.put("feild3", 3);
        map.put("field4", 4);
        stringMap = map;
        end_list.add(stringMap.toString());
    }
    test_list = list();
    for each test in end_list
     {
         map = test.toMap();
         test_list.add(map.get("field1"));   
     }
    info test_list;
    return end_list;
}


1. We created a function that returns a list

list test.array_encode()
{}

2. We created a "start_list" with node1 through node 4. 

    start_list = {"node1", "node2", "node3", "node4"};

 The nodes are simply a list telling us how many iterations we are going to have. This could instead be a collection list of records or rows in an XML list perhaps.

3. Now we create an "end_list" this list will hold our key/value pairs (created by the map function).

end_list = List();

In our PHP example the end_list would be the $client_array variable and the "r" variable in the loop would be each
array inside the $client_array (separated by commas).

4. We create a new map, PUT our keys and values into the map, then convert it to a string!

map = map();
        map.put("field1", 1);
        map.put("field2", 2);
        map.put("feild3", 3);
        map.put("field4", 4);
        stringMap = map;
        end_list.add(stringMap.toString());

OUTPUT FROM HERE!

 [{"field4":4,"feild3":3,"field1":1,"field2":2}, {"field4":4,"feild3":3,"field1":1,"field2":2}, {"field4":4,"feild3":3,"field1":1,"field2":2}, {"field4":4,"feild3":3,"field1":1,"field2":2}]
5. LET'S TEST IT!

    test_list = list();
    for each test in end_list
     {
         map = test.toMap();
         test_list.add(map.get("field1"));   
     }
    info test_list;

Here we create a "test_list" to grab our "values" from the array. We create a new map variable "map" then convert the map string BACK INTO A MAP. Then we just add the the map value to our list and "debug/Info" the test_list..

SURE ENOUGH THE "test_list" comes back with

1, 1, 1, 1

ISN'T THAT GREAT! If you start to think about it more you will see the similarities to the "for each record" function

but instead of using form field names to get your value you use the map's key value!



I hope you find great use out of this concept! Soon I will be posting some more ways to incorporate it into your DS scripts LIKE converting XML to ZC arrays without mapping hundreds of XPaths, storing many records inside ONE record, etc.

PLEASE let me know if you have ideas or suggestions on how to make this concept better. I am always open to ideas. If you have any questions you can go to my website, or post it here as a comment on the forum.

Stephen Rhyne
Owner
Rhyne Design

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne
Sat, 17 Oct 2009 10:52:00 -0700 Zoho Creator Map Function (Intermediate) http://blog.stephenrhyne.com/zoho-creator-map-function-intermediate http://blog.stephenrhyne.com/zoho-creator-map-function-intermediate

View Post on Zoho Creator Forum

This is a follow up post to map tutorial (Beginners)

Hello ZC fans,

I in the last post I discussed some of the basics about the map() function/feature. The last thing I discussed in the post was how to pull in map values from a map function (in functions tab) to a local script (form, view).

But what if you wanted to do the opposite? What if you wanted to transfer a map from a form or view to a function.


Pass a local map variable from form or view to a function

First let's make our map

myMap = map();
myMap.put("key1","value1");
myMap.put("key2",2);
myMap.put("key3",false);

Now let's send this map variable to a function

thisapp.PushmapFunction(myMap);

There! now your map keys and values are ready to be manipulated by your function!


You will find that sending maps to functions is a very useful way to send a lot of parameters to a function quickly.. Sending a single map to your function can save you time and confusion later. They also give you a little more flexibility.

Here's a sample function that could be a little cubersome. It looks like this when you call it.....

thisapp.myCrazyFunction(input.field1, input.field2, input.field3, input.field4, input.field5, input.field6, input.field7, input.field8, input.field9);

This is TOTALLY A VALID FUNCTION! But what if you wanted to change the form field type of input.field2 from a string value to a long value? ZC functions require you to assign an input type to each function parameter. So since you already set "myCrazyFunction" to take a string value by changing input.field2 from string to long, your function becomes invalid.

You would either need to convert input.field2 to a string value (field2_str = field2.toString();) or you would need to change "myCrazyFunction" to except a long value.

If you create and pass a single map variable that holds all your 9 form input field values YOU BYPASS the individual field types. This keeps your function valid and saves you time! (this works the same way for lists).

Now don't get me wrong.. Parameters are a good thing and there are many places where sending individual parameters is a better practice.


The truly powerful feature about maps is that keys can be dynamically named.. You can do some wonderful stuff when you combine the traversable/looping power of lists WITH the "key/value" feature of maps.


"keys can be dynamically named.... "

If you don't know what I mean by this then let's take look at the following INVALID ZC SCRIPT...

value_list = {1,2,3,4,5};
for each value in value_list
{
value+"value" = value;
}

What I was trying to do is dynamically name the variables in the loop. So that I come up with something like this...

value1 = 1;, value2=2; value3 = 3, value4=4;

BUT YOU CAN'T DO THIS IN ZOHO CREATOR. You cannot name variables dynamically. You CAN do this in a full featured scripting language. However, ZC is purposely stripped down. (That's the beauty of it!)

Just so you know... in PHP naming variables is simple..  ${"value".1}  = 1 renders to $value1 = 1.

Anyways this isn't a PHP tutorial. Back on track... :)


Now let's look at the same sort of list loop but this time we are going to use a map and THE ZC DS WILL BE VALID SCRIPT!

value_list = {1,2,3,4,5};
myMap = map();

for each value in value_list
{
myMap.put("value"+value,value);
}

So what does this give us?

 

myMap = {value1=1, value2=2, value3=3, value4=4, value5=5};Now we can get all of our "value_list" values by using a key! myMap.get("value1") == 1;So dynamic naming of keys is again so powerful. And this is all possible because keyvalues are string values NOT a true variable. To hammer down my point of the power of dynamic naming of keys even more. Let's look at the following very powerful piece of code... Put all your form fields and form values into a map variable WITH 7 LINES OF CODE!fields = getFieldNames();form_map = map();for each field in fields{ value = getFieldValue(field); form_map.put(field, value);}fields = getFieldNames(); returns a string list of all of the form field names.form_map = map(); creates a new mapfor each field in fields{} is a loop we use to populate form_map map variablevalue = getFieldValue(field); by first creating a list of the field names in the firstline we are able to loop through the form and get the field values for each field!form_map.put(field, value); now we just put our field name from the list as our key and the valuewe got using the list as our value.ISN'T THAT COOL?! With just 7 lines of code we were able to take all the data from theform and turn it into a map! You could take this form_map and pass it to a functionor you could pass it to a postURL() function that takes the VALID JSON and posts it toan outside server PHP script to save to a database! Whatever you want. The point is that lists and maps a just great to use together. Here's another example of how we can use a list and a map together to create powerfulcode. Let's take our fields list and our form_map and send them to a function! //form side send list and map to functionthisapp.myMapFunction(fields, form_map);//on the function endvoid myMapFunction(list fields, map form_map){ for each field in fields { if(!field.contains("client_")) { form_map.remove(field);  } } request_map = map(); request_map.put("form_map",form_map); xml_response = postUrl("http://RESTresourceExample.com",request_map,false); response = xml_response.get("responseText"); response = response.executeXPath("/response/result/message/text()"); return response;}So in this last example we...1. looped through each field name that we got from the form2. We validated that the form field HAD THE STRING "client_" in it. (This means thatyou can change which fields get used in your script SIMPLY BY CHANGING/APPENDING YOUR FIELDNAME! This is a great tool to use if you are building marketplace apps as you give the usermore control without knowing DS)3. We removed any map key,value pairs that didn't match the "client_" field name validation4. We sent the map/JSON to a RESTful resource/web service to be processed. 5. We get the response... I hope you found these things useful.. In the next post I will be focusing on moreadvanced map function snippets and I'll post my FAVORIATE ZC discovery of all time!Hopefully it's something new to the community. Maybe it's not. If you have ideas or other great Map tricks! PLEASE POST THEM!

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/207609/sideshot_small.jpg http://posterous.com/users/4bhugkgeZW5b Stephen Rhyne Stephen Rhyne Stephen Rhyne