diff --git a/_images/creating-app-ss.jpg b/_images/creating-app-ss.jpg new file mode 100644 index 0000000..99495e0 Binary files /dev/null and b/_images/creating-app-ss.jpg differ diff --git a/_images/quick-start-ss.jpg b/_images/quick-start-ss.jpg new file mode 100644 index 0000000..8204ff6 Binary files /dev/null and b/_images/quick-start-ss.jpg differ diff --git a/_images/screen1.png b/_images/screen1.png new file mode 100644 index 0000000..176d6a1 Binary files /dev/null and b/_images/screen1.png differ diff --git a/_images/screen2.png b/_images/screen2.png new file mode 100644 index 0000000..19d9f66 Binary files /dev/null and b/_images/screen2.png differ diff --git a/_sources/ab-testing-android.txt b/_sources/ab-testing-android.txt new file mode 100644 index 0000000..cbdb7f7 --- /dev/null +++ b/_sources/ab-testing-android.txt @@ -0,0 +1,123 @@ +Android SDK +=========== + +If you don't have an account on your Clutch.io instance yet, you'll need to +`do that first`_. Otherwise, follow the steps below. + + +Getting Started +--------------- + +First, download the `Clutch library`_ JAR file, and add it to your project. +Now, in your project's main Activity, you should add three calls: one in +``onCreate``, another in ``onPause``, and finally one in ``onResume``. Here's +how it should look: + +In your ``onCreate``, call the ``ClutchAB.setup(Context ctx, String key)`` +method: + +.. code-block:: java + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + ClutchAB.setup(this.getApplicationContext() + "YOUR_APPLICATION_KEY", + "YOUR_RPC_URL" + ); + + // The rest of your code here, maybe something like: + // setContentView(R.layout.main); + } + +In your ``onPause``, call the ``ClutchAB.onPause()`` method: + +.. code-block:: java + + protected void onPause() { + super.onPause(); + ClutchAB.onPause(); + } + +In your ``onResume``, call the ``ClutchAB.onResume()`` method: + +.. code-block:: java + + protected void onResume() { + super.onResume(); + ClutchAB.onResume(); + } + +Those three integration points will set everything up, and prepare your code to +begin A/B testing. + + +Normal Tests +------------ + +The function for running a test is +``ClutchAB.test(String name, ClutchABTest test)``. The ``ClutchABTest`` object +should be an anonymous subclass and you can implement ``public void A()`` all +the way up to ``public void J()`` for up to ten different tests per experiment. + +Example: + +.. code-block:: java + + // Find our login button + final Button loginButton = (Button)findViewById(R.id.login_button); + + // Test which color performs better + ClutchAB.test("loginButtonColor", new ClutchABTest() { + public void A() { + // Red? + loginButton.setBackgroundColor(Color.RED); + } + public void B() { + // Or green? + loginButton.setBackgroundColor(Color.GREEN); + } + }); + + +Data-driven Tests +----------------- + +The function for running a data-driven test is +``ClutchAB.test(String name, ClutchABDataTest test)``. The +``ClutchABDataTest`` object should be an anonymous subclass that must implement +``public void action(JSONObject testData)``. + +Example: + +.. code-block:: java + + // Find our login button + final Button loginButton = (Button)findViewById(R.id.login_button); + + ClutchAB.test("loginButtonTitle", new ClutchABDataTest() { + public void action(JSONObject testData) { + loginButton.setText(testData.optString("title")); + } + }); + + +Goal Reached +------------ + +The function for noting that a goal was reached is +``ClutchAB.goalReached(String name)``, where the argument is the test's short +name. + +Example: + +.. code-block:: java + + public void onNewAccountCreated() { + // A new account was created, so whatever button color was chosen, worked! + ClutchAB.goalReached("loginButtonColor"); + } + + +.. _`do that first`: http://127.0.0.1:8000/register/ +.. _`Clutch library`: https://github.com/downloads/clutchio/clutchandroid/Clutch-Android-Latest.jar \ No newline at end of file diff --git a/_sources/ab-testing-ios.txt b/_sources/ab-testing-ios.txt new file mode 100644 index 0000000..4307875 --- /dev/null +++ b/_sources/ab-testing-ios.txt @@ -0,0 +1,132 @@ +iOS SDK +======= + +If you don't have an account on your Clutch.io instance yet, you'll need to +`do that first`_. Otherwise, follow the steps below. + + +Getting Started +--------------- + +First make sure you have the `Clutch library`_ added to your project. To do +so, download the library, extract the zip file, and drag the Clutch.framework +folder into your project. Make sure that the library is in your project's +linked frameworks section. The `Clutch library`_ depends on libsqlite3.dylib, +so make sure to link that as well. + +Now import the Clutch A/B Testing library in your project's ``AppDelegate.h``, +like so: + +.. code-block:: obj-c + + #import + +Now in your project's ``AppDelegate.m``, under +``application:didFinishLaunchingWithOptions:``, add the following code: + +.. code-block:: obj-c + + [ClutchAB setupForKey:@"YOUR_APPLICATION_KEY" rpcURL:@"YOUR_RPC_URL"]; + +That's it--you're now set up to run tests! + + +Normal Tests +------------ + +The function for running a test is ``testWithName:A:B:``. This can be given up +to 10 different code blocks, by adding the next letter in the alphabet. A test +with four code blocks would look like this: ``testWithName:A:B:C:D:``. + +Example: + +.. code-block:: obj-c + + // Create a button and add it to the navigation bar + UIBarButtonItem *loginButton = [ + [UIBarButtonItem alloc] initWithTitle:@"Log In" + style:UIBarButtonItemStyleBordered + target:self + action:@selector(ensureUser)]; + + self.navigationItem.rightBarButtonItem = loginButton; + + // Test which color of tint performs better + [ClutchAB testWithName:@"loginButtonColor" A:^{ + // Red? + loginButton.tintColor = [UIColor redColor]; + } B:^{ + // Or green? + loginButton.tintColor = [UIColor greenColor]; + }]; + + [loginButton release]; + + +Data-driven Tests +----------------- + +The function for running a data-driven test is ``testWithName:data``. The code +block that's passed in must accept one NSDictionary argument. + +Example: + +.. code-block:: obj-c + + // Create a button and add it to the navigation bar + UIBarButtonItem *loginButton = [ + [UIBarButtonItem alloc] initWithTitle:@"Log In" + style:UIBarButtonItemStyleBordered + target:self + action:@selector(ensureUser)]; + + self.navigationItem.rightBarButtonItem = loginButton; + + [ClutchAB testWithName:@"loginButtonTitle" data:^(NSDictionary *testData) { + // Extract the title from the testData dictionary, and assign it to the button. + loginButton.title = [testData objectForKey:@"title"]; + }]; + + [loginButton release]; + + +Goal Reached +------------ + +The function for noting that a goal was reached is ``goalReached:``, where the +argument is the test's short name. + +Example: + +.. code-block:: obj-c + + - (void)newAccountCreated { + // A new account was created, so whatever button color was chosen, worked! + [ClutchAB goalReached:@"loginButtonColor"]; + } + + +Extras +------ + +It's very common for data-driven tests to be color-related. To aid in this, we +have provided a simple function for getting a UIColor out of a hex-string. + +Example: + +.. code-block:: obj-c + + UIColor *buttonColor = [ClutchAB colorFromHex:@"FF0044"]; + +Here's how it might be used with a data-driven test: + +.. code-block:: obj-c + + [ClutchAB testWithName:@"loginButtonVariableColor" data:^(NSDictionary *testData) { + // Extract the color from the testData dictionary, and assign it to the button. + loginButton.tintColor = [ClutchAB colorFromHex:[testData objectForKey:@"color"]]; + }]; + + +.. _`do that first`: http://127.0.0.1:8000/register/ +.. _`Clutch library`: https://github.com/downloads/clutchio/clutchios/Clutch-iOS-Latest.zip \ No newline at end of file diff --git a/_sources/ab-testing-overview.txt b/_sources/ab-testing-overview.txt new file mode 100644 index 0000000..ee6827a --- /dev/null +++ b/_sources/ab-testing-overview.txt @@ -0,0 +1,35 @@ +Overview +======== + +A/B testing is a way of showing users different variations of your app, and +then measuring how each variation affects your goals. For example, if you're +interested in having your users make more in-app purchases, you might test the +phrase "buy more coins now!" versus "save time by buying coins". Clutch's A/B +testing tools can tell you which one will make you more money. + +Types of Tests (Normal vs. Data-Driven) +--------------------------------------- + +With Clutch's A/B testing framework, you have the option of two different types +of tests: normal, and data-driven. + +**Normal** tests are simpler: you give the framework two (or more) different +pieces of code to run. We then choose one of those pieces of code, and run it, +and report back to you which version improves whichever metrics you care about. +This is best for qualitative things like whether a label should go on the left +or right side of an image. + +**Data-driven** tests only have one code path, but that code is passed data from +the server, which can be changed after the app is live in the app store. Your +code should extract some variable from that data, and use it in it's test. +This is good for quantitative things like button color, font size, or text +copy. + + +Tracking Goals +-------------- + +Tests are only good when they can measure some metric and show you which path +is performing better. To help out our system, that metric should be a "goal". +Good examples of goals are things like an in-app purchase, a new account +created, or even a tap on an advertisement. \ No newline at end of file diff --git a/_sources/ab-testing-screencasts.txt b/_sources/ab-testing-screencasts.txt new file mode 100644 index 0000000..0f4935a --- /dev/null +++ b/_sources/ab-testing-screencasts.txt @@ -0,0 +1,31 @@ +Screencasts +=========== + +Everyone learns in different ways. For some, the best way to learn a new tool +is to pore over documentation for hours. For others, jumping in on the deep +end and just starting to build something is the best. For others still, visual +and/or audio walkthroughs are best. Because of that, we want to make sure +there are ample examples of each! Here's our collection of screencasts: + +Getting Started - iOS +--------------------- + +In this screencast we will start a new Clutch A/B testing project for an +existing iOS application, explaining in detail each step that's required and +why. + +.. raw:: html + + + + +Getting Started - Android +------------------------- + +In this screencast we will start a new Clutch A/B testing project for an +existing Android application, explaining in detail each step that's required +and why. + +.. raw:: html + + \ No newline at end of file diff --git a/_sources/ab-testing.txt b/_sources/ab-testing.txt new file mode 100644 index 0000000..febf362 --- /dev/null +++ b/_sources/ab-testing.txt @@ -0,0 +1,10 @@ +Clutch A/B Testing +================== + +.. toctree:: + :maxdepth: 2 + + ab-testing-overview + ab-testing-ios + ab-testing-android + ab-testing-screencasts \ No newline at end of file diff --git a/_sources/addingnewscreen.txt b/_sources/addingnewscreen.txt new file mode 100644 index 0000000..fabf237 --- /dev/null +++ b/_sources/addingnewscreen.txt @@ -0,0 +1,130 @@ +Adding a New Screen +=================== + +Once you have your app all set up and configured, the most common task you will +want to do is add a new screen. Fortunately, this is quite easy! + +First, come up with a short name that you would like to identify this new +screen, which we refer to as the "slug", and the Objective-C class name. For +example if you are creating a screen to present a photo to the user, you might +choose ``photo`` as your slug, and you might want to choose something like +``PhotoViewController`` for your new file in XCode. + +To help make this easier, we've created a tool to help get the details right. +All you have to do is enter your choices below: + +.. raw:: html + + + +
+
+ + +
+
+ +Now you should type this command into +Terminal.app (make sure you change to the directory holding your Clutch +JavaScript first):: + + clutch startscreen $SLUG$ + +Now you should go to your XCode project and add a new file. Choose +"UIViewController subclass" when it asks. Name it what you decided above, and +then copy this into $NAME$.h: + +.. code-block:: obj-c + + #import + #import + + @interface $NAME$ : UIViewController + + @property (nonatomic, retain) ClutchView *clutchView; + + @end + +Now copy this into $NAME$.m: + +.. code-block:: obj-c + + #import "$NAME$.h" + + @implementation $NAME$ + + @synthesize clutchView = _clutchView; + + - (void)didReceiveMemoryWarning + { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + + // Release any cached data, images, etc that aren't in use. + } + + #pragma mark - ClutchViewDelegate + + - (void)clutchView:(ClutchView *)clutchView + methodCalled:(NSString *)method + withParams:(NSDictionary *)params + callback:(void(^)(id))callback { + // Handle any events coming from the JavaScript of your Clutch view here + if([method isEqualToString:@"tapped"]) { + NSLog(@"Tapped: %@\n", [params objectForKey:@"value"]); + } + } + + #pragma mark - View lifecycle + + - (void)loadView + { + self.view = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; + + self.clutchView = [[ClutchView alloc] initWithFrame:CGRectMake(0, 0, 320, 367) + andSlug:@"$SLUG$"]; + [self.clutchView release]; + self.clutchView.delegate = self; + [self.view addSubview:self.clutchView]; + } + + /* + // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. + - (void)viewDidLoad + { + [super viewDidLoad]; + } + */ + + - (void)viewDidUnload + { + [super viewDidUnload]; + self.clutchView = nil; + } + + - (void)viewDidAppear:(BOOL)animated + { + [super viewDidAppear:animated]; + [self.clutchView viewDidAppear:animated]; + } + + - (void)viewDidDisappear:(BOOL)animated { + [super viewDidDisappear:animated]; + [self.clutchView viewDidDisappear:animated]; + } + + - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation + { + // Return YES for supported orientations + return (interfaceOrientation == UIInterfaceOrientationPortrait); + } + + @end + +This is a standard ``UIViewController`` subclass, which instantiates a single +``ClutchView`` instance and adds it to the view, sets itself up as a delegate +to handle events that come in from the JavaScript layer, and passes along any +``viewDidAppear:`` and ``viewDidDisappear:`` messages into the Clutch view. + +**That's it!** You've got your screen hooked up and now it's up to you to use +it for good, not evil. \ No newline at end of file diff --git a/_sources/anatomy.txt b/_sources/anatomy.txt new file mode 100644 index 0000000..30d36e0 --- /dev/null +++ b/_sources/anatomy.txt @@ -0,0 +1,136 @@ +Anatomy of an App Using Clutch +============================== + +If you used our QuickStart guide, we may have breezed past some of the details +about all of the different parts that combine to form an app using Clutch. +This article should serve to highlight each part of the system, how it works, +and how it all fits together. + + +The Suggested Directory Structure +--------------------------------- + +The way the suggested directory structure looks is something like this:: + + MyApp/ + MyApp/ + MyApp.xcodeproj + Clutch.framework + MyApp/ + clutchmyapp/ + clutch-core/ + global/ + myscreen/ + index.html + screen.js + style.css + clutch.plist + +If you have a directory structure that looks different, that's fine, but this +is the one that the QuickStart guide will start you with. (The most common +way that yours could differ is if your clutchmyapp directory is in a different +spot, or is named something different.) + +First, there's the outer ``MyApp`` directory. This is honestly just a +container to hold the inner two directories, so that they can both be checked +into a single source code repository. Feel free to rename this container +directory to anything you want. + +Inside that container, there's an inner ``MyApp`` directory which stores your +iOS XCode project and the Clutch framework, as well as an inner inner ``MyApp`` +directory which contains your actual native Objective-C code. This is pretty +straightforward. + +Then, there's the ``clutchmyapp`` directory. This is where all the +JavaScript/HTML/CSS goes that will make up the screens in your app. There are +three things in there that are auto-generated. ``clutch-core`` contains our +libraries and static files, like backbone, zepto, and our base css. ``global`` +contains any JavaScript/HTML/CSS that you want to reuse across most (or all) of +your screens. Also there's a ``clutch.plist``, which holds any configuration +information you'd like to access but be able to dynamically update. + +Finally there's the ``myscreen`` directory, which is automatically created with +an HTML file, a JavaScript file, and a CSS file. You will create more and more +of these as your application gets larger. You can choose to fill those files +with code, or you can just leave them blank. For example in one screen, let's +say it's an FAQ page, you might just have static content, so you'd just +hand-code the HTML file. Other screens might be more dynamic and so the HTML +file would be left minimal, but the JavaScript file would fill up with your +display logic. + + +The Folder Reference +-------------------- + +This correlates to the ``clutchmyapp`` folder from the previous section. It +needs to be linked into your app as a folder reference for a few reasons. +Firstly, it's because we want to bundle a version of the HTML/CSS/JavaScript +needed to run your app. This means that the first time the user opens the app, +they have a version of the HTML/CSS/JavaScript ready to go. So there's no need +for internet connectivity to run an app that uses Clutch. + +The second reason that this folder needs to be linked into your app as a folder +reference is due to the ``clutch.plist`` file contained within. This file is +used to store configuration. You can use the :ref:`ClutchConf ` +module to access the contents of this file, and then later you can update this +configuration file remotely without having to push out a new application. This +might be used, for example, to determine the text to display on a native +button. + + +How an App Fits Together +------------------------ + +At first glance, Clutch might look similar to an framework like PhoneGap or +Appcelerator Titanium, where you write your whole app in JavaScript and/or +HTML. Sometimes these solutions use an abstraction layer that aims to make it +possible to target other platforms. In fact, Clutch works in a way that's +quite a bit different. Instead, you create your own +``UINavigationController``, your own ``UITabBarController``, and set up your +own project the way you like it, and the way you've done it in the past. + +The only thing that changes from normal iOS development is that instead of +using a XIB or interface builder to build your UI layer for some screen, you +can have Clutch help you to use web technologies instead. + +That means, you carve out an area that you want to be able to update +dynamically, and in that ``UIViewController``'s ``loadView`` method, you simply +instantiate a ``ClutchView`` and add it as a subview. + +Then you use our bridge layer to pass any important events from the Clutch view +back into the Objective-C layer, and handle those events natively. + + +The Bridge +---------- + +The bridge between your JavaScript code and you Objective-C code means that you +can handle any event in the layer that makes the most sense. For things that +do fancy animations, or pop open modal windows, or slide to a new screen, you +will want to do these things natively. For things that involve simple text +changes or content changes, you can handle that directly in JavaScript. + +It also works in the other direction. You can capture events that happen in +the native layer, like a ``UIToolbar`` button being pressed, and call into a +function on the JavaScript side of things. + + +Development Mode +---------------- + +So there's this whole step that you did where you entered in your phone's +identifier and associated it with your account, but what was that for? + +It allows Clutch to enable development mode. Nobody writes perfect code on +their first try. We know that there's a back-and-forth where you want to +experiment, try out a change, see how a CSS tweak looks, and you don't want to +send that out to your users every time. Instead, we provide a development mode +which, when it sees your specific registered phone, it doesn't serve the normal +app using the normal methods. + +Instead it connects to your local computer, to your working set of files, and +renders what you've written--rather than what you've deployed. On top of that, +it shows a nice toolbar that lets you know you're in development mode, and +gives you the option to quickly refresh the ``ClutchView``, so you can avoid +lengthy recompiles or re-navigating back to that same screen that you're +viewing. \ No newline at end of file diff --git a/_sources/commandclient.txt b/_sources/commandclient.txt new file mode 100644 index 0000000..be25e24 --- /dev/null +++ b/_sources/commandclient.txt @@ -0,0 +1,77 @@ +Clutch Command Client +===================== + +The Clutch Command Client is the easiest way to communicate with Clutch. You +will use it whenever you do development, whenever you want to push a new +version, and for various other tasks. Here's a list of the commands +provided and what they are capable of: + + +Installing +---------- + +Installing the command client is as simple as running one command:: + + sudo easy_install clutchclient + +Once you've done that, typing ``clutch`` into the command line should show you +the command's usage instructions and you'll know that it's been successfully +installed. + + +Commands +-------- + +startapp +~~~~~~~~ + +``clutch startapp DIRNAME`` + +Starts a new application directory under the name ``DIRNAME``. It will include +all of the clutchjs JavaScript and CSS files, as well as an empty configuration +plist. + + +startscreen +~~~~~~~~~~~ + +``clutch startscreen SCREENSLUG`` + +Starts a new screen directory under the name ``SCREENSLUG``. It will include a +basic ``index.html`` base as well as a convenient place for your custom +JavaScript and css files. + +.. note:: + + Your current working directory must be a Clutch application directory, or + else the Clutch Command Client will not be able to create a new screen + directory. + + +dev +~~~ + +``clutch dev -a APPNAME [-d DIRNAME]`` + +Starts local development on a Clutch application. If you use one of the iOS +devices `managed by your account`_ then all of the screens in your application +will be loaded on-demand from your computer rather than from the latest +published version. + +By default, it will serve the current working directory, but you can specify +another directory to serve using the ``-d`` command flag. + + +upload +~~~~~~ + +``clutch upload -a APPNAME [-d DIRNAME]`` + +Uploads a new version of your Clutch application to production. All of your +users will begin running the new code the next time they bring the application +into the foreground. + +By default, it will upload the current working directory, but you can specify +another directory to serve using the ``-d`` command flag. + +.. _`managed by your account`: http://clutch.io/devices/ \ No newline at end of file diff --git a/_sources/examples.txt b/_sources/examples.txt new file mode 100644 index 0000000..99893d3 --- /dev/null +++ b/_sources/examples.txt @@ -0,0 +1,29 @@ +Example Apps +============ + +Sometimes the best way to familiarize yourself with a new codebase is to see +examples of it being used. With that in mind, we've put forth our best effort +to make some really great example applications to show off the power of the +platform. Of course, if you build an open-source app and you'd like it +showcased here, we're happy to include it! + +Imgs - Fun Image App +-------------------- + +Imgs_ is a fun iOS app that showcases the best images on the internet, as +provided by Imgur_, and allows users to comment on them and like them. Imgs_ +also uses Parse_ as its storage layer to show how easy integration with modern +platforms can be when using Clutch. + +We designed, coded, and shipped this app in a week. + +|ImgsScreen1| |ImgsScreen2| + +.. _Imgs: https://github.com/boilerplate/imgs +.. _Imgur: http://imgur.com/ +.. _Parse: https://parse.com/ + +.. |ImgsScreen1| image:: _static/screen1.png + :width: 300px +.. |ImgsScreen2| image:: _static/screen2.png + :width: 300px \ No newline at end of file diff --git a/_sources/framework.txt b/_sources/framework.txt new file mode 100644 index 0000000..06db56e --- /dev/null +++ b/_sources/framework.txt @@ -0,0 +1,9 @@ +Clutch Framework +================ + +.. toctree:: + :maxdepth: 2 + + tutorials + reference + screencasts \ No newline at end of file diff --git a/_sources/gettingstarted.txt b/_sources/gettingstarted.txt new file mode 100644 index 0000000..6881c9d --- /dev/null +++ b/_sources/gettingstarted.txt @@ -0,0 +1,28 @@ +Getting Started +=============== + +The first thing to do is to `sign up for an account`_ on your local Clutch.io +instance. If you don't have a Clutch.io instance set up yet, follow the steps +on the `Clutch project README`. + +Now to get started with Clutch, the first thing you need to do is +`create an app`_. All that's required to create an app is to choose an app name +and a short name. The short name will be used in URLs and in certain cases you +might have to type it on the command line. + +.. image:: _static/creating-app-ss.jpg + +.. raw:: html + +

+ +Once you've created your app, the website will redirect you to the Quick Start +guide for your new app. The easiest thing to do here is to stay on the +"I am starting a new XCode project" option. Follow the instructions listed +there and you should be up-and-running with your first Clutch app! + +.. image:: _static/quick-start-ss.jpg + +.. _`create an app`: http://127.0.0.1:8000/apps/create/ +.. _`sign up for an account`: http://127.0.0.1:8000/register/ +.. _`Clutch project README`: https://github.com/clutchio/clutch/blob/master/README.rst \ No newline at end of file diff --git a/_sources/index.txt b/_sources/index.txt new file mode 100644 index 0000000..6c0e660 --- /dev/null +++ b/_sources/index.txt @@ -0,0 +1,22 @@ +.. Clutch documentation master file, created by + sphinx-quickstart on Tue Nov 29 11:21:00 2011. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to Clutch's documentation! +================================== + +.. toctree:: + :maxdepth: 2 + + ab-testing + framework + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/_sources/ioslibrary.txt b/_sources/ioslibrary.txt new file mode 100644 index 0000000..8693e66 --- /dev/null +++ b/_sources/ioslibrary.txt @@ -0,0 +1,177 @@ +iOS Library Reference +===================== + +The Clutch iOS library syncs up your latest code, helps you analyze usage about +your app, and provides a bi-directional bridge between your JavaScript code and +your Objective-C code. + + +ClutchSync +---------- + +.. code-block:: obj-c + + - (void)sync + +Intended to be called when the app finishes launching. Syncs to the latest +version of the application code. + +.. code-block:: obj-c + + - (void)foreground + +Intended to be called when the app is brought into the foreground. Syncs +to the latest version of the application code. + + +.. code-block:: obj-c + + - (void)background + +Intended to be called when the app is sent to the background. Performs +cleanup and sends statistics information. + +.. code-block:: obj-c + + + (ClutchSync *)sharedClientForKey:(NSString *)appKey + tunnelURL:(NSString *)tunnelURL + rpcURL:(NSString *)rpcURL; + +Returns a ``ClutchSync`` client instance for the given application key, tunnel +URL, and RPC URL. + + +ClutchView +---------- + +.. code-block:: obj-c + + - (id)initWithFrame:(CGRect)frame andSlug:(NSString *)slug + +Initializes a Clutch view instance with the given frame and screen slug. + +.. code-block:: obj-c + + - (id)callMethod:(NSString *)method withParams:(NSDictionary *)params + +Calls a JavaScript method (that has been registered with Clutch) and returns +its response. The ``params`` dictionary is the parameters you woud like to +pass as an argument to the JavaScript function. + +.. code-block:: obj-c + + - (id)callMethod:(NSString *)method + +The same as the previous call except no ``params``. + +.. code-block:: obj-c + + - (void)viewDidAppear:(BOOL)animated + +Should be called when its containing view controller's viewDidAppear is called. + +.. code-block:: obj-c + + - (void)viewDidDisappear:(BOOL)animated + +Should be called when its containing view controller's viewDidDisappear is +called. + +.. code-block:: obj-c + + + (void)logDeviceIdentifier + +Logs the current device's identifier, for use on the `add device page`_. + +.. code-block:: obj-c + + + (void)prepareForAnimation:(UIViewController *)viewController success:(void(^)(void))block_ + + + (void)prepareForDisplay:(UIViewController *)viewController success:(void(^)(void))block_ + +Prepares the given view controller subclass for animation or display (such as +adding it to a navigation controller) and then calls the given ``success`` +block. + +.. code-block:: obj-c + + + (void)prepareForDisplay:(UIViewController *)viewController; + +Prepares the given view controller subclass for display, and does not call any +callback. + +Properties +~~~~~~~~~~ + +.. code-block:: obj-c + + id delegate + +You may set this property to point to any instance of ClutchViewDelegate_ and +it will allow you to communicate between JavaScript and Objective-C. + +.. code-block:: obj-c + + id scrollDelegate + +You may set this property to any instance of ``UIScrollViewDelegate``, which +will send updates for all of the scrolling that happens on the web view. + +.. code-block:: obj-c + + UIWebView *webView + +The underlying webview that is the main workhorse of each ClutchView. + +.. code-block:: obj-c + + UIScrollView *scrollView + +The webview's scrollview. Useful for being updated as the user scrolls the +webview's contents, as in a pull-to-refresh implementation. + + +ClutchViewDelegate +------------------ + +.. code-block:: obj-c + + - (void)clutchView:(ClutchView *)clutchView + methodCalled:(NSString *)method + withParams:(NSDictionary *)params + +Called when JavaScript calls the ``Clutch.Core.callMethod(method, params)`` +method, which is useful for communication between your JavaScript code and +your Objective-C code. + +.. code-block:: obj-c + + - (void)clutchView:(ClutchView *)clutchView + methodCalled:(NSString *)method + withParams:(NSDictionary *)params + callback:(void(^)(id))callback + +Similar to the above method, except that this time it provides a callback that +you can call. Whatever object you pass to this callback will be sent to your +JavaScript callback. + + +.. _ClutchConf: + +ClutchConf +---------- + +.. code-block:: obj-c + + + (NSDictionary *)conf + +Gets the latest configuration (provided by clutch.plist). + +.. code-block:: obj-c + + + (NSInteger)version + +Gets the latest version of the configuration. + + +.. _`add device page`: http://127.0.0.1:8000/devices/create/ \ No newline at end of file diff --git a/_sources/jslibrary.txt b/_sources/jslibrary.txt new file mode 100644 index 0000000..5a62bd1 --- /dev/null +++ b/_sources/jslibrary.txt @@ -0,0 +1,358 @@ +JavaScript Library Reference +============================ + +Applications using Clutch are made using a combination of native code and +HTML/CSS/JavaScript. The Clutch JavaScript library is designed to create +content areas for your application using web technology that both looks and +feels native. + +To achieve this kind of performance and flexibility, we've built the core of +the library on top of the best mobile JavaScript code we could find: +Zepto_, Backbone_, and Underscore_. + + +Core +---- + +The first thing that Clutch does when it loads is set up some bookkeeping and +set up a communication channel between your native code and your JavaScript +code. Once that's all finished, it calls the function you attach using +``Clutch.Core.init``. + +.. js:function:: Clutch.Core.init(func) + + :param func: The function to run once Clutch is initialized. + +Keep in mind you should not start your rendering until after this function has +been called. Here's an example of how that could look in your code: + +.. code-block:: javascript + + Clutch.Core.init(function() { + alert('Hello from Clutch!'); + }); + +Once that is set up, you can go ahead and use any of Clutch's resources--the +communication channel, the UI helpers, and more. + +But the real core of Clutch is really just the communication channel between +the JavaScript that you write and the iOS code that you write. + +.. js:function:: Clutch.Core.callMethod(methodName[, params, callback]) + + :param string methodName: + The name of the Objective-C method you want to call. + :param params: An optional mapping of parameters to pass to the method. + :param callback: + An optional callback that will be called with the object passed into + the callback block in Objective-C. + :returns: Nothing + +As you can see, it's simple and straightforward. As an example, if a user +taps on a button and you want something to happen, you might write something +like this: + +.. code-block:: javascript + + Clutch.Core.callMethod('userTapped', {userId: 10}); + +In this example, we're calling the ``userTapped`` method in your iOS code, and +passing an NSDictionary whose key ``userId`` is set to ``10``. You can also +pass a callback function, which might look something like this: + +.. code-block:: javascript + + Clutch.Core.callMethod('getUsername', function(data) { + alert('Hello, ' + data.username); + }); + +To register a function on the JavaScript side that iOS can call, Clutch +provides a ``registerMethod`` function. + +.. js:function:: Clutch.Core.registerMethod(methodName, func) + + :param string methodName: + The name of the JavaScript method that you are exposing. + :param func: The actual JavaScript function to be exposed. + +.. note:: + + The function that you expose will always receive a single argument: an + object of parameters passed from iOS. + +Here's how it might look if you were to expose an ``alertUser`` function which +pops open an alert dialog with the given alert text: + +.. code-block:: javascript + + function alertUser(params) { + alert(params.alertText); + } + Clutch.Core.registerMethod('alertUser', alertUser); + + +Loading +------- + +One thing we need to do all the time in building iOS apps is to wait for some +data. Whenever we do that, we need to somehow indicate to the user that +there's something loading. Clutch provides an easy mechanism for showing and +hiding loading screens. + +.. js:function:: Clutch.Load.begin([loadingText], [top]) + + :param string loadingText: + Optional text to show to the user inside of the loading dialog. + + :param float top: + Optional offset from the top of the ClutchView, in pixels. + + Pops up the loading dialog with optional loading text. + +.. js:function:: Clutch.Load.end() + + Removes the loading dialog. + + +UI +-- + +Clutch helps you present a UI to your users that looks and feels like it's +native. Here's what's provided: + +.. js:function:: Clutch.UI.View([options]) + + :param options: A mapping of options to be provided to the view instance. + + This view is the core of all of the Clutch-provided UI constructs. It's + actually a subclass of `Backbone.View`_, with a few added extras. Here are + the added properties and functions: + + .. js:attribute:: template + + The default template provided for all Clutch.UI.View subclasses is + a simple `underscore template`_ that looks like ``<%= c.value %>``. + + .. js:function:: render() + + The default render for all Clutch.UI.View subclasses renders the + template but passes the view options as the ``c`` varible. It's + equivalent to this implementation: + + .. code-block:: javascript + + $(this.el).html(this.template({c: this.options})); + + +.. js:function:: Clutch.UI.Table([options]) + + :param options: A mapping of options to be provided to the view instance. + + This view creates a user interface that looks and acts like Cocoa's + ``UITableView``. + + You must extend this view to populate it with any data, and here are the + parameters you can provide in your extension: + + **Required** + + .. js:attribute:: numSections + + The number of table sections that should be displayed. + + .. js:function:: numCells(section) + + :param section: The 0-indexed integer of the current section. + + Determines the number of cells to be rendered for the given section. + + .. js:function:: cell(section, row) + + :param section: The 0-indexed integer of the current section. + :param row: The 0-indexed integer of the current row. + + Returns the ``Clutch.UI.TableCell`` subclass that should render the + requested table cell. + + **Optional** + + .. js:attribute:: style + + Determines the visual style of the table. Currently only supports + ``'normal'`` and ``'grouped'``. + + .. js:function:: tableHeader() + + Returns the ``Clutch.UI.TableHeader`` subclass that should render into + the table's header area. + + .. js:function:: tableFooter() + + Returns tje ``Clutch.UI.TableFooter`` subclass that should render into + the table's footer area. + + .. js:function:: sectionHeader(section) + + :param section: The 0-indexed integer of the current section. + + Returns a ``Clutch.UI.SectionHeader`` subclass that should render into + the given table section's header area. + + .. js:function:: sectionFooter(section) + + :param section: The 0-indexed integer of the current section. + + Returns a ``Clutch.UI.SectionHeader`` subclass that should render into + the given table section's footer area. + + +.. js:function:: Clutch.UI.TableHeader([options]) + + :param options: A mapping of options to be provided to the view instance. + + A ``Clutch.UI.View`` subclass for rendering table headers. + + +.. js:function:: Clutch.UI.TableFooter([options]) + + :param options: A mapping of options to be provided to the view instance. + + A ``Clutch.UI.View`` subclass for rendering table footers. + + +.. js:function:: Clutch.UI.SectionHeader([options]) + + :param options: A mapping of options to be provided to the view instance. + + A ``Clutch.UI.View`` subclass for rendering table section headers. + + +.. js:function:: Clutch.UI.SectionFooter([options]) + + :param options: A mapping of options to be provided to the view instance. + + A ``Clutch.UI.View`` subclass for rendering table section footers. + + +.. js:function:: Clutch.UI.TableCell([options]) + + :param options: A mapping of options to be provided to the view instance. + + In that ``options`` object, here are the expected and optional parameters: + + **Required** + + .. js:attribute:: value + + The value that should be displayed in the cell. + + **Optional** + + .. js:attribute:: accessory + + Determines which accessory to display for the cell. Should be one of + ``Clutch.UI.Accessories``. + + .. js:function:: tap(e) + + An optional function which will receive an event whenever this table + cell is tapped by the end user. + + +.. note:: + + If you subclass ``Clutch.UI.TableCell``, then you can set the ``multiline`` + attribute to ``true`` and it will be able to display more than one line + of content. + + .. code-block:: javascript + + var MultiLineCell = Clutch.UI.TableCell.extend({ + multiline: true + }); + + +.. js:attribute:: Clutch.UI.Accessories + + Accessories that can be used to decorate a table cell. + + .. js:attribute:: Checkmark + + Shows a check mark. + + .. js:attribute:: DisclosureButton + + Shows a button with a right-facing triangle indicating that there is + more content. + + .. js:attribute:: DisclosureIndicator + + Shows a right-facing triangle indicating that there is more content. + + +Example +------- + +Here's an example of how you could use this JavaScript library to create a +table which has some cells and a few headers. + +.. code-block:: javascript + + // Let's create a simple table by subclassing Clutch.UI.Table + var SimpleTable = Clutch.UI.Table.extend({ + // Our table should have two sections + numSections: 2, + // We want it to display in the "grouped" style which looks cooler + style: 'grouped', + + numCells: function(section) { + // Each section has 4 cells + return 4; + }, + + sectionHeader: function(section) { + // The section header just displays its own index + return new Clutch.UI.TableSectionHeader( + {value: 'Section ' + section + ' Header'} + ); + }, + + sectionFooter: function(section) { + // The first section doesn't have a footer + if(section === 0) { + return null; + } + // The second section does have a footer though + return new Clutch.UI.TableSectionFooter( + {value: 'Section ' + section + ' Footer'} + ); + }, + + cell: function(section, row) { + var value = 'Section ' + section + ' Cell ' + row; + return new Clutch.UI.TableCell({ + value: value, + accessory: Clutch.UI.Accessories.DisclosureButton, + tap: function(e) { + // Call the "tapped" method on iOS, and pass + // the text value of the cell as an argument. + Clutch.Core.callMethod('tapped', {value: value}); + } + }); + } + }); + + // Remember to wait for this event before rendering out our table. + Clutch.Core.init(function() { + // Instantiate our new table + var table = new SimpleTable(); + // Render the table + $('body').append(table.render().el); + }); + + +.. _Zepto: http://zeptojs.com/ +.. _Backbone: http://documentcloud.github.com/backbone/ +.. _Underscore: http://documentcloud.github.com/underscore/ +.. _`Backbone.View`: http://documentcloud.github.com/backbone/#View +.. _`underscore template`: http://documentcloud.github.com/underscore/#template \ No newline at end of file diff --git a/_sources/pulltorefresh.txt b/_sources/pulltorefresh.txt new file mode 100644 index 0000000..3da4118 --- /dev/null +++ b/_sources/pulltorefresh.txt @@ -0,0 +1,200 @@ +Integrating Pull-to-Refresh +=========================== + +One common UI element that people like to have in their apps is +pull-to-refresh. By using some open source software along with a little bit +of integration with Clutch, you can add this UI element to your Clutch screens +quite easily! + + +Download and Install EGOTableViewPullRefresh +-------------------------------------------- + +For the purposes of this tutorial, we're going to use the open source +`EGOTableViewPullRefresh`_ project, by the talented team at `enormego.com`_. +First you need to clone the repository:: + + git clone https://github.com/enormego/EGOTableViewPullRefresh.git + +Then open the directory:: + + open EGOTableViewPullRefresh + +Now drag the EGOTableViewPullRefresh folder into your XCode project. + + +Integrate EGOTableViewPullRefresh in Your Header File +----------------------------------------------------- + +In your ViewController's header file, import the pull-to-refresh library +headers so that we have something to work with: + +.. code-block:: obj-c + + #import "EGORefreshTableHeaderView.h" + +Then add make sure your Clutch ViewController is a scroll view delegate, and a +``EGORefreshTableHeaderDelegate``: + +.. code-block:: obj-c + + @interface ImageTableController : UIViewController + +Now add three properties: + +.. code-block:: obj-c + + @property (nonatomic, retain) EGORefreshTableHeaderView *refreshHeaderView; + @property (nonatomic, retain) NSDate *dateLastUpdated; + @property (nonatomic, assign) BOOL reloading; + + +Synthesize and Instantiate Refresh Variables +-------------------------------------------- + +First, synthesize the new variables that you have added: + +.. code-block:: obj-c + + @synthesize refreshHeaderView = _refreshHeaderView; + @synthesize dateLastUpdated = _dateLastUpdated; + @synthesize reloading = _reloading; + +Now instantiate the view and set the last updated date in your ``loadView``, +and set this class as both the delegate and the scroll delegate for Clutch: + +.. code-block:: obj-c + + - (void)loadView + { + + // ... + + self.dateLastUpdated = [NSDate date]; + + // Initialize the pull-to-refresh implementation + self.refreshHeaderView = [[EGORefreshTableHeaderView alloc] initWithFrame:CGRectMake(0, -324, 320, 368)]; + [self.refreshHeaderView release]; + [self.view addSubview:self.refreshHeaderView]; + self.refreshHeaderView.delegate = self; + [self.refreshHeaderView refreshLastUpdatedDate]; + + // Set up the Clutch view + self.clutchView = [[ClutchView alloc] initWithFrame:CGRectMake(0, 0, 320, 411) + andSlug:@"SOMESLUG"]; + [self.clutchView release]; + self.clutchView.delegate = self; + self.clutchView.scrollDelegate = self; + [self.view addSubview:self.clutchView]; + + // ... + + } + + +Add Delegate Methods +-------------------- + +We're almost there! Everything is set up, except there are a bunch of delegate +methods that are being called and we haven't yet implemented them yet. First +up is the ``EGORefreshTableHeaderView`` delegate methods: + +.. code-block:: obj-c + + - (void)egoRefreshTableHeaderDidTriggerRefresh:(EGORefreshTableHeaderView *)view + { + [self.clutchView.webView reload]; + self.reloading = TRUE; + } + + - (BOOL)egoRefreshTableHeaderDataSourceIsLoading:(EGORefreshTableHeaderView *)view + { + return self.reloading; + } + + - (NSDate*)egoRefreshTableHeaderDataSourceLastUpdated:(EGORefreshTableHeaderView *)view + { + return self.dateLastUpdated; + } + + - (void)doneLoadingTableViewData + { + self.reloading = FALSE; + self.dateLastUpdated = [NSDate date]; + [self.refreshHeaderView egoRefreshScrollViewDataSourceDidFinishedLoading:self.clutchView.scrollView]; + } + +.. note:: + + You may not want to just call ``[self.clutchView.webView reload]``. You + could also call a method in the JavaScript to refresh the data, or get the + data using Objective-C code. This is the easiest and simplest way to + achieve a reload though. + +Now we need to implement one of the ``ScrollViewDelegate`` delegate methods: + +.. code-block:: obj-c + + + - (void)scrollViewDidScroll:(UIScrollView *)scrollView + { + [self.refreshHeaderView egoRefreshScrollViewDidScroll:scrollView]; + + // This slides the pull-to-refresh view into the proper location + self.refreshHeaderView.frame = CGRectMake(self.refreshHeaderView.frame.origin.x, + -324.0f - scrollView.contentOffset.y, + self.refreshHeaderView.frame.size.width, + self.refreshHeaderView.frame.size.height); + } + + +Pulling it All Together +----------------------- + +We have one last step before this will all work properly. Right now you have +a Clutch view that, when dragged, will reveal a pull-to-refresh panel. When +you drag it down, it will reload the page. But it won't yet know when it's +done refreshing. That's a bummer, so let's fix it: + +.. code-block:: obj-c + + - (void)clutchView:(ClutchView *)clutchView + methodCalled:(NSString *)method + withParams:(NSDictionary *)params + callback:(void(^)(id))callback + { + // ... + + if([method isEqualToString:@"clutch.loading.end"]) { + [self doneLoadingTableViewData]; + } + + // ... + } + +As you can see, we're hooking into the ``clutch.loading.end`` method call +to determine when loading is complete. Now all that's left to do is call that +method in our JavaScript code: + +.. code-block:: javascript + + Clutch.Core.init(function() { + // Do your loading here, and then call... + Clutch.Loading.end(); + }); + +Boom! Now we're done integrating a pull-to-refresh into our Clutch screen. +Thanks to the power of great open source code and a bit of integration, it's +quite easy to get this great effect in your app. + + +Example +------- + +We've built an example application called Imgs which uses this technique, so +you can `check out the code`_ and see how we did it in a real app. + + +.. _`EGOTableViewPullRefresh`: https://github.com/enormego/EGOTableViewPullRefresh +.. _`enormego.com`: http://enormego.com/ +.. _`check out the code`: https://github.com/boilerplate/imgs \ No newline at end of file diff --git a/_sources/reference.txt b/_sources/reference.txt new file mode 100644 index 0000000..80033a5 --- /dev/null +++ b/_sources/reference.txt @@ -0,0 +1,10 @@ +Reference +========= + +.. toctree:: + :maxdepth: 2 + + jslibrary + ioslibrary + commandclient + termsanddefinitions \ No newline at end of file diff --git a/_sources/screencasts.txt b/_sources/screencasts.txt new file mode 100644 index 0000000..8b1e603 --- /dev/null +++ b/_sources/screencasts.txt @@ -0,0 +1,59 @@ +Screencasts +=========== + +Everyone learns in different ways. For some, the best way to learn a new tool +is to pore over documentation for hours. For others, jumping in on the deep +end and just starting to build something is the best. For others still, visual +and/or audio walkthroughs are best. Because of that, we want to make sure +there are ample examples of each! Here's our collection of screencasts: + +Getting Started - New XCode Project +----------------------------------- + +In this screencast we will start a new Clutch project from scratch, explaining +in detail each step that's required and why. + +.. raw:: html + + + + +Getting Started - Existing XCode Project +---------------------------------------- + +In this screencast we will start a new Clutch project for an existing iOS +application, explaining in detail each step that's required and why. + +.. raw:: html + + + +Tutorial - Adding a Screen +-------------------------- + +Once you have your project all set up, this tutorial will help show you how to +add a new Clutch screen to your project. + +.. raw:: html + + + +Tutorial - Demo App Walkthrough +------------------------------- + +Our Demo app, Imgs, has a lot of code and it's fairly large. In this tutorial, +we'll go over the basics of how it fits together and how it works. + +.. raw:: html + + + +Tutorial - Building a Twitter Search App +---------------------------------------- + +In this video we'll demonstrate the power of Clutch by building a very simple +Twitter search app. + +.. raw:: html + + \ No newline at end of file diff --git a/_sources/termsanddefinitions.txt b/_sources/termsanddefinitions.txt new file mode 100644 index 0000000..404def7 --- /dev/null +++ b/_sources/termsanddefinitions.txt @@ -0,0 +1,24 @@ +Terms and Definitions +--------------------- + +.. glossary:: + + Clutch App + A container holding all of the files that will make up the + HTML/JavaScript/CSS portion of your app. This container is registered + with Clutch and is given a name and a short name to easily talk about it. + + Screen + A content area that will be shown to the user using your app. Each + :term:`Clutch App` contains one or more screens. Examples of a screen could be + a user profile or a list of friends. This roughly corresponds one-to-one + with the number of UIViewControllers in your app that use Clutch. + + Short Name + The short version of an app name that is used in the URL for your + :term:`Clutch App` and is typed into the command line. For instance an + app named "Example App" might have the short name "exampleapp", which + you might type into the command line like ``clutch dev -a exampleapp``. + Some people might refer to this as a Slug_. + +.. _Slug: http://en.wikipedia.org/wiki/Slug_(web_publishing) \ No newline at end of file diff --git a/_sources/tutorials.txt b/_sources/tutorials.txt new file mode 100644 index 0000000..0083d4d --- /dev/null +++ b/_sources/tutorials.txt @@ -0,0 +1,11 @@ +Tutorials and Articles +====================== + +.. toctree:: + :maxdepth: 2 + + examples + gettingstarted + anatomy + addingnewscreen + pulltorefresh \ No newline at end of file diff --git a/_static/ajax-loader.gif b/_static/ajax-loader.gif new file mode 100644 index 0000000..61faf8c Binary files /dev/null and b/_static/ajax-loader.gif differ diff --git a/_static/basic.css b/_static/basic.css new file mode 100644 index 0000000..3fe08ac --- /dev/null +++ b/_static/basic.css @@ -0,0 +1,551 @@ +/*** CSS document by Eric Maguire for Boilerplate Inc. 11/2011 ***/ + +/* reset styles +--------------------------------------------- */ +html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {margin: 0;padding: 0;font-size: 100%;vertical-align: baseline;border: 0;outline: 0;background: transparent;} +ol, ul {list-style: none;} +blockquote, q {quotes: none;} +table {border-collapse: collapse;border-spacing: 0;} + +ol {list-style:decimal outside none;margin:0 0 0 20px;} +ul.bullets {list-style:disc outside none;margin:0 0 0 20px;} +ol li, ul.bullets li {margin: 0 0 10px;} + +ul.simple {padding-left: 30px;margin: 20px 0;list-style: none outside none;} +ul.simple li {list-style-type: disc;margin: 0 0 10px;} + +/** + * General Global Stuff. + */ +/* Textual elements */ + +body {font: 14px/20px "helvetica neue",helvetica,arial,sans-serif;background:url(images/bkg/bkg2.png) -30% 0% #222;color:#27231A;margin:0;padding:0;} +h1, h2, h3, h4, h5, h6 {color:#38342B;font-weight:normal;} + h1 {font-size:27px;} + h2 {font-size:26px;} + h3 {font-size:24px;text-shadow:0 1px 0 #fff;} + h4 {font-size:14px;} + h5 {font-size:12px;} + h6 {font-size:12px;} + +a {color:#b73d06;} +a:hover {color:#e06321;} +p{margin:0 0 20px 0;} + +#header {border-bottom:1px solid #000;background:url(images/bkg/header-bkg3.jpg) scroll -40% 0% #222;height:90px;} +.secondary #header {border-bottom:0;} +#header .content {background:url(images/bkg/highlight2.png) top center no-repeat;min-height:90px;position:relative;} +#header .content h1.logo a {position:absolute;top:18px;left:5px;z-index:3;background:url(images/btn/logo1.png) top center no-repeat;width:225px;height:46px;text-indent:-5000px;} +#header .content .main-nav {position:absolute;top:0;right:0;width:685px;height:90px;} +#header .content .main-nav.in-app {width:475px;} +#header .content .main-nav li {float: left;margin: 12px 0 0;padding:13px 37px 0 37px;height:54px;background:url(images/bkg/nav-line.png) center left no-repeat } +#header .content .main-nav li.last {background-image: url(images/bkg/nav-line.png), url(images/bkg/nav-line.png);background-position: center left, center right;background-repeat: no-repeat;} +#header .content .main-nav li.active { + background-image: url(images/bkg/nav-line.png); + background-position: center left, 88% 33%; + background-repeat: no-repeat; + } +#header .content .main-nav li a {color:#fff;text-decoration:none;} +#header .content .main-nav li.active a {color:#e06321;} +#header .content .main-nav li a strong {font-size:17px;text-shadow: 0px -2px 3px #000;} +#header .content .main-nav li a:hover strong {color:#f4742f;} +#header .content .main-nav li a em {font-size:12px;font-weight:normal;display:block;font-style:normal;} +#header .content .main-nav li.active a em {color:#fff;} +#header .content .main-nav li a:hover em {color:#fff;} +#header .content .main-nav li a.logout-link:hover em {color:red} + +.relbar {width:960px;margin:0 auto 10px;font-size:11px;} +.relbar .breadcrumbs {float:left;color:#666;} +.relbar .rellinks {float:right;} +.relbar .rellinks a {margin:0 10px 0 0;} +.section-wrap {background:url(images/bkg/bkg1.jpg) scroll -200% 0% #efe9dd;border-bottom:1px solid #c3b397;border-top:1px solid #fff;} +.secondary .section-wrap {border:none;padding:20px 0 45px;} +.secondary .section-wrap .content {width:960px;margin:0 auto;background:url(images/bkg/content-bkg1.png);border-radius:10px;box-shadow:0 2px 3px rgba(78, 68, 60, 0.3);min-height:300px;position:relative;} +.secondary .section-wrap .content .title {border-bottom:1px solid #ccc;box-shadow: 0 2px 0 -1px #fff;margin:0 0 15px 0;padding:11px 20px 3px 19px;position:relative;} + +.secondary .section-wrap .content .main-link {font-size:28px;text-decoration:none;} +.secondary .section-wrap .content .parents {position:absolute;top:17px; right:215px;} +.secondary .section-wrap .content .rellinks {position:absolute;top:14px; right:15px;} +.secondary .section-wrap .content .rellinks a {margin:0 0 0 8px;} + +.main-sec {width:669px;float:right;margin:0 0 20px 0;border-left:1px solid #CCCCCC;padding:0 30px 25px;} +.main-sec .section {margin:0;} +.main-sec .section h1 {border-bottom: 1px solid #ccc;font-weight:normal; +box-shadow: 0 2px 0 -1px #FFFFFF;margin:0 0 10px -30px;padding:0;padding:18px 20px 15px 30px;width:679px;} +.main-sec .section h2 {color:#38342B;border-bottom: 1px solid #ccc; +box-shadow: 0 2px 0 -1px #FFFFFF;margin:45px 0 10px -30px;padding:18px 20px 17px 30px;font-size:27px;width:679px;position:relative;} +.main-sec h3 {margin:20px 0 0;font-size:21px;} + +h1 .headerlink,h2 .headerlink,h3 .headerlink +{width:33px;height:30px;background:url(images/bkg/perma-tag.png);top:30px;right:-33px;text-indent:-5000px;position:absolute;} +h1:hover .headerlink,h2:hover .headerlink,h3:hover .headerlink,dt:hover .headerlink {} + +dt .headerlink { + background: url(images/bkg/perma-tag2.png) repeat scroll 0 0 transparent; + height: 30px; + position: absolute; + right: -59px; + text-indent: -5000px; + top: 1px; + width: 30px; +} + +.sphinxsidebarwrapper h3.contents {border-top:none;} + +.secondary-sec {width:230px;float:left;overflow:hidden;padding:0 0 30px 0;} +.secondary-sec h3 {border-bottom: 1px dotted #CCCCCC;border-top:1px solid #CCCCCC; +color: #999999;font-size: 14px;font-weight: bold;margin: 0 0 20px;padding: 9px 20px;text-transform: uppercase;} +.secondary-sec h4 {border-bottom: 1px dotted #CCCCCC;border-top:1px solid #CCCCCC; +color: #999999;font-size: 14px;font-weight: bold;margin: 0 0 20px;padding: 9px 20px;text-transform: uppercase;} +.secondary-sec h3 a {text-decoration:none;} +.index .secondary-sec h3 {border-top:none;} + +.secondary-sec .pad {padding:0 20px 20px;} +.secondary-sec ul li a {display:block;padding:0 0 10px 0;text-decoration:none;font-size:12px;width:200px;white-space:nowrap;overflow:hidden;text-overflow: ellipsis; +} +.secondary-sec .topless a {text-decoration:none;font-size:12px;} +.secondary-sec .topless {margin:0;font-size:12px;} +.secondary-sec #searchbox form.search {position:relative;margin:8px 0 3px 0;height:33px;} +.secondary-sec #searchbox input[type="text"] {width:133px;font-size:14px;position:absolute;top:0;left:0;} +.secondary-sec #searchbox input[type="submit"] {font-size:14px;margin:0;width:38px;position:absolute;top:3px;right:0;padding:5px;height:28px;} +.secondary-sec #searchbox .searchtip {color:#666;font-size:11px;} + +.secondary-sec .secondary-nav {margin:0 0 10px 0;} +.secondary-sec .secondary-nav li{background:url(images/bkg/nav-line2.png) left bottom no-repeat;} +.secondary-sec .secondary-nav li.active {background:none;} +.secondary-sec .secondary-nav li a {display:block;padding:10px 0 11px 20px;font-size:18px;text-decoration:none;} +.secondary-sec .secondary-nav li.active a {background:url(images/bkg/ribbon2.png) left bottom no-repeat;margin:0 0 0 -5px;color:#fff;padding:11px 0 15px 27px;text-shadow: 0px -1px 2px rgba(0, 0, 0, 0.8);} + +.secondary-sec .callout { + border-radius: 6px 6px 6px 6px; + color: rgba(0, 0, 0, 0.6); + font-size: 0.75em; + font-weight: normal; + margin: 20px 30px 25px 22px; +} + +#homepage .cta1 .content {background:url(images/bkg/iphone-ss1.jpg) left bottom no-repeat;padding:0 0 0 420px;width:540px;min-height:276px;} +#homepage .cta2 .content {background:url(images/bkg/gears-icon1.png) right center no-repeat;padding:0 420px 0 0;width:540px;min-height:315px;} +#homepage .cta1 .content p, #homepage .cta2 .content p {margin:0 0 25px 0;} + +.content {width:960px;margin:0 auto;} +#homepage .content h3 {padding:30px 0 7px 0;} +#homepage .content p {text-shadow:0 1px 0 #fff;} + +.appselector {width:255px;position:absolute;top:12px;right:12px;height:37px;} +.appselector h4 {font-size:18px;position:absolute;top:8px;left:0;} +.appselector select#app-jumper {width:200px;font-size:16px;position:absolute;top:0;right:0;height:34px;} + +.full .main-sec {width:920px;border:none;padding:20px;} +.full .main-sec h2 {width:794px;} + +div.note { + background-color: #ffc; + border: 1px solid #fbe58b; + border-radius:3px; + font-size:12px; +} + +div.admonition { + margin-bottom: 10px; + margin-top: 10px; + padding: 7px; +} + +div.note p {margin:0;} + +p.admonition-title:after { + content: ":"; + margin:0 5px 0 0; +} + +div.body p, div.body dd, div.body li { + line-height: 130%; + text-align: justify; +} +p.admonition-title { + display: inline; + font-weight: bold; + margin: 0 10px 0 0; + float:left; +} + +.edge {background:url(images/bkg/edge1.png) scroll -200% -300%;height:13px;margin:-12px 0 0 0;position:relative;z-index:1;} +.secondary .edge {margin:-9px 0 0 0;} +.ribbon {width:54px;height:104px;background:url(images/bkg/ribbon1.png) top left no-repeat;position:absolute;top:0px;left:0;z-index:2;} + +#footer {height:150px;background:url(images/bkg/edge2.png) scroll -200% 0% repeat-x;color:#555;} +#footer a {color:#777;text-decoration:none;text-shadow:1px 1px 0 rgba(0, 0, 0, 0.6) !important} +#footer a:hover {color:#666;} +#footer p {text-shadow:1px 1px 0 rgba(0, 0, 0, 0.6) !important} +#footer .left {width:475px;float:left;margin:50px 0 0 0;} +#footer .right {width:450px;float:right;margin:50px 0 0 0;} +#footer ul li {float:left;margin:0 10px 0 0;} +#footer ul li.last {margin:0;} +#footer .copyright {text-align:right;} +#footer .left .twitter-follow-button {margin: 10px 0 0;} + +.clear {clear:both;} +.last {margin-right:0 !important;} +.right {float:right;} +.left {float:left;} + +/* homepage specific */ + +.doc-home {} +.doc-home .main-sec {border-left:none;width:900px;} +.doc-home.secondary .section-wrap .content .title {position:relative;border-bottom: 1px solid #CCCCCC;box-shadow: 0 2px 0 -1px #FFFFFF;font-weight: normal;margin: 0 0 10px -30px; +padding: 23px 20px 22px 26px;width: 914px;} +.doc-home.secondary .section-wrap .content .title h1 {font-size:32px;} +.doc-home .main-sec .title .search-box {position:absolute;top:16px;right:10px;width:241px;} +.doc-home .main-sec .title .search-box input[type="text"] {font-size:16px;width:180px;} +.doc-home .main-sec .title .search-box input[type="submit"] {margin:0;padding:6px 5px 5px;font-size:14px !important;} + +.doc-home .row {padding:0;} +.doc-home .row .first, .doc-home .row .second {float:left;margin:15px 0 0 0;} +.doc-home .row .first {padding:0 30px 0 0;width:400px;} +.doc-home .row .second {padding:0 0 0 30px;width:439px;} +.doc-home .main-sec .row h3 {border-bottom: 1px solid #CCCCCC;box-shadow: 0 2px 0 -1px #FFFFFF;display: block;font-size: 24px; +margin: 15px 0 15px 0;padding: 0 20px 10px 0;text-align:center;} +.doc-home .main-sec .row h3 a {text-decoration:none;} + +.doc-home .row .screencasts, .doc-home .row .example {min-height:300px;} +.doc-home .row .downloads, .doc-home .row .tutorials {min-height:232px;} +.doc-home .row .reference {margin:15px 0 0 0;} +.doc-home .row .contact {min-height:300px;margin:11px 0 0 0;} + +a.ab-testing-btn {width:299px;height:171px;background:url(images/btn/clutch-ab-big-btn.png) bottom left no-repeat;text-indent:-5000px;display:block;margin:30px 0 26px 42px} +a.ab-testing-btn:hover {background-position:top left;} +a.framework-btn {width:299px;height:171px;background:url(images/btn/clutch-fw-big-btn.png) bottom left no-repeat;text-indent:-5000px;display:block;margin:30px 0 26px 42px} +a.framework-btn:hover {background-position:top left;} + +.doc-home .row ul {list-style:disc inside none;} +.doc-home .row ul li {margin:10px 0 15px 2px;} +.doc-home .row ul li a {font-size:16px;} + +.doc-home .main-sec .row .contact h2{border-bottom: 1px solid #CCCCCC;box-shadow: 0 2px 0 -1px #FFFFFF;display: block;font-size: 24px; +margin: 0 0 15px 0;padding: 18px 20px 10px 0;font-family:"helvetica neue",helvetica,arial,sans-serif;} + +.doc-home .downloads .btn {font-size: 21px !important;margin: 0 10px 15px 0;padding: 15px 0 15px 30px;text-align: center;width: 156px;} +.doc-home .downloads .command-line {padding:10px;border:1px solid #ccc;border-radius:7px;width:367px;} +.doc-home .downloads .command-line p {font-size:12px;font-style:italic;margin:0 0 10px 0;} +.doc-home .downloads .command-line p strong {font-size:14px;} +.doc-home .downloads .command-line pre {margin:0;} + +.doc-home .screencasts .screencast {width:192px;overflow:hidden;float:left;margin:0 15px 0 0;} + +.doc-home .example .screenshots img {float:left;margin:0 19px 0 0;} +.doc-home .links {margin:15px 0 0 0;} +.doc-home .links .btn {margin:0 0 0 10px;} + +.doc-home .downloads .btn.green { + background: url(images/btn/download-icon.png) 22px 10px no-repeat; + background: + url(images/btn/download-icon.png) 22px 10px no-repeat, + -webkit-linear-gradient(top , #57A957, #62C462); + background: + url(images/btn/download-icon.png) 22px 10px no-repeat, + -moz-linear-gradient(top , #57A957, #62C462);} + +.doc-home .downloads .btn.green:hover { + background: url(images/btn/download-icon.png) 22px 10px no-repeat; + background: + url(images/btn/download-icon.png) 22px 10px no-repeat, + -webkit-linear-gradient(top , #57A957, #6eda6e); + background: + url(images/btn/download-icon.png) 22px 10px no-repeat, + -moz-linear-gradient(top , #57A957, #6eda6e);} + +.doc-home .screencasts a.thumb {float:left;width:192px;margin:0 5px 0 0;} + + +/* page specific */ +#docs ul li a {text-decoration:none;} +#docs ul li.toctree-l1 {margin:0 0 20px 0;padding:0 0 20px 0;} +#docs ul li.toctree-l1 a {font-size:24px;border-bottom: 1px solid #CCCCCC;box-shadow: 0 2px 0 -1px #FFFFFF;display:block;padding:18px 20px 10px 29px;margin:0 0 8px -30px;width:631px;} + +#docs ul li.toctree-l2 a,#docs ul li.toctree-l3 a,#docs ul li.toctree-l4 a {box-shadow:none;font-weight:normal;font-size:14px;border:none;padding:0;margin:0px 0 7px 1px;width:100%;} + +body.search-results ul.search li {border-bottom:1px solid #ccc;box-shadow:0 2px 0 -1px #FFFFFF;margin:0 0 15px 0;padding:0 0 15px 0;} +body.search-results ul.search li a {font-weight:bold;} +body.search-results ul.search li .context{font-size:14px;} +.highlighted {background:#EEDC94;font-weight:bold;} + +body.search-results .main-sec h2 {border-bottom: 1px solid #CCCCCC; +box-shadow: 0 2px 0 -1px #FFFFFF;color: #57A957;margin: 0 0 10px;padding:10px 0;;width: 100%;} + +body.search-results #search-documentation {border-bottom: 1px solid #B1E3F2; +box-shadow: 0 2px 0 -1px rgba(255, 255, 255, 0.55);color: #38342B;margin: 0 0 10px;padding: 0 0 10px 0;width: 100%;} + +#docs .alert-message.blue {padding:11px 20px 15px 20px;} +#docs .alert-message form {margin:15px 0 0 0;} +#docs .alert-message form input[type="submit"] {margin:0 0 0 5px;} + +#docs.index .section-wrap .content .main-sec .title {height:42px;border-bottom:1px solid #ccc;box-shadow: 0 2px 0 -1px #fff;margin:0 0 15px 0;padding:11px 20px 3px 19px;position:relative;} +#docs.index .section-wrap .content .main-sec .title h1 {position:absolute;top:21px;left:0;color: #57A957;} + +#docs.index .section-wrap .content .main-sec .title .genindex-jumpbox {position:absolute;top:22px;right:0;} +#docs.index .main-sec h2 {color:#38342B;border-bottom:none;box-shadow:none;font-size:21px;margin:0;text-shadow:none;} + +#docs.index table {border:none;} +#docs.index table td {border-top:none;padding:0 0 20px 0;box-shadow:0 2px 0 -1px #FFFFFF;} +#docs.index table th + th, #docs.index table td + td, #docs.index table th + td {border-left:none;} + +#docs table.docutils {margin:7px 0;} +#docs table.docutils ul.simple {margin:0;} +#docs table.docutils ul.simple li {margin:0;} + +dl.function {font-size:15px;margin:0 0 35px 0;} +dl.function dd {margin:0 0 0 20px;} +tt.docutils { + background-color: #fff; + font-size: 0.95em; + padding: 0 1px; + font-family:Monaco,Andale Mono,Courier New,monospace; + color:#336633; +} + +tt.descname {font-weight:bold;} +dt {position:relative;} + +/* login pages */ +.form-box {border-right:1px solid #fff;width:440px;float:left;margin:15px 0 15px 0;min-height:392px;} +.help-box {border-left:1px solid #ccc;width:420px;float:left;padding:0 0 0 40px;min-height:392px;margin:15px 0 15px 0;} +.help-box h3 {margin:0;} + +/* General Thumbnail Styles */ +a.thumb {position:relative;display:inline-block;text-decoration:none;font-size:10px;text-align:center;} +a.thumb .play-btn {width:55px;height:56px;position:absolute;top:34px;left:61px;background:url(images/btn/play-btn.png) bottom left;text-indent:-5000px;} +a.thumb:hover .play-btn {background-position:top left;} + +img.frame {border: 4px solid #FFFFFF; + border-radius: 4px; + box-shadow: 0 2px 3px rgba(78, 68, 60, 0.3);} + +/* General Global Button Styles */ +.btn {background-color: #b43a04; + background-image: -moz-linear-gradient(top , #b43a04, #de6020); + background-image: -webkit-linear-gradient(top , #b43a04, #de6020); + background-repeat: repeat-x; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + color:#fff; + text-decoration:none; + border-radius:60px; + border-width:1px; + border-style:solid; + box-shadow:0 1px 0 rgba(255, 255, 255, 0.2) inset, 0 1px 2px rgba(0, 0, 0, 0.05); + font-size:18px !important; + padding:7px 14px 8px; + font-weight:bold; + display:inline-block; + } + +.btn:hover {color:#fff; + background-image: -moz-linear-gradient(top , #b43a04, #fa7934); + background-image: -webkit-linear-gradient(top , #b43a04, #fa7934); + } + +.btn.green {background-color: #57A957; + background-image: -moz-linear-gradient(top , #57A957, #62C462); + background-image: -webkit-linear-gradient(top , #57A957, #62C462); + } + +.btn.green:hover {color:#fff; + background-image: -moz-linear-gradient(top , #57A957, #6eda6e); + background-image: -webkit-linear-gradient(top , #57A957, #6eda6e); + } + +.btn.gray {background-color: #57A957; + background-image: -moz-linear-gradient(top , #ddd, #eee); + background-image: -webkit-linear-gradient(top , #ddd, #eee); + border-color:#ccc #ccc #c0c5c2; + text-shadow: 0 1px 1px #fff; + color:#b73d06; + box-shadow:0 1px 0 rgba(255, 255, 255, 0.6) inset, 0 1px 2px rgba(0, 0, 0, 0.05); + font-size:16px !important; + padding:7px 14px 8px; + } + +.btn.gray:hover {color:#e06321; + background-image: -moz-linear-gradient(top , #ddd, #fff); + background-image: -webkit-linear-gradient(top , #ddd, #fff); + } + +.btn.big { + padding:11px 24px; + } +.btn.small{ + font-size: 11px !important; + padding: 4px 10px; +} + +/* alert and message boxes */ +.alert-message { + background-color: #EEDC94; + background-image: -moz-linear-gradient(top , #FCEEC1, #EEDC94); + background-image: -webkit-linear-gradient(top , #FCEEC1, #EEDC94); + background-repeat: repeat-x; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + border-radius: 5px; + border-style: solid; + border-width: 1px; + box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25) inset; + color: #404040; + margin-bottom: 18px; + padding: 15px 20px; + position: relative; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + font-size:14px; +} + +.alert-message.blue {background-color: #DDF4FB; +background-image: -moz-linear-gradient(top , #DDF4FB, #C6EDF9); +background-image: -webkit-linear-gradient(top , #DDF4FB, #C6EDF9); +border-color: #b1e3f2;} + +.alert-message p {margin:0;} +.alert-message .alert-actions {margin:10px 0 0 0;} +.close {color: #000000;float: right;font-size: 20px;font-weight: bold;line-height: 13.5px;opacity: 0.25;text-shadow: 0 1px 0 #FFFFFF;text-decoration: none;} +.close:hover {color: #000000;opacity: 0.4;text-decoration: none;} + + +/* forms */ +code,pre{padding:0 3px 2px;font-family:Monaco, Andale Mono, Courier New, monospace;font-size:12px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} +code{background-color:#fee9cc;color:rgba(0, 0, 0, 0.75);padding:1px 3px;} +pre{background-color:#fff;box-shadow:0 2px 3px rgba(78, 68, 60, 0.3);display:block;padding:8.5px;margin:0 0 18px;line-height:18px;font-size:12px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;white-space:pre;white-space:pre-wrap;word-wrap:break-word;} + + + +form{margin-bottom:18px;} +form ul li {margin:0 0 15px 0;clear:both;} +fieldset{margin-bottom:18px;padding-top:18px;}fieldset legend{display:block;padding-left:150px;font-size:19.5px;line-height:1;color:#404040;*padding:0 0 5px 145px;*line-height:1.5;} +form .clearfix{margin-bottom:18px;zoom:1;}form .clearfix:before,form .clearfix:after{display:table;content:"";zoom:1;*display:inline;} +form .clearfix:after{clear:both;} +label,input,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:normal;} +label{padding-top:10px;font-size:14px;line-height:18px;float:left;width:120px;text-align:right;color:#404040;margin:0 10px 0 0;} +form .input{margin-left:150px;} +input[type=checkbox],input[type=radio]{cursor:pointer;} +input,textarea,select,.uneditable-input{display:inline-block;width:246px;padding:6px;font-size:21px;color:#808080;border:1px solid #ccc;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;} +input[type=checkbox],input[type=radio]{width:auto;height:auto;padding:0;margin:3px 0;*margin-top:0;line-height:normal;border:none;} +input[type=file]{background-color:#ffffff;padding:initial;border:initial;line-height:initial;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} +input[type=button],input[type=reset],input[type=submit]{width:auto;height:auto;margin:0 0 0 130px;cursor:pointer;} +select,input[type=file]{line-height:27px;*margin-top:4px;} +select[multiple]{height:inherit;} +textarea{height:auto;} +.uneditable-input{background-color:#ffffff;display:block;border-color:#eee;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);cursor:not-allowed;} +:-moz-placeholder{color:#bfbfbf;} +::-webkit-input-placeholder{color:#bfbfbf;} +input,textarea{-webkit-transition:border linear 0.2s,box-shadow linear 0.2s;-moz-transition:border linear 0.2s,box-shadow linear 0.2s;-ms-transition:border linear 0.2s,box-shadow linear 0.2s;-o-transition:border linear 0.2s,box-shadow linear 0.2s;transition:border linear 0.2s,box-shadow linear 0.2s;-webkit-box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1);-moz-box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1);box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1);} +input:focus,textarea:focus{outline:0;border-color:rgba(82, 168, 236, 0.8);-webkit-box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1),0 0 8px rgba(82, 168, 236, 0.6);-moz-box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1),0 0 8px rgba(82, 168, 236, 0.6);box-shadow:inset 0 1px 3px rgba(0, 0, 0, 0.1),0 0 8px rgba(82, 168, 236, 0.6);} +input[type=file]:focus,input[type=checkbox]:focus,select:focus{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;outline:1px dotted #666;} +.errorlist li {color:red;font-style:italic;font-weight:bold;margin:0 0 -8px 0;width:120px;text-align:right;font-size:10px;} + + + + +/* modal pop-up styles */ +.fade { + -webkit-transition: opacity 0.15s linear; + -moz-transition: opacity 0.15s linear; + -ms-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; + opacity: 0; +} +.fade.in { + opacity: 1; +} +.modal-open .dropdown-menu { + z-index: 2050; +} +.modal-open .dropdown.open { + *z-index: 2050; +} +.modal-open .popover { + z-index: 2060; +} +.modal-open .tooltip { + z-index: 2070; +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #f3f1eb; +} +.modal-backdrop.fade { + opacity: 0; +} +.modal-backdrop, .modal-backdrop.fade.in { + opacity: 0.7; + filter: alpha(opacity=70); +} +.modal { + position: fixed; + top: 50%; + left: 50%; + z-index: 1050; + max-height: 500px; + overflow: auto; + width: 560px; + margin: -250px 0 0 -280px; + background-color: #ffffff; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} +.modal.fade { + -webkit-transition: opacity .3s linear, top .3s ease-out; + -moz-transition: opacity .3s linear, top .3s ease-out; + -ms-transition: opacity .3s linear, top .3s ease-out; + -o-transition: opacity .3s linear, top .3s ease-out; + transition: opacity .3s linear, top .3s ease-out; + top: -25%; +} +.modal.fade.in { + top: 50%; +} +.modal-header { + padding: 9px 15px; + border-bottom: 1px solid #eee; +} +.modal-header .close { + margin-top: 2px; +} +.modal-body { + padding: 15px; +} +.modal-footer { + padding: 14px 15px 15px; + margin-bottom: 0; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; + *zoom: 1; +} +.modal-footer:before, .modal-footer:after { + display: table; + content: ""; +} +.modal-footer:after { + clear: both; +} +.modal-footer .btn { + float: right; + margin-left: 5px; + margin-bottom: 0; +} + +.modal iframe {float:left;} \ No newline at end of file diff --git a/_static/bootstrap-modal.js b/_static/bootstrap-modal.js new file mode 100644 index 0000000..bac0dee --- /dev/null +++ b/_static/bootstrap-modal.js @@ -0,0 +1,209 @@ +/* ========================================================= + * bootstrap-modal.js v2.0.0 + * http://twitter.github.com/bootstrap/javascript.html#modals + * ========================================================= + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================= */ + + +!function( $ ){ + + "use strict" + + /* MODAL CLASS DEFINITION + * ====================== */ + + var Modal = function ( content, options ) { + this.options = $.extend({}, $.fn.modal.defaults, options) + this.$element = $(content) + .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this)) + } + + Modal.prototype = { + + constructor: Modal + + , toggle: function () { + return this[!this.isShown ? 'show' : 'hide']() + } + + , show: function () { + var that = this + + if (this.isShown) return + + $('body').addClass('modal-open') + + this.isShown = true + this.$element.trigger('show') + + escape.call(this) + backdrop.call(this, function () { + var transition = $.support.transition && that.$element.hasClass('fade') + + !that.$element.parent().length && that.$element.appendTo(document.body) //don't move modals dom position + + that.$element + .show() + + if (transition) { + that.$element[0].offsetWidth // force reflow + } + + that.$element.addClass('in') + + transition ? + that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) : + that.$element.trigger('shown') + + }) + } + + , hide: function ( e ) { + e && e.preventDefault() + + if (!this.isShown) return + + var that = this + this.isShown = false + + $('body').removeClass('modal-open') + + escape.call(this) + + this.$element + .trigger('hide') + .removeClass('in') + + $.support.transition && this.$element.hasClass('fade') ? + hideWithTransition.call(this) : + hideModal.call(this) + } + + } + + + /* MODAL PRIVATE METHODS + * ===================== */ + + function hideWithTransition() { + var that = this + , timeout = setTimeout(function () { + that.$element.off($.support.transition.end) + hideModal.call(that) + }, 500) + + this.$element.one($.support.transition.end, function () { + clearTimeout(timeout) + hideModal.call(that) + }) + } + + function hideModal( that ) { + this.$element + .hide() + .trigger('hidden') + + backdrop.call(this) + } + + function backdrop( callback ) { + var that = this + , animate = this.$element.hasClass('fade') ? 'fade' : '' + + if (this.isShown && this.options.backdrop) { + var doAnimate = $.support.transition && animate + + this.$backdrop = $(' + +
+
+ + + + + +
+
+
+ + + + + + + + + + + + + + \ No newline at end of file diff --git a/gettingstarted.html b/gettingstarted.html new file mode 100644 index 0000000..4de19f0 --- /dev/null +++ b/gettingstarted.html @@ -0,0 +1,182 @@ + + + + + + + + + Clutch.io - Getting Started - Documentation + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + +
+
+ +
+
+ +
+

Getting Started

+

The first thing to do is to sign up for an account on your local Clutch.io +instance. If you don’t have a Clutch.io instance set up yet, follow the steps +on the Clutch project README.

+

Now to get started with Clutch, the first thing you need to do is +create an app. All that’s required to create an app is to choose an app name +and a short name. The short name will be used in URLs and in certain cases you +might have to type it on the command line.

+_images/creating-app-ss.jpg +

Once you’ve created your app, the website will redirect you to the Quick Start +guide for your new app. The easiest thing to do here is to stay on the +“I am starting a new XCode project” option. Follow the instructions listed +there and you should be up-and-running with your first Clutch app!

+_images/quick-start-ss.jpg +
+ + +
+ +
+
+

Previous topic

+

+ Example Apps +

+

Next topic

+

+ Anatomy of an App Using Clutch +

+

This Page

+ + + +
+
+
+
+ +
+
+ + + + + + + + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..2e95b85 --- /dev/null +++ b/index.html @@ -0,0 +1,213 @@ + + + + + + + + Clutch.io - Overview - Documentation + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + +
+
+ +
+
+ +
+

Clutch Documentation

+ +
+ + + + + +
+
+

Clutch A/B Testing Docs

+ + Clutch A/B Testing + +

A/B testing is pure-native way of running experiments on your native iOS and Android apps. Inside you can learn more about how to set up and run these tests.

+ +
+
+

Clutch Framework Docs

+ + Clutch Framework + +

The Clutch framework helps you write hybrid iOS apps built using native and HTML code. The framework provides Objective-C layer, the JavaScript layer, and a layer that binds it all together. Inside you can learn about how to use this framework in your own apps.

+ +
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+
+ + + + + + + + + + + \ No newline at end of file diff --git a/ioslibrary.html b/ioslibrary.html new file mode 100644 index 0000000..6a27641 --- /dev/null +++ b/ioslibrary.html @@ -0,0 +1,309 @@ + + + + + + + + + Clutch.io - iOS Library Reference - Documentation + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + +
+
+ +
+
+ +
+

iOS Library Reference

+

The Clutch iOS library syncs up your latest code, helps you analyze usage about +your app, and provides a bi-directional bridge between your JavaScript code and +your Objective-C code.

+
+

ClutchSync

+
- (void)sync
+
+
+

Intended to be called when the app finishes launching. Syncs to the latest +version of the application code.

+
- (void)foreground
+
+
+

Intended to be called when the app is brought into the foreground. Syncs +to the latest version of the application code.

+
- (void)background
+
+
+

Intended to be called when the app is sent to the background. Performs +cleanup and sends statistics information.

+
+ (ClutchSync *)sharedClientForKey:(NSString *)appKey
+                     tunnelURL:(NSString *)tunnelURL
+                        rpcURL:(NSString *)rpcURL;
+
+
+

Returns a ClutchSync client instance for the given application key, tunnel +URL, and RPC URL.

+
+
+

ClutchView

+
- (id)initWithFrame:(CGRect)frame andSlug:(NSString *)slug
+
+
+

Initializes a Clutch view instance with the given frame and screen slug.

+
- (id)callMethod:(NSString *)method withParams:(NSDictionary *)params
+
+
+

Calls a JavaScript method (that has been registered with Clutch) and returns +its response. The params dictionary is the parameters you woud like to +pass as an argument to the JavaScript function.

+
- (id)callMethod:(NSString *)method
+
+
+

The same as the previous call except no params.

+
- (void)viewDidAppear:(BOOL)animated
+
+
+

Should be called when its containing view controller’s viewDidAppear is called.

+
- (void)viewDidDisappear:(BOOL)animated
+
+
+

Should be called when its containing view controller’s viewDidDisappear is +called.

+
+ (void)logDeviceIdentifier
+
+
+

Logs the current device’s identifier, for use on the add device page.

+
+ (void)prepareForAnimation:(UIViewController *)viewController success:(void(^)(void))block_
+
++ (void)prepareForDisplay:(UIViewController *)viewController success:(void(^)(void))block_
+
+
+

Prepares the given view controller subclass for animation or display (such as +adding it to a navigation controller) and then calls the given success +block.

+
+ (void)prepareForDisplay:(UIViewController *)viewController;
+
+
+

Prepares the given view controller subclass for display, and does not call any +callback.

+
+

Properties

+
id delegate
+
+
+

You may set this property to point to any instance of ClutchViewDelegate and +it will allow you to communicate between JavaScript and Objective-C.

+
id scrollDelegate
+
+
+

You may set this property to any instance of UIScrollViewDelegate, which +will send updates for all of the scrolling that happens on the web view.

+
UIWebView *webView
+
+
+

The underlying webview that is the main workhorse of each ClutchView.

+
UIScrollView *scrollView
+
+
+

The webview’s scrollview. Useful for being updated as the user scrolls the +webview’s contents, as in a pull-to-refresh implementation.

+
+
+
+

ClutchViewDelegate

+
- (void)clutchView:(ClutchView *)clutchView
+      methodCalled:(NSString *)method
+        withParams:(NSDictionary *)params
+
+
+

Called when JavaScript calls the Clutch.Core.callMethod(method, params) +method, which is useful for communication between your JavaScript code and +your Objective-C code.

+
- (void)clutchView:(ClutchView *)clutchView
+      methodCalled:(NSString *)method
+        withParams:(NSDictionary *)params
+          callback:(void(^)(id))callback
+
+
+

Similar to the above method, except that this time it provides a callback that +you can call. Whatever object you pass to this callback will be sent to your +JavaScript callback.

+
+
+

ClutchConf

+
+ (NSDictionary *)conf
+
+
+

Gets the latest configuration (provided by clutch.plist).

+
+ (NSInteger)version
+
+
+

Gets the latest version of the configuration.

+
+
+ + +
+ +
+
+

Contents

+ +

Previous topic

+

+ JavaScript Library Reference +

+

Next topic

+

+ Clutch Command Client +

+

This Page

+ + + +
+
+
+
+ +
+
+ + + + + + + + + + \ No newline at end of file diff --git a/jslibrary.html b/jslibrary.html new file mode 100644 index 0000000..97ec3cc --- /dev/null +++ b/jslibrary.html @@ -0,0 +1,686 @@ + + + + + + + + + Clutch.io - JavaScript Library Reference - Documentation + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + +
+
+ +
+
+ +
+

JavaScript Library Reference

+

Applications using Clutch are made using a combination of native code and +HTML/CSS/JavaScript. The Clutch JavaScript library is designed to create +content areas for your application using web technology that both looks and +feels native.

+

To achieve this kind of performance and flexibility, we’ve built the core of +the library on top of the best mobile JavaScript code we could find: +Zepto, Backbone, and Underscore.

+
+

Core

+

The first thing that Clutch does when it loads is set up some bookkeeping and +set up a communication channel between your native code and your JavaScript +code. Once that’s all finished, it calls the function you attach using +Clutch.Core.init.

+
+
+Clutch.Core.init(func)
+
+++ + + + +
Arguments:
    +
  • func – The function to run once Clutch is initialized.
  • +
+
+
+ +

Keep in mind you should not start your rendering until after this function has +been called. Here’s an example of how that could look in your code:

+
Clutch.Core.init(function() {
+    alert('Hello from Clutch!');
+});
+
+
+

Once that is set up, you can go ahead and use any of Clutch’s resources–the +communication channel, the UI helpers, and more.

+

But the real core of Clutch is really just the communication channel between +the JavaScript that you write and the iOS code that you write.

+
+
+Clutch.Core.callMethod(methodName[, params, callback])
+
+++ + + + + + +
Arguments:
    +
  • methodName (string) – The name of the Objective-C method you want to call.
  • +
  • params – An optional mapping of parameters to pass to the method.
  • +
  • callback – An optional callback that will be called with the object passed into +the callback block in Objective-C.
  • +
+
Returns:

Nothing

+
+
+ +

As you can see, it’s simple and straightforward. As an example, if a user +taps on a button and you want something to happen, you might write something +like this:

+
Clutch.Core.callMethod('userTapped', {userId: 10});
+
+
+

In this example, we’re calling the userTapped method in your iOS code, and +passing an NSDictionary whose key userId is set to 10. You can also +pass a callback function, which might look something like this:

+
Clutch.Core.callMethod('getUsername', function(data) {
+    alert('Hello, ' + data.username);
+});
+
+
+

To register a function on the JavaScript side that iOS can call, Clutch +provides a registerMethod function.

+
+
+Clutch.Core.registerMethod(methodName, func)
+
+++ + + + +
Arguments:
    +
  • methodName (string) – The name of the JavaScript method that you are exposing.
  • +
  • func – The actual JavaScript function to be exposed.
  • +
+
+
+ +
+

Note

+

The function that you expose will always receive a single argument: an +object of parameters passed from iOS.

+
+

Here’s how it might look if you were to expose an alertUser function which +pops open an alert dialog with the given alert text:

+
function alertUser(params) {
+    alert(params.alertText);
+}
+Clutch.Core.registerMethod('alertUser', alertUser);
+
+
+
+
+

Loading

+

One thing we need to do all the time in building iOS apps is to wait for some +data. Whenever we do that, we need to somehow indicate to the user that +there’s something loading. Clutch provides an easy mechanism for showing and +hiding loading screens.

+
+
+Clutch.Load.begin([loadingText][, top])
+
+++ + + + +
Arguments:
    +
  • loadingText (string) – Optional text to show to the user inside of the loading dialog.
  • +
  • top (float) – Optional offset from the top of the ClutchView, in pixels.
  • +
+
+

Pops up the loading dialog with optional loading text.

+
+ +
+
+Clutch.Load.end()
+

Removes the loading dialog.

+
+ +
+
+

UI

+

Clutch helps you present a UI to your users that looks and feels like it’s +native. Here’s what’s provided:

+
+
+Clutch.UI.View([options])
+
+++ + + + +
Arguments:
    +
  • options – A mapping of options to be provided to the view instance.
  • +
+
+

This view is the core of all of the Clutch-provided UI constructs. It’s +actually a subclass of Backbone.View, with a few added extras. Here are +the added properties and functions:

+
+
+template
+

The default template provided for all Clutch.UI.View subclasses is +a simple underscore template that looks like <%= c.value %>.

+
+ +
+
+render()
+

The default render for all Clutch.UI.View subclasses renders the +template but passes the view options as the c varible. It’s +equivalent to this implementation:

+
$(this.el).html(this.template({c: this.options}));
+
+
+
+ +
+ +
+
+Clutch.UI.Table([options])
+
+++ + + + +
Arguments:
    +
  • options – A mapping of options to be provided to the view instance.
  • +
+
+

This view creates a user interface that looks and acts like Cocoa’s +UITableView.

+

You must extend this view to populate it with any data, and here are the +parameters you can provide in your extension:

+

Required

+
+
+numSections
+

The number of table sections that should be displayed.

+
+ +
+
+numCells(section)
+
+++ + + + +
Arguments:
    +
  • section – The 0-indexed integer of the current section.
  • +
+
+

Determines the number of cells to be rendered for the given section.

+
+ +
+
+cell(section, row)
+
+++ + + + +
Arguments:
    +
  • section – The 0-indexed integer of the current section.
  • +
  • row – The 0-indexed integer of the current row.
  • +
+
+

Returns the Clutch.UI.TableCell subclass that should render the +requested table cell.

+
+ +

Optional

+
+
+style
+

Determines the visual style of the table. Currently only supports +'normal' and 'grouped'.

+
+ +
+
+tableHeader()
+

Returns the Clutch.UI.TableHeader subclass that should render into +the table’s header area.

+
+ +
+
+tableFooter()
+

Returns tje Clutch.UI.TableFooter subclass that should render into +the table’s footer area.

+
+ +
+
+sectionHeader(section)
+
+++ + + + +
Arguments:
    +
  • section – The 0-indexed integer of the current section.
  • +
+
+

Returns a Clutch.UI.SectionHeader subclass that should render into +the given table section’s header area.

+
+ +
+
+sectionFooter(section)
+
+++ + + + +
Arguments:
    +
  • section – The 0-indexed integer of the current section.
  • +
+
+

Returns a Clutch.UI.SectionHeader subclass that should render into +the given table section’s footer area.

+
+ +
+ +
+
+Clutch.UI.TableHeader([options])
+
+++ + + + +
Arguments:
    +
  • options – A mapping of options to be provided to the view instance.
  • +
+
+

A Clutch.UI.View subclass for rendering table headers.

+
+ +
+
+Clutch.UI.TableFooter([options])
+
+++ + + + +
Arguments:
    +
  • options – A mapping of options to be provided to the view instance.
  • +
+
+

A Clutch.UI.View subclass for rendering table footers.

+
+ +
+
+Clutch.UI.SectionHeader([options])
+
+++ + + + +
Arguments:
    +
  • options – A mapping of options to be provided to the view instance.
  • +
+
+

A Clutch.UI.View subclass for rendering table section headers.

+
+ +
+
+Clutch.UI.SectionFooter([options])
+
+++ + + + +
Arguments:
    +
  • options – A mapping of options to be provided to the view instance.
  • +
+
+

A Clutch.UI.View subclass for rendering table section footers.

+
+ +
+
+Clutch.UI.TableCell([options])
+
+++ + + + +
Arguments:
    +
  • options – A mapping of options to be provided to the view instance.
  • +
+
+

In that options object, here are the expected and optional parameters:

+

Required

+
+
+value
+

The value that should be displayed in the cell.

+
+ +

Optional

+
+
+accessory
+

Determines which accessory to display for the cell. Should be one of +Clutch.UI.Accessories.

+
+ +
+
+tap(e)
+

An optional function which will receive an event whenever this table +cell is tapped by the end user.

+
+ +
+ +
+

Note

+

If you subclass Clutch.UI.TableCell, then you can set the multiline +attribute to true and it will be able to display more than one line +of content.

+
var MultiLineCell = Clutch.UI.TableCell.extend({
+    multiline: true
+});
+
+
+
+
+
+Clutch.UI.Accessories
+

Accessories that can be used to decorate a table cell.

+
+
+Checkmark
+

Shows a check mark.

+
+ +
+
+DisclosureButton
+

Shows a button with a right-facing triangle indicating that there is +more content.

+
+ +
+
+DisclosureIndicator
+

Shows a right-facing triangle indicating that there is more content.

+
+ +
+ +
+
+

Example

+

Here’s an example of how you could use this JavaScript library to create a +table which has some cells and a few headers.

+
// Let's create a simple table by subclassing Clutch.UI.Table
+var SimpleTable = Clutch.UI.Table.extend({
+    // Our table should have two sections
+    numSections: 2,
+    // We want it to display in the "grouped" style which looks cooler
+    style: 'grouped',
+
+    numCells: function(section) {
+        // Each section has 4 cells
+        return 4;
+    },
+
+    sectionHeader: function(section) {
+        // The section header just displays its own index
+        return new Clutch.UI.TableSectionHeader(
+            {value: 'Section ' + section + ' Header'}
+        );
+    },
+
+    sectionFooter: function(section) {
+        // The first section doesn't have a footer
+        if(section === 0) {
+            return null;
+        }
+        // The second section does have a footer though
+        return new Clutch.UI.TableSectionFooter(
+            {value: 'Section ' + section + ' Footer'}
+        );
+    },
+
+    cell: function(section, row) {
+        var value = 'Section ' + section + ' Cell ' + row;
+        return new Clutch.UI.TableCell({
+            value: value,
+            accessory: Clutch.UI.Accessories.DisclosureButton,
+            tap: function(e) {
+                // Call the "tapped" method on iOS, and pass
+                // the text value of the cell as an argument.
+                Clutch.Core.callMethod('tapped', {value: value});
+            }
+        });
+    }
+});
+
+// Remember to wait for this event before rendering out our table.
+Clutch.Core.init(function() {
+    // Instantiate our new table
+    var table = new SimpleTable();
+    // Render the table
+    $('body').append(table.render().el);
+});
+
+
+
+
+ + +
+ +
+
+

Contents

+ +

Previous topic

+

+ Reference +

+

Next topic

+

+ iOS Library Reference +

+

This Page

+ + + +
+
+
+
+ +
+
+ + + + + + + + + + \ No newline at end of file diff --git a/objects.inv b/objects.inv new file mode 100644 index 0000000..fc3fcb3 Binary files /dev/null and b/objects.inv differ diff --git a/pulltorefresh.html b/pulltorefresh.html new file mode 100644 index 0000000..ee69d3c --- /dev/null +++ b/pulltorefresh.html @@ -0,0 +1,346 @@ + + + + + + + + + Clutch.io - Integrating Pull-to-Refresh - Documentation + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + +
+
+ +
+
+ +
+

Integrating Pull-to-Refresh

+

One common UI element that people like to have in their apps is +pull-to-refresh. By using some open source software along with a little bit +of integration with Clutch, you can add this UI element to your Clutch screens +quite easily!

+
+

Download and Install EGOTableViewPullRefresh

+

For the purposes of this tutorial, we’re going to use the open source +EGOTableViewPullRefresh project, by the talented team at enormego.com. +First you need to clone the repository:

+
git clone https://github.com/enormego/EGOTableViewPullRefresh.git
+
+

Then open the directory:

+
open EGOTableViewPullRefresh
+
+

Now drag the EGOTableViewPullRefresh folder into your XCode project.

+
+
+

Integrate EGOTableViewPullRefresh in Your Header File

+

In your ViewController’s header file, import the pull-to-refresh library +headers so that we have something to work with:

+
#import "EGORefreshTableHeaderView.h"
+
+
+

Then add make sure your Clutch ViewController is a scroll view delegate, and a +EGORefreshTableHeaderDelegate:

+
@interface ImageTableController : UIViewController <ClutchViewDelegate, UIScrollViewDelegate, EGORefreshTableHeaderDelegate>
+
+
+

Now add three properties:

+
@property (nonatomic, retain) EGORefreshTableHeaderView *refreshHeaderView;
+@property (nonatomic, retain) NSDate *dateLastUpdated;
+@property (nonatomic, assign) BOOL reloading;
+
+
+
+
+

Synthesize and Instantiate Refresh Variables

+

First, synthesize the new variables that you have added:

+
@synthesize refreshHeaderView = _refreshHeaderView;
+@synthesize dateLastUpdated = _dateLastUpdated;
+@synthesize reloading = _reloading;
+
+
+

Now instantiate the view and set the last updated date in your loadView, +and set this class as both the delegate and the scroll delegate for Clutch:

+
- (void)loadView
+{
+
+    // ...
+
+    self.dateLastUpdated = [NSDate date];
+
+    // Initialize the pull-to-refresh implementation
+    self.refreshHeaderView = [[EGORefreshTableHeaderView alloc] initWithFrame:CGRectMake(0, -324, 320, 368)];
+    [self.refreshHeaderView release];
+    [self.view addSubview:self.refreshHeaderView];
+    self.refreshHeaderView.delegate = self;
+    [self.refreshHeaderView refreshLastUpdatedDate];
+
+    // Set up the Clutch view
+    self.clutchView = [[ClutchView alloc] initWithFrame:CGRectMake(0, 0, 320, 411)
+                                                andSlug:@"SOMESLUG"];
+    [self.clutchView release];
+    self.clutchView.delegate = self;
+    self.clutchView.scrollDelegate = self;
+    [self.view addSubview:self.clutchView];
+
+    // ...
+
+}
+
+
+
+
+

Add Delegate Methods

+

We’re almost there! Everything is set up, except there are a bunch of delegate +methods that are being called and we haven’t yet implemented them yet. First +up is the EGORefreshTableHeaderView delegate methods:

+
- (void)egoRefreshTableHeaderDidTriggerRefresh:(EGORefreshTableHeaderView *)view
+{
+    [self.clutchView.webView reload];
+    self.reloading = TRUE;
+}
+
+- (BOOL)egoRefreshTableHeaderDataSourceIsLoading:(EGORefreshTableHeaderView *)view
+{
+    return self.reloading;
+}
+
+- (NSDate*)egoRefreshTableHeaderDataSourceLastUpdated:(EGORefreshTableHeaderView *)view
+{
+    return self.dateLastUpdated;
+}
+
+- (void)doneLoadingTableViewData
+{
+    self.reloading = FALSE;
+    self.dateLastUpdated = [NSDate date];
+    [self.refreshHeaderView egoRefreshScrollViewDataSourceDidFinishedLoading:self.clutchView.scrollView];
+}
+
+
+
+

Note

+

You may not want to just call [self.clutchView.webView reload]. You +could also call a method in the JavaScript to refresh the data, or get the +data using Objective-C code. This is the easiest and simplest way to +achieve a reload though.

+
+

Now we need to implement one of the ScrollViewDelegate delegate methods:

+
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
+{
+    [self.refreshHeaderView egoRefreshScrollViewDidScroll:scrollView];
+
+    // This slides the pull-to-refresh view into the proper location
+    self.refreshHeaderView.frame = CGRectMake(self.refreshHeaderView.frame.origin.x,
+                                              -324.0f - scrollView.contentOffset.y,
+                                              self.refreshHeaderView.frame.size.width,
+                                              self.refreshHeaderView.frame.size.height);
+}
+
+
+
+
+

Pulling it All Together

+

We have one last step before this will all work properly. Right now you have +a Clutch view that, when dragged, will reveal a pull-to-refresh panel. When +you drag it down, it will reload the page. But it won’t yet know when it’s +done refreshing. That’s a bummer, so let’s fix it:

+
- (void)clutchView:(ClutchView *)clutchView
+      methodCalled:(NSString *)method
+        withParams:(NSDictionary *)params
+          callback:(void(^)(id))callback
+{
+    // ...
+
+    if([method isEqualToString:@"clutch.loading.end"]) {
+        [self doneLoadingTableViewData];
+    }
+
+    // ...
+}
+
+
+

As you can see, we’re hooking into the clutch.loading.end method call +to determine when loading is complete. Now all that’s left to do is call that +method in our JavaScript code:

+
Clutch.Core.init(function() {
+    // Do your loading here, and then call...
+    Clutch.Loading.end();
+});
+
+
+

Boom! Now we’re done integrating a pull-to-refresh into our Clutch screen. +Thanks to the power of great open source code and a bit of integration, it’s +quite easy to get this great effect in your app.

+
+
+

Example

+

We’ve built an example application called Imgs which uses this technique, so +you can check out the code and see how we did it in a real app.

+
+
+ + +
+ +
+
+

Contents

+ +

Previous topic

+

+ Adding a New Screen +

+

Next topic

+

+ Reference +

+

This Page

+ + + +
+
+
+
+ +
+
+ + + + + + + + + + \ No newline at end of file diff --git a/reference.html b/reference.html new file mode 100644 index 0000000..eb95752 --- /dev/null +++ b/reference.html @@ -0,0 +1,192 @@ + + + + + + + + + Clutch.io - Reference - Documentation + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + +
+
+ +
+ + +
+
+

Previous topic

+

+ Integrating Pull-to-Refresh +

+

Next topic

+

+ JavaScript Library Reference +

+

This Page

+ + + +
+
+
+
+ +
+
+ + + + + + + + + + \ No newline at end of file diff --git a/screencasts.html b/screencasts.html new file mode 100644 index 0000000..d148002 --- /dev/null +++ b/screencasts.html @@ -0,0 +1,206 @@ + + + + + + + + + Clutch.io - Screencasts - Documentation + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + +
+
+ +
+
+ +
+

Screencasts

+

Everyone learns in different ways. For some, the best way to learn a new tool +is to pore over documentation for hours. For others, jumping in on the deep +end and just starting to build something is the best. For others still, visual +and/or audio walkthroughs are best. Because of that, we want to make sure +there are ample examples of each! Here’s our collection of screencasts:

+
+

Getting Started - New XCode Project

+

In this screencast we will start a new Clutch project from scratch, explaining +in detail each step that’s required and why.

+
+
+

Getting Started - Existing XCode Project

+

In this screencast we will start a new Clutch project for an existing iOS +application, explaining in detail each step that’s required and why.

+
+
+

Tutorial - Adding a Screen

+

Once you have your project all set up, this tutorial will help show you how to +add a new Clutch screen to your project.

+
+
+

Tutorial - Demo App Walkthrough

+

Our Demo app, Imgs, has a lot of code and it’s fairly large. In this tutorial, +we’ll go over the basics of how it fits together and how it works.

+
+
+

Tutorial - Building a Twitter Search App

+

In this video we’ll demonstrate the power of Clutch by building a very simple +Twitter search app.

+
+
+ + +
+ +
+
+

Contents

+ +

Previous topic

+

+ Terms and Definitions +

+

This Page

+ + + +
+
+
+
+ +
+
+ + + + + + + + + + \ No newline at end of file diff --git a/search.html b/search.html new file mode 100644 index 0000000..25717fc --- /dev/null +++ b/search.html @@ -0,0 +1,164 @@ + + + + + + + + + Clutch.io - Search - Documentation + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + +
+
+ +
+
+ + +
+

Search

+
+ +

+ Please activate JavaScript to enable the search + functionality. +

+
+

+ From here you can search these documents. Enter your search + words into the box below and click "search". Note that the search + function will automatically search for all of the words. Pages + containing fewer words won't appear in the result list. +

+
+ + + +
+
+ + + + +
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + + + + + + + + \ No newline at end of file diff --git a/searchindex.js b/searchindex.js new file mode 100644 index 0000000..cf33bad --- /dev/null +++ b/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({objects:{"":{tableHeader:[13,0,1,""],style:[13,1,1,""],tap:[13,0,1,""],render:[13,0,1,""],sectionHeader:[13,0,1,""],Checkmark:[13,1,1,""],DisclosureButton:[13,1,1,""],value:[13,1,1,""],accessory:[13,1,1,""],cell:[13,0,1,""],sectionFooter:[13,0,1,""],DisclosureIndicator:[13,1,1,""],template:[13,1,1,""],numCells:[13,0,1,""],numSections:[13,1,1,""],tableFooter:[13,0,1,""]},"Clutch.Load":{begin:[13,0,1,""],end:[13,0,1,""]},"Clutch.UI":{TableHeader:[13,0,1,""],TableCell:[13,0,1,""],SectionHeader:[13,0,1,""],Accessories:[13,1,1,""],SectionFooter:[13,0,1,""],Table:[13,0,1,""],TableFooter:[13,0,1,""],View:[13,0,1,""]},"Clutch.Core":{callMethod:[13,0,1,""],registerMethod:[13,0,1,""],init:[13,0,1,""]}},terms:{all:[0,1,3,10,7,9,17,13,18,15,16],code:[1,3,7,8,9,17,11,13,14,15],myapp:7,scratch:17,global:7,four:14,correl:7,dirnam:15,follow:[14,0,1],row:13,whose:13,decid:10,nsinteg:9,depend:14,system:[7,8],initwithfram:[10,9,3],navigationitem:14,send:[7,9],articl:[7,4,18,12],init:[3,13],present:[10,13],under:[14,15],andslug:[10,9,3],redcolor:14,sent:9,sourc:[7,11,3],everi:7,string:[14,1,13],straightforward:[7,13],fals:3,"void":[10,14,1,9,3],faq:7,account:[0,1,7,8,14,15],your_application_kei:[14,1],clutchmyapp:7,mechan:13,veri:[14,17],affect:8,nsdictionari:[10,14,9,3,13],nonatom:[10,3],did:[7,3],showcas:11,button:[7,8,1,14,13],list:[0,15,16],upload:15,clutchclient:15,"try":7,nsdate:3,technolog:[7,13],team:3,quick:0,imgur:11,div:10,didreceivememorywarn:10,prepar:[1,9],numcel:13,fortun:10,ten:1,colorfromhex:14,pore:[6,17],direct:[7,9],sign:0,jump:[6,17],second:[7,13],video:[6,17],uiscrollview:[9,3],pass:[10,7,8,9,13,14],download:[14,18,1,3],clutchconf:[7,9,2],append:13,even:8,index:[7,4,15,13],what:[7,10,15,13],hide:13,insid:[7,13],phonegap:7,section:[7,14,13],abl:[7,15,13],interfaceorient:10,launch:9,access:7,version:[7,8,9,15,16],"new":[0,1,3,12,10,6,7,8,17,11,13,14,15,18],method:[1,3,10,7,9,13,18],can:[1,3,7,8,9,11,13,14,15],involv:7,bylin:[6,17],variat:8,gener:7,nslog:10,here:[0,1,3,10,6,17,11,13,14,15],bodi:13,let:[7,3,13],path:8,along:[10,3],prepareforanim:9,valu:[10,13],wait:13,great:[11,3],talent:3,ahead:13,uikit:10,ff0044:14,larger:7,ctx:1,exampleapp:16,subview:7,nsstring:[10,9,3],within:7,loginbutton:[14,1],chang:[7,8,10],uiscrollviewdeleg:[9,3],alerttext:13,extra:[5,14,13],jar:1,app:[0,3,12,10,7,8,9,17,11,13,18,16],layer:[7,10,11],brought:9,releas:[10,14,3],leav:7,instal:[18,15,3,2],should:[0,1,10,7,8,9,13,15],mobil:13,bookkeep:13,from:[10,7,8,17,13,14,15],zip:14,commun:[9,15,13],regist:[7,9,16,13],two:[7,8,13],next:[14,15],websit:0,tablefoot:13,live:8,call:[7,1,9,3,13],simpler:8,type:[0,8,5,10,15,16],tell:8,more:[7,8,16,13],alphabet:14,peopl:[16,3],relat:14,thei:[7,8,15],uitabbarcontrol:7,instanc:[0,1,10,9,13,14,16],phone:7,visual:[6,17,13],indic:[4,13],sens:7,hold:[7,10,16],effort:11,cach:10,must:[14,1,15,13],clutchj:15,buttoncolor:14,hour:[6,17],tunnel:9,testdata:[14,1],setup:[10,1],work:[1,3,7,17,14,15],dev:[15,16],viewdidunload:10,whatev:[14,1,9],learn:[6,17],purpos:3,savedinstancest:1,control:[10,9],tap:[10,8,13],quickstart:7,give:[7,8],sudo:15,accept:14,titanium:7,befor:[3,13],want:[3,10,6,7,17,13,15],phrase:8,keep:13,plist:[7,9,15],whichev:8,alwai:13,cours:11,end:[10,17,6,3,13],goal:[5,8,1,14],rather:[7,15],anoth:[1,15],disclosurebutton:13,write:[7,13],how:[1,3,7,8,17,11,13,14,18],allowfullscreen:[6,17],viewdiddisappear:[10,9],instead:7,uicolor:14,simpl:[7,14,15,17,13],css:[7,15,16,13],updat:[7,9,3],map:13,product:15,resourc:13,modal:7,clone:3,after:[10,8,13],spot:7,appnam:15,startscreen:[10,15],mai:[7,9,3],underscor:13,data:[1,3,5,8,10,13,14],clutchabtest:1,demonstr:17,accessori:13,alloc:[10,14,3],"short":[10,0,1,14,16],honestli:7,footer:13,block_:9,minim:7,correspond:16,element:3,callback:[10,9,3,13],libsqlite3:14,green:[14,1],allow:[7,9,11],enter:[7,10],"_datelastupd":3,talk:16,help:[10,7,8,9,17,13],over:[6,17],disclosureind:13,becaus:[7,6,17],still:[6,17],dynam:7,paramet:[9,13],perfect:7,style:[7,14,13],outer:7,render:[7,13],fit:[7,18,17],chosen:[14,1],fix:3,greencolor:14,quantit:8,better:[14,8,1],platform:[7,11],window:7,html:[7,15,16,13],requir:[0,6,17,13],bummer:3,tablesectionfoot:13,main:[1,9],might:[0,10,7,8,13,14,16],pixel:13,them:[7,11,3],good:[10,8],"return":[10,9,3,13],setcontentview:1,handl:[7,10],auto:7,tunnelurl:9,bound:10,framework:[7,8,14,12,4],now:[0,1,3,10,8,14],login_button:1,enabl:7,choic:10,term:[12,16,2],tablecel:13,name:[0,1,10,7,13,14,15,16],walkthrough:[12,6,17],clutch:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18],userid:13,refresh:[7,12,9,3,18],your_rpc_url:[14,1],easili:[16,3],slide:[7,3],screencast:[5,4,6,17,12],mode:[7,18],each:[6,7,8,9,17,13,16],side:[7,8,13],mean:7,callmethod:[9,13],registermethod:13,dylib:14,realli:[11,13],"static":7,viewdidload:10,aim:7,our:[1,3,6,7,8,17,11,13],happen:[7,9,13],extract:[14,8],event:[7,10,13],out:[7,8,14,3,13],variabl:[18,8,3],shown:16,goe:7,publish:15,content:[7,9,16,13],rightbarbuttonitem:14,internet:[7,11],got:10,optstr:1,forth:[7,11],myscreen:7,red:[14,1],common:[7,10,14,3],multilin:13,foreground:[9,15],navig:[7,14,9],carv:7,xib:7,free:7,standard:10,reason:7,base:[7,15],dictionari:[14,9],ask:10,hand:7,care:8,capabl:15,could:[7,16,3,13],area:[7,16,13],put:11,loadview:[7,10,3],thing:[7,0,13,8],place:15,viewcontrol:[9,3],retain:[10,3],assign:[14,3],first:[0,1,3,10,7,13,14],origin:3,softwar:3,directli:7,feel:[7,13],onc:[10,0,15,17,13],scrollviewdidscrol:3,number:[16,13],yourself:11,hook:[10,3],instruct:[0,15],done:[7,15,3],messag:10,blank:7,loginbuttoncolor:[14,1],custom:15,open:[7,11,3,13],fanci:7,size:[8,3],differ:[1,6,7,8,17,14],width:[17,6,3],associ:7,top:[7,13],usertap:13,sometim:[7,11],construct:13,attach:13,oncreat:1,clutchviewdeleg:[10,9,3,2],termin:10,conveni:15,"final":[7,1],store:[7,8],breez:7,option:[7,0,13,8],tool:[10,8,6,17],copi:[10,8],specifi:15,selector:14,recompil:7,pars:11,pragma:10,sectionhead:13,nobodi:7,haven:3,id_nam:10,past:7,kind:13,target:[7,14],whenev:[15,13],provid:[7,9,11,13,14,15],remov:13,structur:[7,18],exampl:[1,2,3,12,10,6,7,8,17,11,13,14,16,18],project:[0,1,3,10,6,7,12,17,14],reus:7,friend:16,were:13,design:[11,13],uiview:10,sai:7,comput:[7,15],modern:11,mind:[11,13],argument:[14,1,9,13],current:[9,15,13],have:[0,1,3,10,7,8,17,13,14,16],tabl:[4,13],need:[0,1,3,7,13,14],tablehead:13,date:3,built:[3,13],equival:13,egorefreshscrollviewdatasourcedidfinishedload:3,self:[10,14,3],multilinecel:13,note:[14,1,15,3,13],tintcolor:14,without:7,build:[6,7,12,17,11,13],which:[1,3,10,7,8,9,13,14,16],combin:[7,13],didfinishlaunchingwithopt:14,singl:[7,10,13],zepto:[7,13],anatomi:[7,12,18],methodcal:[10,9,3],begin:[1,15,13],setbackgroundcolor:1,normal:[1,5,7,8,13,14],track:[5,8],object:[1,3,10,7,9,13],reach:[5,14,1],deleg:[10,18,9,3],most:[7,10],letter:14,deploi:7,coin:8,mozallowfullscreen:[6,17],"class":[10,3],don:[7,0,1,14],url:[0,9,16],clear:10,later:7,request:13,doe:[9,13],part:7,uitableview:13,clutchabdatatest:1,left:[7,8,3],remot:7,someth:[1,3,10,6,7,17,13],fact:7,show:[7,8,17,11,13,15],text:[7,8,10,13],xcode:[0,3,10,7,12,17],preparefordisplai:9,scrollview:[9,3],connect:7,bring:15,font:8,fine:7,find:[1,13],redirect:0,cell:13,onli:[7,8,13],locat:3,pretti:7,clutchsync:[9,2],explain:[6,17],configur:[7,10,9,15],activ:1,than:[7,15,13],analyz:9,templat:13,folder:[7,14,3,18],sdk:[5,4,1,14],local:[7,0,15],serv:[7,15],variou:15,get:[0,1,3,12,5,6,7,10,9,17,14,18],familiar:11,uitoolbar:7,between:[7,9,13],refreshheaderview:3,nativ:[7,13],scrollviewdeleg:3,report:8,cgrect:9,layout:1,reveal:3,bar:14,scrolldeleg:[9,3],specif:7,synthes:[10,18,3],"public":1,reload:3,mainscreen:10,integr:[18,12,1,11,3],contain:[7,9,16],where:[7,14,1],view:[7,10,9,3,13],user:[10,7,8,9,11,13,15,16],set:[0,1,3,10,7,9,17,13,14],"float":13,frame:[9,3],methodnam:13,see:[7,11,3,13],respons:9,portrait:[6,17],best:[8,6,11,17,13],egorefreshtableheaderdatasourcelastupd:3,flexibl:13,kei:[1,9,13],egorefreshscrollviewdidscrol:3,getapplicationcontext:1,easi:[10,11,3,13],label:[10,8],written:7,won:3,action:[14,1],simplest:3,"import":[7,10,14,3],experi:[7,1],across:7,attribut:13,onresum:1,extend:13,addsubview:[10,3],screen:[3,10,7,12,9,17,13,18,15,16],javascript:[2,3,10,7,12,9,13,15,16],popul:13,logdeviceidentifi:9,otherwis:[14,1],viewdidappear:[10,9],group:13,advertis:8,come:10,thank:3,both:[7,3,13],protect:1,last:3,img:[18,17,11,3],extens:13,"_clutchview":10,"_reload":3,etc:10,doneloadingtableviewdata:3,context:1,logic:7,improv:8,login:1,com:[17,6,3],load:[10,15,3,2,13],simpli:7,point:[1,9],instanti:[7,10,18,3,13],overview:[5,8,4],pop:[7,13],height:[17,6,3],sync:9,header:[18,3,13],rpc:9,empti:15,param:[10,9,3,13],loginbuttontitl:[14,1],bridg:[7,18,9],quit:[7,10,3],tint:14,loginbuttonvariablecolor:14,deep:[6,17],framebord:[6,17],devic:[9,15],three:[7,1,3],"_refreshheaderview":3,mark:[10,13],toolbar:7,easiest:[0,15,3],basic:[15,17],addit:10,quickli:7,egorefreshtableheaderdidtriggerrefresh:3,bit:[7,3],given:[14,9,16,13],imag:[10,8,11,18],search:[4,17,12],ani:[7,10,9,13],togeth:[7,18,17,3],func:13,demand:15,those:[7,8,1],statist:9,"case":0,look:[7,14,1,13],vimeo:[6,17],also:[7,11,3,13],properti:[10,9,3,13],easier:10,appkei:9,abov:[10,9],fun:[18,11],aid:14,anonym:1,uibarbuttonitemstylebord:14,everyon:[6,17],loadingtext:13,purchas:8,file:[1,3,10,7,18,14,15,16],helper:13,almost:3,demo:[12,17],metric:8,readm:0,player:[6,17],itself:10,conf:9,tje:13,webkitallowfullscreen:[6,17],ship:11,decor:13,"null":13,develop:[7,18,15],welcom:4,contentoffset:3,perform:[14,8,1,9,13],suggest:[7,18],make:[3,10,6,7,8,17,11,14,16],same:[7,9],check:[7,3,13],lengthi:7,tablesectionhead:13,android:[5,4,1,6],document:[4,6,17],sharedclientforkei:9,complet:3,week:11,autoreleas:10,ifram:[6,17],finish:[9,13],http:[17,6,3],nil:10,screenslug:15,nib:10,effect:3,evil:10,alert:13,driven:[5,8,1,14],fairli:17,onpaus:1,initi:[9,3,13],egorefreshtableheaderdatasourceisload:3,typic:10,cocoa:13,techniqu:3,task:[10,15],off:11,ampl:[6,17],firstli:7,whole:7,builder:7,well:[7,14,15],id_slug:10,qualit:8,getusernam:13,anim:[7,10,9],client:[12,9,15,2],command:[0,2,10,12,15,16],thi:[1,3,10,6,7,8,9,17,11,13,14,16],choos:[7,0,10,8],newaccountcr:14,everyth:[1,3],audio:[6,17],roughli:16,latest:[9,15],comment:11,uiscreen:10,identifi:[7,10,9],just:[7,17,6,3,13],photo:10,rest:1,detail:[7,10,6,17],isequaltostr:[10,3],monei:8,yet:[14,0,1,3],objectforkei:[10,14],web:[7,9,13],versu:8,expos:13,shouldautorotatetointerfaceorient:10,except:[9,3],littl:3,color:[14,8,1],add:[1,3,10,7,18,9,17,14],other:[7,15,6,17],appdeleg:14,inner:7,tweak:7,els:15,uiinterfaceorient:10,save:8,uinavigationcontrol:7,modul:[7,4],alertus:13,real:[3,13],applic:[3,6,7,9,17,11,13,14,15],mayb:1,piec:8,onnewaccountcr:1,ensureus:14,testwithnam:14,know:[7,15,3],background:9,someslug:3,press:7,amp:[6,17],enormego:3,like:[1,3,10,7,8,9,11,13,14,16],measur:8,xcodeproj:7,backbon:[7,13],success:9,cooler:13,withparam:[10,9,3],anyth:7,integ:13,noth:13,collect:[6,17],channel:13,bunch:3,uibarbuttonitem:14,page:[7,4,9,3],underli:9,right:[10,8,3,13],captur:7,egorefreshtableheaderdeleg:3,egorefreshtableheaderview:3,settext:1,some:[3,6,7,8,17,11,13,16],back:[7,8],sure:[10,17,6,14,3],proper:3,server:8,librari:[1,2,3,7,12,9,13,14],woud:9,guid:[7,0],setupforkei:14,avoid:7,though:[3,13],definit:[12,16,2],achiev:[3,13],subclass:[10,1,9,13],usernam:13,larg:17,refer:[4,2,10,7,12,9,13,18,16],core:[7,9,3,2,13],previou:[7,9],run:[0,1,7,8,13,14,15],power:[17,11,3],cgrectmak:[10,3],rpcurl:[14,9],usag:[9,15],refreshlastupdatedd:3,solut:7,step:[0,1,3,6,7,17,14],repositori:[7,3],offset:13,simplet:13,"super":[10,1],slug:[10,9,16],panel:3,src:[6,17],about:[7,8,9,16],actual:[7,13],would:[7,10,14],startapp:15,manag:15,photoviewcontrol:10,lifecycl:10,dialog:13,act:13,webview:[9,3],block:[14,9,13],findviewbyid:1,own:[7,13],tutori:[18,4,17,3,12],easy_instal:15,automat:7,due:7,down:3,been:[9,15,13],storag:11,your:[0,1,3,10,7,8,9,17,13,14,15,16,18],per:1,git:3,triangl:13,log:[14,9],wai:[1,3,6,7,8,17,11,15],few:[7,13],aren:10,checkmark:13,support:[10,13],hex:14,clutchab:[14,1],happi:11,start:[0,1,5,6,7,12,17,13,14,15,18],initwithtitl:14,interfac:[7,10,3,13],includ:[15,11],uiwebview:9,"var":13,numsect:13,twitter:[12,17],"function":[1,3,7,9,13,14],properli:3,interest:8,form:7,jsonobject:1,bundl:[7,1],somehow:13,github:3,bui:8,link:[7,14],renam:7,line:[0,15,16,13],"true":[3,13],varibl:13,pull:[18,12,9,3],made:13,input:10,datelastupd:3,possibl:7,whether:8,displai:[7,9,13],until:13,below:[10,14,1],egotableviewpullrefresh:[18,3],highlight:7,inform:[7,9],similar:[7,9],expect:13,uiinterfaceorientationportrait:10,superview:10,creat:[0,1,10,7,8,13,14,15],certain:0,"abstract":7,imagetablecontrol:3,doesn:[7,10,13],implement:[10,1,9,3,13],glanc:7,exist:[12,6,17],face:13,codebas:11,fill:7,readi:7,successfulli:15,titl:[14,1,6,17],when:[3,10,7,8,9,11,13],workhors:9,orient:10,"default":[15,13],cleanup:9,bool:[10,9,3],boom:3,rememb:13,test:[4,1,5,6,8,14],you:[0,1,3,10,7,8,9,17,11,13,14,15,16],sectionfoot:13,nice:7,intend:9,determin:[7,3,13],why:[6,17],drag:[14,3],uiviewcontrol:[7,10,9,16,3],appceler:7,stai:0,receiv:13,directori:[7,10,15,3,18],lot:17,flag:15,scroll:[9,3],portion:16,time:[7,8,9,15,13],push:[7,15],clutchview:[2,3,10,7,9,13],profil:16,hello:13,goalreach:[14,1]},objtypes:{"0":"js:function","1":"js:attribute"},titles:["Getting Started","Android SDK","Reference","Integrating Pull-to-Refresh","Welcome to Clutch’s documentation!","Clutch A/B Testing","Screencasts","Anatomy of an App Using Clutch","Overview","iOS Library Reference","Adding a New Screen","Example Apps","Clutch Framework","JavaScript Library Reference","iOS SDK","Clutch Command Client","Terms and Definitions","Screencasts","Tutorials and Articles"],objnames:{"0":["js","function","JavaScript function"],"1":["js","attribute","JavaScript attribute"]},filenames:["gettingstarted","ab-testing-android","reference","pulltorefresh","index","ab-testing","ab-testing-screencasts","anatomy","ab-testing-overview","ioslibrary","addingnewscreen","examples","framework","jslibrary","ab-testing-ios","commandclient","termsanddefinitions","screencasts","tutorials"]}) \ No newline at end of file diff --git a/termsanddefinitions.html b/termsanddefinitions.html new file mode 100644 index 0000000..3a59b4e --- /dev/null +++ b/termsanddefinitions.html @@ -0,0 +1,186 @@ + + + + + + + + + Clutch.io - Terms and Definitions - Documentation + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + +
+
+ +
+
+ +
+

Terms and Definitions

+
+
Clutch App
+
A container holding all of the files that will make up the +HTML/JavaScript/CSS portion of your app. This container is registered +with Clutch and is given a name and a short name to easily talk about it.
+
Screen
+
A content area that will be shown to the user using your app. Each +Clutch App contains one or more screens. Examples of a screen could be +a user profile or a list of friends. This roughly corresponds one-to-one +with the number of UIViewControllers in your app that use Clutch.
+
Short Name
+
The short version of an app name that is used in the URL for your +Clutch App and is typed into the command line. For instance an +app named “Example App” might have the short name “exampleapp”, which +you might type into the command line like clutch dev -a exampleapp. +Some people might refer to this as a Slug.
+
+
+ + +
+ +
+
+

Previous topic

+

+ Clutch Command Client +

+

Next topic

+

+ Screencasts +

+

This Page

+ + + +
+
+
+
+ +
+
+ + + + + + + + + + \ No newline at end of file diff --git a/tutorials.html b/tutorials.html new file mode 100644 index 0000000..ed921a1 --- /dev/null +++ b/tutorials.html @@ -0,0 +1,195 @@ + + + + + + + + + Clutch.io - Tutorials and Articles - Documentation + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + +
+
+ + + +
+
+ + + + + + + + + + \ No newline at end of file