Knockout.js Twitter client example rewritten to Bck2Brwsr (just missing JSON access to tweets) model
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 04 Apr 2013 13:12:17 +0200
branchmodel
changeset 9319a7df12648b9
parent 930 e8916518b38d
child 932 0dd6343a91f5
Knockout.js Twitter client example rewritten to Bck2Brwsr (just missing JSON access to tweets)
javaquery/demo-twitter/bck2brwsr-assembly.xml
javaquery/demo-twitter/nb-configuration.xml
javaquery/demo-twitter/nbactions.xml
javaquery/demo-twitter/pom.xml
javaquery/demo-twitter/src/main/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClient.java
javaquery/demo-twitter/src/main/resources/org/apidesign/bck2brwsr/demo/twitter/index.html
javaquery/demo-twitter/src/main/resources/org/apidesign/bck2brwsr/demo/twitter/twitterExample.css
javaquery/demo-twitter/src/test/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClientTest.java
javaquery/pom.xml
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/javaquery/demo-twitter/bck2brwsr-assembly.xml	Thu Apr 04 13:12:17 2013 +0200
     1.3 @@ -0,0 +1,71 @@
     1.4 +<?xml version="1.0"?>
     1.5 +<!--
     1.6 +
     1.7 +    Back 2 Browser Bytecode Translator
     1.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     1.9 +
    1.10 +    This program is free software: you can redistribute it and/or modify
    1.11 +    it under the terms of the GNU General Public License as published by
    1.12 +    the Free Software Foundation, version 2 of the License.
    1.13 +
    1.14 +    This program is distributed in the hope that it will be useful,
    1.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.17 +    GNU General Public License for more details.
    1.18 +
    1.19 +    You should have received a copy of the GNU General Public License
    1.20 +    along with this program. Look for COPYING file in the top folder.
    1.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
    1.22 +
    1.23 +-->
    1.24 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    1.25 +  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
    1.26 +  
    1.27 +  <id>bck2brwsr</id>
    1.28 +  <formats>
    1.29 +      <format>zip</format>
    1.30 +  </formats>
    1.31 +  <baseDirectory>public_html</baseDirectory>
    1.32 +  <dependencySets>
    1.33 +    <dependencySet>
    1.34 +        <useProjectArtifact>false</useProjectArtifact>
    1.35 +        <scope>runtime</scope>
    1.36 +        <outputDirectory>lib</outputDirectory>
    1.37 +        <includes>
    1.38 +            <include>*:jar</include>
    1.39 +            <include>*:rt</include>
    1.40 +        </includes>
    1.41 +    </dependencySet>
    1.42 +    <dependencySet>
    1.43 +        <useProjectArtifact>false</useProjectArtifact>
    1.44 +        <scope>provided</scope>
    1.45 +        <includes>
    1.46 +            <include>*:js</include>
    1.47 +        </includes>
    1.48 +        <unpack>true</unpack>
    1.49 +        <outputDirectory>/</outputDirectory>
    1.50 +    </dependencySet>
    1.51 +  </dependencySets> 
    1.52 +  <files>
    1.53 +    <file>
    1.54 +      <source>${project.build.directory}/${project.build.finalName}.jar</source>
    1.55 +      <outputDirectory>/</outputDirectory>
    1.56 +    </file>
    1.57 +    <file>
    1.58 +      <source>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/twitter/index.html</source>
    1.59 +      <outputDirectory>/</outputDirectory>
    1.60 +      <destName>index.html</destName>
    1.61 +    </file>
    1.62 +    <file>
    1.63 +      <source>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/twitter/twitterExample.css</source>
    1.64 +      <outputDirectory>/</outputDirectory>
    1.65 +      <destName>twitterExample.css</destName>
    1.66 +    </file>
    1.67 +    <file>
    1.68 +      <source>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/twitter/twitterApi.js</source>
    1.69 +      <outputDirectory>/</outputDirectory>
    1.70 +      <destName>twitterApi.js</destName>
    1.71 +    </file>
    1.72 +  </files>
    1.73 +
    1.74 +</assembly>
    1.75 \ No newline at end of file
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/javaquery/demo-twitter/nb-configuration.xml	Thu Apr 04 13:12:17 2013 +0200
     2.3 @@ -0,0 +1,37 @@
     2.4 +<?xml version="1.0" encoding="UTF-8"?>
     2.5 +<!--
     2.6 +
     2.7 +    Back 2 Browser Bytecode Translator
     2.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     2.9 +
    2.10 +    This program is free software: you can redistribute it and/or modify
    2.11 +    it under the terms of the GNU General Public License as published by
    2.12 +    the Free Software Foundation, version 2 of the License.
    2.13 +
    2.14 +    This program is distributed in the hope that it will be useful,
    2.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.17 +    GNU General Public License for more details.
    2.18 +
    2.19 +    You should have received a copy of the GNU General Public License
    2.20 +    along with this program. Look for COPYING file in the top folder.
    2.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
    2.22 +
    2.23 +-->
    2.24 +<project-shared-configuration>
    2.25 +    <!--
    2.26 +This file contains additional configuration written by modules in the NetBeans IDE.
    2.27 +The configuration is intended to be shared among all the users of project and
    2.28 +therefore it is assumed to be part of version control checkout.
    2.29 +Without this configuration present, some functionality in the IDE may be limited or fail altogether.
    2.30 +-->
    2.31 +    <properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
    2.32 +        <!--
    2.33 +Properties that influence various parts of the IDE, especially code formatting and the like. 
    2.34 +You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
    2.35 +That way multiple projects can share the same settings (useful for formatting rules for example).
    2.36 +Any value defined here will override the pom.xml file value but is only applicable to the current project.
    2.37 +-->
    2.38 +        <netbeans.compile.on.save>none</netbeans.compile.on.save>
    2.39 +    </properties>
    2.40 +</project-shared-configuration>
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/javaquery/demo-twitter/nbactions.xml	Thu Apr 04 13:12:17 2013 +0200
     3.3 @@ -0,0 +1,29 @@
     3.4 +<?xml version="1.0" encoding="UTF-8"?>
     3.5 +<!--
     3.6 +
     3.7 +    Back 2 Browser Bytecode Translator
     3.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     3.9 +
    3.10 +    This program is free software: you can redistribute it and/or modify
    3.11 +    it under the terms of the GNU General Public License as published by
    3.12 +    the Free Software Foundation, version 2 of the License.
    3.13 +
    3.14 +    This program is distributed in the hope that it will be useful,
    3.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.17 +    GNU General Public License for more details.
    3.18 +
    3.19 +    You should have received a copy of the GNU General Public License
    3.20 +    along with this program. Look for COPYING file in the top folder.
    3.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
    3.22 +
    3.23 +-->
    3.24 +<actions>
    3.25 +    <action>
    3.26 +        <actionName>run</actionName>
    3.27 +        <goals>
    3.28 +            <goal>process-classes</goal>
    3.29 +            <goal>org.apidesign.bck2brwsr:mojo:0.6-SNAPSHOT:brwsr</goal>
    3.30 +        </goals>
    3.31 +    </action>
    3.32 +</actions>
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/javaquery/demo-twitter/pom.xml	Thu Apr 04 13:12:17 2013 +0200
     4.3 @@ -0,0 +1,141 @@
     4.4 +<?xml version="1.0" encoding="UTF-8"?>
     4.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     4.6 +  <modelVersion>4.0.0</modelVersion>
     4.7 +  <parent>
     4.8 +    <artifactId>javaquery</artifactId>
     4.9 +    <groupId>org.apidesign.bck2brwsr</groupId>
    4.10 +    <version>0.6-SNAPSHOT</version>
    4.11 +  </parent>
    4.12 +
    4.13 +  <groupId>org.apidesign.bck2brwsr</groupId>
    4.14 +  <artifactId>demo-twitter</artifactId>
    4.15 +  <version>0.6-SNAPSHOT</version>
    4.16 +  <packaging>jar</packaging>
    4.17 +
    4.18 +  <name>Bck2Brwsr's Twttr</name>
    4.19 +  <description>
    4.20 +      Rewrite of knockoutjs example to use model written in Java and
    4.21 +      execute using Bck2Brwsr virtual machine.
    4.22 +  </description>
    4.23 +
    4.24 +  <repositories>
    4.25 +      <repository>
    4.26 +          <id>java.net</id>
    4.27 +          <name>Java.net</name>
    4.28 +          <url>https://maven.java.net/content/repositories/releases/</url>
    4.29 +          <snapshots>
    4.30 +          </snapshots>
    4.31 +      </repository>
    4.32 +      <repository>
    4.33 +          <id>netbeans</id>
    4.34 +          <name>NetBeans</name>
    4.35 +          <url>http://bits.netbeans.org/maven2/</url>
    4.36 +      </repository>
    4.37 +  </repositories>
    4.38 +  <pluginRepositories>
    4.39 +      <pluginRepository>
    4.40 +          <id>java.net</id>
    4.41 +          <name>Java.net</name>
    4.42 +          <url>https://maven.java.net/content/repositories/releases/</url>
    4.43 +          <snapshots>
    4.44 +          </snapshots>
    4.45 +      </pluginRepository>
    4.46 +  </pluginRepositories>
    4.47 +
    4.48 +  <properties>
    4.49 +    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    4.50 +  </properties>
    4.51 +  <build>
    4.52 +      <plugins>
    4.53 +            <plugin>
    4.54 +                <groupId>org.apidesign.bck2brwsr</groupId>
    4.55 +                <artifactId>mojo</artifactId>
    4.56 +                <version>0.6-SNAPSHOT</version>
    4.57 +                <executions>
    4.58 +                    <execution>
    4.59 +                        <goals>
    4.60 +                            <goal>brwsr</goal>
    4.61 +                        </goals>
    4.62 +                    </execution>
    4.63 +                </executions>
    4.64 +                <configuration>
    4.65 +                    <startpage>org/apidesign/bck2brwsr/demo/twitter/index.html</startpage>
    4.66 +                </configuration>
    4.67 +            </plugin>
    4.68 +         <plugin>
    4.69 +            <groupId>org.apache.maven.plugins</groupId>
    4.70 +            <artifactId>maven-compiler-plugin</artifactId>
    4.71 +            <version>2.3.2</version>
    4.72 +            <configuration>
    4.73 +               <source>1.7</source>
    4.74 +               <target>1.7</target>
    4.75 +            </configuration>
    4.76 +         </plugin>
    4.77 +         <plugin>
    4.78 +             <groupId>org.apache.maven.plugins</groupId>
    4.79 +             <artifactId>maven-jar-plugin</artifactId>
    4.80 +             <version>2.4</version>
    4.81 +             <configuration>
    4.82 +                 <archive>
    4.83 +                     <manifest>
    4.84 +                         <addClasspath>true</addClasspath>
    4.85 +                         <classpathPrefix>lib/</classpathPrefix>
    4.86 +                     </manifest>
    4.87 +                 </archive>
    4.88 +             </configuration>
    4.89 +         </plugin>
    4.90 +         <plugin>
    4.91 +             <artifactId>maven-assembly-plugin</artifactId>
    4.92 +             <version>2.4</version>
    4.93 +             <executions>
    4.94 +                 <execution>
    4.95 +                     <id>distro-assembly</id>
    4.96 +                     <phase>package</phase>
    4.97 +                     <goals>
    4.98 +                         <goal>single</goal>
    4.99 +                     </goals>
   4.100 +                     <configuration>
   4.101 +                         <descriptors>
   4.102 +                             <descriptor>bck2brwsr-assembly.xml</descriptor>
   4.103 +                         </descriptors>
   4.104 +                     </configuration>
   4.105 +                 </execution>
   4.106 +             </executions>                
   4.107 +         </plugin>      
   4.108 +      </plugins>
   4.109 +  </build>
   4.110 +
   4.111 +  <dependencies>
   4.112 +    <dependency>
   4.113 +      <groupId>org.apidesign.bck2brwsr</groupId>
   4.114 +      <artifactId>emul</artifactId>
   4.115 +      <version>0.6-SNAPSHOT</version>
   4.116 +      <classifier>rt</classifier>
   4.117 +    </dependency>
   4.118 +    <dependency>
   4.119 +      <groupId>org.apidesign.bck2brwsr</groupId>
   4.120 +      <artifactId>javaquery.api</artifactId>
   4.121 +      <version>0.6-SNAPSHOT</version>
   4.122 +    </dependency>
   4.123 +    <dependency>
   4.124 +      <groupId>org.testng</groupId>
   4.125 +      <artifactId>testng</artifactId>
   4.126 +      <version>6.5.2</version>
   4.127 +      <scope>test</scope>
   4.128 +    </dependency>
   4.129 +    <dependency>
   4.130 +      <groupId>org.apidesign.bck2brwsr</groupId>
   4.131 +      <artifactId>vm4brwsr</artifactId>
   4.132 +      <classifier>js</classifier>
   4.133 +      <type>zip</type>
   4.134 +      <version>0.6-SNAPSHOT</version>
   4.135 +      <scope>provided</scope>
   4.136 +    </dependency>
   4.137 +    <dependency>
   4.138 +      <groupId>org.apidesign.bck2brwsr</groupId>
   4.139 +      <artifactId>vmtest</artifactId>
   4.140 +      <version>0.6-SNAPSHOT</version>
   4.141 +      <scope>test</scope>
   4.142 +    </dependency>
   4.143 +  </dependencies>
   4.144 +</project>
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/javaquery/demo-twitter/src/main/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClient.java	Thu Apr 04 13:12:17 2013 +0200
     5.3 @@ -0,0 +1,137 @@
     5.4 +/**
     5.5 + * Back 2 Browser Bytecode Translator
     5.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     5.7 + *
     5.8 + * This program is free software: you can redistribute it and/or modify
     5.9 + * it under the terms of the GNU General Public License as published by
    5.10 + * the Free Software Foundation, version 2 of the License.
    5.11 + *
    5.12 + * This program is distributed in the hope that it will be useful,
    5.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.15 + * GNU General Public License for more details.
    5.16 + *
    5.17 + * You should have received a copy of the GNU General Public License
    5.18 + * along with this program. Look for COPYING file in the top folder.
    5.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    5.20 + */
    5.21 +package org.apidesign.bck2brwsr.demo.twitter;
    5.22 +
    5.23 +import java.util.Arrays;
    5.24 +import java.util.List;
    5.25 +import org.apidesign.bck2brwsr.htmlpage.api.*;
    5.26 +import org.apidesign.bck2brwsr.htmlpage.api.Page;
    5.27 +import org.apidesign.bck2brwsr.htmlpage.api.Property;
    5.28 +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
    5.29 +
    5.30 +/** Controller class for access to Twitter.
    5.31 + * 
    5.32 + * @author Jaroslav Tulach
    5.33 + */
    5.34 +@Page(xhtml="index.html", className="TwitterModel", properties={
    5.35 +    @Property(name="savedLists", type=TwitterClient.Twttrs.class, array = true),
    5.36 +    @Property(name="activeTweetersName", type=String.class),
    5.37 +    @Property(name="modifiedList", type=TwitterClient.Twttrs.class),
    5.38 +    @Property(name="userNameToAdd", type=String.class),
    5.39 +    @Property(name="currentTweets", type=String.class, array = true)
    5.40 +})
    5.41 +public class TwitterClient {
    5.42 +    @Model(className = "Tweeters", properties = {
    5.43 +        @Property(name="name", type = String.class),
    5.44 +        @Property(name="userNames", type = String.class, array = true)
    5.45 +    })
    5.46 +    static class Twttrs {
    5.47 +    }
    5.48 +    
    5.49 +    private static Tweeters tweeters(String listName, String... userNames) {
    5.50 +        Tweeters t = new Tweeters();
    5.51 +        t.setName(listName);
    5.52 +        t.getUserNames().addAll(Arrays.asList(userNames));
    5.53 +        return t;
    5.54 +    }
    5.55 +    
    5.56 +    static {
    5.57 +        final TwitterModel model = new TwitterModel();
    5.58 +        final List<Tweeters> svdLst = model.getSavedLists();
    5.59 +        svdLst.add(tweeters("API Design", "JaroslavTulach"));
    5.60 +        svdLst.add(tweeters("Celebrities", "JohnCleese", "MCHammer", "StephenFry", "algore", "StevenSanderson"));
    5.61 +        svdLst.add(tweeters("Microsoft people", "BillGates", "shanselman", "ScottGu"));
    5.62 +        svdLst.add(tweeters("NetBeans", "GeertjanW","monacotoni", "NetBeans"));
    5.63 +        svdLst.add(tweeters("Tech pundits", "Scobleizer", "LeoLaporte", "techcrunch", "BoingBoing", "timoreilly", "codinghorror"));
    5.64 +
    5.65 +        model.setActiveTweetersName("NetBeans");
    5.66 +        
    5.67 +        model.applyBindings();
    5.68 +    }
    5.69 +    
    5.70 +    @ComputedProperty
    5.71 +    static Tweeters activeTweeters(String activeTweetersName, List<Tweeters> savedLists, Tweeters modifiedList) {
    5.72 +        if (modifiedList != null && modifiedList.getName() != null) {
    5.73 +            if (modifiedList.getName().equals(activeTweetersName)) {
    5.74 +                return modifiedList;
    5.75 +            } else {
    5.76 +                modifiedList.setName(null);
    5.77 +            }
    5.78 +        }
    5.79 +        return findByName(savedLists, activeTweetersName);
    5.80 +    }
    5.81 +    
    5.82 +    @ComputedProperty
    5.83 +    static boolean hasUnsavedChanges(Tweeters modifiedList) {
    5.84 +        return modifiedList != null;
    5.85 +    }
    5.86 +    
    5.87 +    @ComputedProperty
    5.88 +    static boolean userNameToAddIsValid(String userNameToAdd, String activeTweetersName, List<Tweeters> savedLists, Tweeters modifiedList) {
    5.89 +        Tweeters editingList = activeTweeters(activeTweetersName, savedLists, modifiedList);
    5.90 +        return editingList != null && userNameToAdd != null && 
    5.91 +            userNameToAdd.matches("[a-zA-Z0-9_]{1,15}") &&
    5.92 +            !editingList.getUserNames().contains(userNameToAdd);
    5.93 +    }
    5.94 +    
    5.95 +    @OnFunction
    5.96 +    static void deleteList(TwitterModel model) {
    5.97 +        final List<Tweeters> sl = model.getSavedLists();
    5.98 +        sl.remove(model.getActiveTweeters());
    5.99 +        if (sl.isEmpty()) {
   5.100 +            final Tweeters t = new Tweeters();
   5.101 +            t.setName("New");
   5.102 +            sl.add(t);
   5.103 +        }
   5.104 +        model.setActiveTweetersName(sl.get(0).getName());
   5.105 +    }
   5.106 +    
   5.107 +    @OnFunction
   5.108 +    static void saveChanges(TwitterModel model) {
   5.109 +        Tweeters t = findByName(model.getSavedLists(), model.getActiveTweetersName());
   5.110 +        int indx = model.getSavedLists().indexOf(t);
   5.111 +        assert indx != -1;
   5.112 +        model.getSavedLists().set(indx, model.getModifiedList());
   5.113 +        model.setModifiedList(null);
   5.114 +    }
   5.115 +    
   5.116 +    @OnFunction
   5.117 +    static void addUser(TwitterModel model) {
   5.118 +        String n = model.getUserNameToAdd();
   5.119 +        findModifiedList(model).getUserNames().add(n);
   5.120 +    }
   5.121 +    @OnFunction
   5.122 +    static void removeUser(String data, TwitterModel model) {
   5.123 +        findModifiedList(model).getUserNames().remove(data);
   5.124 +    }
   5.125 +    
   5.126 +    private static Tweeters findModifiedList(TwitterModel model) {
   5.127 +        if (model.getModifiedList() == null || model.getModifiedList().getName() == null) {
   5.128 +            model.setModifiedList(model.getActiveTweeters().clone());
   5.129 +        }
   5.130 +        return model.getModifiedList();
   5.131 +    }
   5.132 +    private static Tweeters findByName(List<Tweeters> list, String name) {
   5.133 +        for (Tweeters l : list) {
   5.134 +            if (l.getName() != null && l.getName().equals(name)) {
   5.135 +                return l;
   5.136 +            }
   5.137 +        }
   5.138 +        return list.isEmpty() ? null : list.get(0);
   5.139 +    }
   5.140 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/javaquery/demo-twitter/src/main/resources/org/apidesign/bck2brwsr/demo/twitter/index.html	Thu Apr 04 13:12:17 2013 +0200
     6.3 @@ -0,0 +1,99 @@
     6.4 +<?xml version="1.0" encoding="UTF-8"?>
     6.5 +<!--
     6.6 +
     6.7 +    Back 2 Browser Bytecode Translator
     6.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     6.9 +
    6.10 +    This program is free software: you can redistribute it and/or modify
    6.11 +    it under the terms of the GNU General Public License as published by
    6.12 +    the Free Software Foundation, version 2 of the License.
    6.13 +
    6.14 +    This program is distributed in the hope that it will be useful,
    6.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.17 +    GNU General Public License for more details.
    6.18 +
    6.19 +    You should have received a copy of the GNU General Public License
    6.20 +    along with this program. Look for COPYING file in the top folder.
    6.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
    6.22 +
    6.23 +-->
    6.24 +
    6.25 +<!--
    6.26 +    Copied from knockout.js Twitter example:
    6.27 +    http://knockoutjs.com/examples/twitter.html
    6.28 +-->
    6.29 +
    6.30 +<!DOCTYPE html>
    6.31 +<html xmlns="http://www.w3.org/1999/xhtml">
    6.32 +    <head>
    6.33 +        <title>Bck2Brwsr's Twitter</title>
    6.34 +    </head>
    6.35 +    <body>
    6.36 +        <link href='twitterExample.css' rel='Stylesheet' ></link>
    6.37 +        
    6.38 +        <script src='twitterApi.js' type='text/javascript'> </script>
    6.39 +        
    6.40 +        <style type='text/css'>
    6.41 +           .liveExample select { height: 1.7em; }
    6.42 +           .liveExample button { height: 2em; }
    6.43 +        </style>
    6.44 +        
    6.45 +        
    6.46 +        <h2>Bck2Brwsr's Twitter</h2>
    6.47 +        
    6.48 +        <p>
    6.49 +        This code based on original <a href="http://knockoutjs.com/examples/twitter.html">knockout.js Twitter example</a> and
    6.50 +        uses almost unmodified HTML code. It just changes the model. It 
    6.51 +        is written in Java language and it is executed using <a href="http://bck2brwsr.apidesign.org">Bck2Brwsr</a>
    6.52 +        virtual machine.
    6.53 +        </p>
    6.54 +        
    6.55 +        <div class='liveExample'>
    6.56 +            <div class='configuration'>
    6.57 +                <div class='listChooser'>
    6.58 +                    <button data-bind='click: deleteList, enable: activeTweeters.name'>Delete</button>
    6.59 +                    <button data-bind='click: saveChanges, enable: hasUnsavedChanges'>Save</button> 
    6.60 +                    <select data-bind='options: savedLists, optionsValue: "name", value: activeTweetersName'> </select>
    6.61 +                </div>
    6.62 +
    6.63 +                <p>Currently viewing <span data-bind='text: activeTweeters().userNames().length'> </span> user(s):</p>
    6.64 +                <div class='currentUsers' data-bind='with: activeTweeters'>
    6.65 +                    <ul data-bind='foreach: userNames'>
    6.66 +                        <li>
    6.67 +                            <button data-bind='click: $root.removeUser'>Remove</button>
    6.68 +                            <div data-bind='text: $data'> </div>
    6.69 +                        </li>
    6.70 +                    </ul>
    6.71 +                </div>
    6.72 +
    6.73 +                <form data-bind='submit: addUser'>
    6.74 +                    <label>Add user:</label>
    6.75 +                    <input data-bind='value: userNameToAdd, valueUpdate: "keyup", css: { invalid: !userNameToAddIsValid() }' />
    6.76 +                    <button data-bind='enable: userNameToAddIsValid' type='submit'>Add</button>
    6.77 +                </form>
    6.78 +            </div>
    6.79 +            <div class='tweets'>
    6.80 +                <div class='loadingIndicator'>Loading...</div>
    6.81 +                <table data-bind='foreach: currentTweets' width='100%'>
    6.82 +                    <tr>
    6.83 +                        <td><img data-bind='attr: { src: profile_image_url }' /></td>
    6.84 +                        <td>
    6.85 +                            <a href='http://twitter.com/${ from_user }' class='twitterUser' data-bind='attr: { href: "http://twitter.com/" + from_user }, text: from_user'> </a>
    6.86 +                            <span data-bind='text: text'> </span>
    6.87 +                            <div class='tweetInfo' data-bind='text: created_at'> </div>
    6.88 +                        </td>
    6.89 +                    </tr>
    6.90 +                </table>
    6.91 +            </div>
    6.92 +        </div>
    6.93 +        
    6.94 +        <script src="bck2brwsr.js"></script>
    6.95 +        <script type="text/javascript">
    6.96 +            var vm = bck2brwsr('demo-twitter-0.6-SNAPSHOT.jar');
    6.97 +            vm.loadClass('org.apidesign.bck2brwsr.demo.twitter.TwitterClient');
    6.98 +        </script>
    6.99 +
   6.100 +
   6.101 +    </body>
   6.102 +</html>
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/javaquery/demo-twitter/src/main/resources/org/apidesign/bck2brwsr/demo/twitter/twitterExample.css	Thu Apr 04 13:12:17 2013 +0200
     7.3 @@ -0,0 +1,50 @@
     7.4 +/**
     7.5 + * Back 2 Browser Bytecode Translator
     7.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     7.7 + *
     7.8 + * This program is free software: you can redistribute it and/or modify
     7.9 + * it under the terms of the GNU General Public License as published by
    7.10 + * the Free Software Foundation, version 2 of the License.
    7.11 + *
    7.12 + * This program is distributed in the hope that it will be useful,
    7.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.15 + * GNU General Public License for more details.
    7.16 + *
    7.17 + * You should have received a copy of the GNU General Public License
    7.18 + * along with this program. Look for COPYING file in the top folder.
    7.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    7.20 + */
    7.21 +
    7.22 +/*
    7.23 +    Copied from knockout.js Twitter example:
    7.24 +    http://knockoutjs.com/examples/twitter.html
    7.25 +*/
    7.26 +
    7.27 +.configuration, .tweets, .tweets td { font-family: Verdana; font-size: 13px; }
    7.28 +.configuration { background-color: #DEDEDE; border: 2px solid gray; float:left; height: 40em; width: 40%; padding: 0.5em; border-right-width:0; }
    7.29 +.tweets { width: 55%; border: 2px solid gray; height: 40em; overflow: scroll; overflow-x: hidden; background-color: Black; color: White; padding: 0.5em; position: relative; }
    7.30 +.tweets table { border-width: 0;}
    7.31 +.tweets tr { vertical-align: top; }
    7.32 +.tweets td { padding: 0.4em 0.3em 1em 0.4em; border-width: 0; }
    7.33 +.tweets img { width: 4em; }
    7.34 +.tweetInfo { color: Gray; font-size: 0.9em; }
    7.35 +.twitterUser { color: #77AAFF; text-decoration: none; font-size: 1.1em; font-weight: bold; }
    7.36 +input.invalid { border: 1px solid red !important; background-color: #FFAAAA !important; }
    7.37 +
    7.38 +.listChooser select, .listChooser button { vertical-align:top; }
    7.39 +.listChooser select { width: 60%; font-size:1.2em; height:1.4em; }
    7.40 +.listChooser button { width: 19%; height:1.68em; float:right; }
    7.41 +
    7.42 +.currentUsers { height: 28em; overflow-y: auto; overflow-x: hidden; }
    7.43 +.currentUsers button { float: right; height: 2.5em; margin: 0.1em; padding-left: 1em; padding-right: 1em; }
    7.44 +.currentUsers ul, .configuration li { list-style: none; margin: 0; padding: 0 }
    7.45 +.currentUsers li { height: 2.4em; font-size: 1.2em; background-color: #A7D0E3; border: 1px solid gray; margin-bottom: 0.3em; -webkit-border-radius: 5px; -moz-border-radius: 5px; -webkit-box-shadow: 0 0.2em 0.5em gray; -moz-box-shadow: 0 0.2em 0.5em gray; }
    7.46 +.currentUsers li div { padding: 0.6em; }
    7.47 +.currentUsers li:hover { background-color: #EEC; }
    7.48 +
    7.49 +.configuration form label { width: 25%; display: inline-block; text-align:right; overflow: hidden; }
    7.50 +.configuration form input { width:40%; font-size: 1.3em; border:1px solid silver; background-color: White; padding: 0.1em; }
    7.51 +.configuration form button { width: 20%; margin-left: 0.3em; height: 2em; }
    7.52 +
    7.53 +.loadingIndicator { position: absolute; top: 0.1em; left: 0.1em; font: 0.8em Arial; background-color: #229; color: White; padding: 0.2em 0.5em 0.2em 0.5em; display: none; }
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/javaquery/demo-twitter/src/test/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClientTest.java	Thu Apr 04 13:12:17 2013 +0200
     8.3 @@ -0,0 +1,66 @@
     8.4 +/**
     8.5 + * Back 2 Browser Bytecode Translator
     8.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     8.7 + *
     8.8 + * This program is free software: you can redistribute it and/or modify
     8.9 + * it under the terms of the GNU General Public License as published by
    8.10 + * the Free Software Foundation, version 2 of the License.
    8.11 + *
    8.12 + * This program is distributed in the hope that it will be useful,
    8.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.15 + * GNU General Public License for more details.
    8.16 + *
    8.17 + * You should have received a copy of the GNU General Public License
    8.18 + * along with this program. Look for COPYING file in the top folder.
    8.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    8.20 + */
    8.21 +package org.apidesign.bck2brwsr.demo.twitter;
    8.22 +
    8.23 +import static org.testng.Assert.*;
    8.24 +import org.testng.annotations.BeforeMethod;
    8.25 +import org.testng.annotations.Test;
    8.26 +
    8.27 +/** We can unit test the TwitterModel smoothly.
    8.28 + *
    8.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    8.30 + */
    8.31 +public class TwitterClientTest {
    8.32 +    private TwitterModel model;
    8.33 +    
    8.34 +
    8.35 +    @BeforeMethod
    8.36 +    public void initModel() {
    8.37 +        model = new TwitterModel().applyBindings();
    8.38 +    }
    8.39 +
    8.40 +    @Test public void testIsValidToAdd() {
    8.41 +        model.setUserNameToAdd("Joe");
    8.42 +        Tweeters t = new Tweeters();
    8.43 +        t.setName("test");
    8.44 +        model.getSavedLists().add(t);
    8.45 +        model.setActiveTweetersName("test");
    8.46 +        
    8.47 +        assertTrue(model.isUserNameToAddIsValid(), "Joe is OK");
    8.48 +        TwitterClient.addUser(model);
    8.49 +        assertFalse(model.isUserNameToAddIsValid(), "Can't add Joe for the 2nd time");
    8.50 +        assertEquals(t.getUserNames().size(), 0, "Original tweeters list remains empty");
    8.51 +        
    8.52 +        Tweeters mod = model.getModifiedList();
    8.53 +        assertNotNull(mod, "Modified list is not filled in");
    8.54 +        assertTrue(model.isHasUnsavedChanges(), "We have modifications");
    8.55 +        assertEquals(mod.getUserNames().size(), 1, "One element in the list");
    8.56 +        assertEquals(mod.getUserNames().get(0), "Joe", "Its name is Joe");
    8.57 +        
    8.58 +        assertSame(model.getActiveTweeters(), mod, "Editing list is the modified one");
    8.59 +        
    8.60 +        TwitterClient.saveChanges(model);
    8.61 +        assertFalse(model.isHasUnsavedChanges(), "Does not have anything to save");
    8.62 +        assertNull(model.getModifiedList(), "No list modified");
    8.63 +        
    8.64 +        assertSame(model.getActiveTweeters(), mod, "Still editing the old modified one");
    8.65 +        
    8.66 +        assertFalse(model.getSavedLists().contains(t), "No longer contains old list");
    8.67 +    }
    8.68 +    
    8.69 +}
     9.1 --- a/javaquery/pom.xml	Thu Apr 04 13:08:26 2013 +0200
     9.2 +++ b/javaquery/pom.xml	Thu Apr 04 13:12:17 2013 +0200
     9.3 @@ -15,5 +15,6 @@
     9.4          <module>api</module>
     9.5          <module>demo-calculator</module>
     9.6          <module>demo-calculator-dynamic</module>
     9.7 -    </modules>
     9.8 -</project>
     9.9 +    <module>demo-twitter</module>
    9.10 +  </modules>
    9.11 +</project>
    9.12 \ No newline at end of file