Search Results

Search found 8941 results on 358 pages for 'src jar'.

Page 125/358 | < Previous Page | 121 122 123 124 125 126 127 128 129 130 131 132  | Next Page >

  • Using CookieJar in Python to log in to a website from "Google App Engine". What's wrong here?

    - by brilliant
    Hello everybody, I've been trying to find a python code that would log in to my mail box on yahoo.com from "Google App Engine" . Here (click here to see that page) I was given this code: import urllib, urllib2, cookielib url = "https://login.yahoo.com/config/login?" form_data = {'login' : 'my-login-here', 'passwd' : 'my-password-here'} jar = cookielib.CookieJar() opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(jar)) form_data = urllib.urlencode(form_data) # data returned from this pages contains redirection resp = opener.open(url, form_data) # yahoo redirects to http://my.yahoo.com, so lets go there instead resp = opener.open('http://mail.yahoo.com') print resp.read() The author of this script looked into HTML script of yahoo log-in form and came up with this script. That log-in form contains two fields, one for users' Yahoo! ID and another one is for users' password. Here is how HTML code of that page for both of those fields looks like: User ID field: <input type="text" maxlength="96" class="yreg_ipt" size="17" value="" id="username" name="login"> Password field: <input type="password" maxlength="64" class="yreg_ipt" size="17" value="" id="passwd" name="passwd"> However, when I uploaded this code to Google App Engine I discovered that this log-in form keeps coming back to me, which, I assume, means that logging-in process didn't succeed. Why is it so?

    Read the article

  • Using CookieJar in Python to log in to a website from "Google App Engine". What's wrong here?

    - by brilliant
    Hello everybody, I've been trying to find a python code that would log in to my mail box on yahoo.com from "Google App Engine" . Here (click here to see that page) I was given this code: import urllib, urllib2, cookielib url = "https://login.yahoo.com/config/login?" form_data = {'login' : 'my-login-here', 'passwd' : 'my-password-here'} jar = cookielib.CookieJar() opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(jar)) form_data = urllib.urlencode(form_data) # data returned from this pages contains redirection resp = opener.open(url, form_data) # yahoo redirects to http://my.yahoo.com, so lets go there instead resp = opener.open('http://mail.yahoo.com') print resp.read() The author of this script looked into HTML script of yahoo log-in form and came up with this script. That log-in form contains two fields, one for users' Yahoo! ID and another one is for users' password. Here is how HTML code of that page for both of those fields looks like: User ID field: <input type="text" maxlength="96" class="yreg_ipt" size="17" value="" id="username" name="login"> Password field: <input type="password" maxlength="64" class="yreg_ipt" size="17" value="" id="passwd" name="passwd"> However, when I uploaded this code to Google App Engine I discovered that this log-in form keeps coming back to me, which, I assume, means that logging-in process didn't succeed. Why is it so?

    Read the article

  • I just need one dependent module , but don't need its dependencies (Maven)

    - by smallufo
    In my project , there is a spring XML config that utilizes ehcache to cache method returns. xml snippet : http://www.springmodules.org/schema/ehcache http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd <ehcache:config configLocation="classpath:ehcache.xml"/> <ehcache:proxy id="explainRetriever" refId="explainRetrieverImpl"> <ehcache:caching methodName="get*" cacheName="explainCache"/> </ehcache:proxy> but in runtime , server complains it cannot find definitions of http://www.springmodules.org/schema/ehcache , I know I have to add "spring-modules-cache.jar" to WEB-INF/lib directory. But my project is maintained by maven , if I add "spring-modules-cache" to the runtime dependency , it will bring a lot of dependencies to my WAR file , filling my WAR with a lot of unnecessary jars. I just need one declaration in it , not all of its dependencies ... Is there any way to tell maven not to include its dependencies to the project ? Or ... another way , when packaging WAR , just copy another prepared spring-modules-cache.jar to WEB-INF/lib , how to do this ? Thanks !

    Read the article

  • Is it possible to Kick off a java process under Windows Service with C#?

    - by Wing C. Chen
    I would like to wrap a java program into a windows service with C# using System.ServiceProcess.ServiceBase. So I came up with the following code: /// <summary> /// The main entry point for the application. /// </summary> static void Main() { System.ServiceProcess.ServiceBase.Run(new JavaLauncher()); } protected override void OnStart(string[] args) { Thread _thread; _thread = new Thread(StartService); _thread.Start(); base.OnStart(args); } protected override void OnStop() { Thread _thread; _thread = new Thread(StopService); _thread.Start(); base.OnStop(); } static public void StartService() { System.Diagnostics.Process proc = new System.Diagnostics.Process(); proc.EnableRaisingEvents = false; proc.StartInfo.FileName = "javaw"; proc.StartInfo.Arguments = config.generateLaunchCommand(); proc.Start(); } static public void StopService() { System.Diagnostics.Process proc = new System.Diagnostics.Process(); proc.EnableRaisingEvents = false; proc.StartInfo.FileName = "javaw"; proc.StartInfo.Arguments = "-jar stop.jar"; proc.Start(); } Firstly I had to use Threads in OnStart and OnStop. If not, an exception occurs complaining that the service is terminated because of doing nothing. Secondly, the service can be hooked up to windows smoothly. However, the service terminates a short while after it is started. I looked into the process monitor, only the service process stays alive for that short while, the javaw process never showed up, however. Is there anyone who knows how this can be fixed? It works fine in an ordinary console environment. I think it has something to do with Windows service.

    Read the article

  • Why can't I open a JBoss vfs:/ URL?

    - by skiphoppy
    We are upgrading our application from JBoss 4 to JBoss 6. A couple of pieces of our application get delivered to the client in an unusual way: jars are looked up inside of our application and sent to the client from a servlet, where the client extracts them in order to run certain support functions. In JBoss 4 we would look these jars up with the classloader and find a jar:// URL which would be used to read the jar and send its contents to the client. In JBoss 6 when we perform the lookup we get a vfs:/ URL. I understand that this is from the org.jboss.vfs package. Unfortunately when I call openStream() on this URL and read from the stream, I immediately get an EOF (read() returns -1). What gives? Why can't I read the resource this URL refers to? I've tried trying to access the underlying VFS packages to open the file through the JBoss VFS API, but most of the API appears to be private, and I couldn't find a routine to translate from a vfs:/ URL to a VFS VirtualFile object, so I couldn't get anywhere. I can try to find the file on disk within JBoss, but that approach sounds very failure prone on upgrade. Our old approach was to use Java Web Start to distribute the jars to the client and then look them up within Java Web Start's cache to extract them. But that broke on every minor upgrade of Java because the layout of the cache changed.

    Read the article

  • Compilig + testing an Android library with the JDK?

    - by Jarle Hansen
    Hi all, I am creating a library for Android that others can include in their own project. So far I have been working on it as a normal Java project with JDK 1.6 setup as system library. This works just fine in Eclipse when I add the android.jar. The issue comes when I try to my build script. I am running Gradle and doing a normal compile and test build cycle. My thoughts were that it does not matter if I compile it with a normal JDK, since this is not a standalone application. The benefits by creating a normal Java project is that Gradle does support this much better. My project also does not contain any UI at all. However, the problem is that of course android.jar and the JDK contains lots of the same classes and I think that this is what messes up my build script. Everything crashes when running the tests (the tests are in the same project under src/test/java). My question is, how should I create this project that is meant to be included in Android projects as a third party library? Should I create it as an Android project in Eclipse even though I am only creating a library that does not use any of the UI features? Also, should the tests be in a separate project? Thanks for all responses!

    Read the article

  • Capabilities & Linux & Java

    - by Marek Jelen
    Hi, I am experimenting with linux capabilities for java application ... I do not want to add capabilities to interpreter (JVM), so I tried to write simple wrapper (with debugging information printed to stdout): #include <stdio.h> #include <stdlib.h> #include <sys/capability.h> #include <unistd.h> int main(int argc, char *argv[]){ cap_t cap = cap_get_proc(); if (!cap) { perror("cap_get_proc"); exit(1); } printf("%s: running with caps %s\n", argv[0], cap_to_text(cap, NULL)); return execlp("/usr/bin/java", "-server", "-jar", "project.jar", (char *)NULL); } This way, I can se that the capability is set for this execucatable: ./runner: running with caps = cap_net_bind_service+p And getcap shows runner = cap_net_bind_service+ip I have the capability set to be inheritable, so there should be no problem. However java still don't want to bind to privileged ports :-( I am getting this error: sun/nio/ch/Net.java:-2:in `bind': java.net.SocketException: Permission denied (NativeException) Can someone help me to resolve this? Thanks in advance

    Read the article

  • How do I programmatically run all the JUnit tests in my Java application?

    - by Andrew McKinlay
    From Eclipse I can easily run all the JUnit tests in my application. I would like to be able to run the tests on target systems from the application jar, without Eclipse (or Ant or Maven or any other development tool). I can see how to run a specific test or suite from the command line. I could manually create a suite listing all the tests in my application, but that seems error prone - I'm sure at some point I'll create a test and forget to add it to the suite. The Eclipse JUnit plugin has a wizard to create a test suite, but for some reason it doesn't "see" my test classes. It may be looking for JUnit 3 tests, not JUnit 4 annotated tests. I could write a tool that would automatically create the suite by scanning the source files. Or I could write code so the application would scan it's own jar file for tests (either by naming convention or by looking for the @Test annotation). It seems like there should be an easier way. What am I missing?

    Read the article

  • "Detecting" and loading of "plugins" in GAE

    - by Patrick Cornelissen
    Hi! I have a "plugin like" architecture and I want to create one instance of each class that implements a dedicated interface and put these in a cache. (To have a singleton-ish effect). The plugins will be provided as jars and put into the app engine war file before the app is uploaded. I have tried to use the ClassPathScanningCandidateComponentProvider as I'm using spring anyway, but this didn't work. The provider complained that it was not able to find the HttpServletResponse class file while scanning the classpath. I can't get around this, when I add the servlet jar, then I'll get of course problems, because the same jar is also provided by the GAE. If I don't, I'm getting the error above... So I tried to add a static initialization code, but of course this doesn't work, because the class is initialized when it's instantiated for the first time. (Well I knew that but it was worth a try) The last chance I currently see is that I create a properties file with all plugin classes when the package is created, but this requires writing of a maven plugin etc. and I'd like to avoid that. Is there something that I am missing?

    Read the article

  • tomcat wont start up on linux machine

    - by David
    hi, im new to linux but after spending the day i have got linux running. installed java and tomcat. my goal is host my app with this linux box i've just set up. i know it all works fine from my windows based machine but it is my laptop so i'm planning this as my dedicated server. following many many forums i've now got tomcat 7 installed. however i cannot get it to start. changing to the tomcat directory and "./startup.sh" i get output Using CATALINA_BASE: /usr/local/tomcat Using CATALINA_HOME: /usr/local.tomcat Using CATALINA_TMPDIR: /usr/local/tomcat/temp Using JRE_HOME: usr/lib/jvm/java-6-sun/ Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local.tomcat/bin/c\tomcat-juli.jar thats the end of theoutput. however localhost:8080 is not up. and in the tomcat log file is the error "eval: 1: usr/lib/jvm/java-6-sun//bin/java: not found" hopfully there is some expert here who can help me with this problem. please note that im a novice when it comes to linux. thankyou oh and my version of linux is Ubuntu 10.04 LTS - the Lucid Lynx

    Read the article

  • Maven Assembly: include a dependency with a different classifier

    - by James Kingsbery
    I would like to build two different versions of a WAR in Maven (I know that's a no-no, that's just the way it is given the current situation). In the version of a WAR depicted by an assembly, I want to replace a dependency by the same dependency with a different classifier. For example, I was expecting this assembly to work: <assembly> <id>end-user</id> <formats> <format>war</format> </formats> <dependencySets> <dependencySet> <excludes> <exclude>group:artifact:jar:${project.version}</exclude> </excludes> <includes> <include>group:artifact:jar:${project.version}:end-user</include> </includes> </dependencySet> </dependencySets> </assembly> This doesn't work, but am I heading in the right direction? I've already read all the pages on the Maven assembly page and the section on the Maven Definitive Guide that seems relevant. Any pointers would be helpful.

    Read the article

  • Error when running a basic Hadoop code

    - by Abhishek Shivkumar
    I am running a hadoop code that has a partitioner class inside the job. But, when I run the command hadoop jar Sort.jar SecondarySort inputdir outputdir I am getting a runtime error that says class KeyPartitioner not org.apache.hadoop.mapred.Partitioner. I have ensured that the KeyPartitioner class has extended the Partitioner class, but why am I getting this error? Here is the driver code: JobConf conf = new JobConf(getConf(), SecondarySort.class); conf.setJobName(SecondarySort.class.getName()); conf.setJarByClass(SecondarySort.class); conf.setInputFormat(TextInputFormat.class); conf.setOutputFormat(TextOutputFormat.class); conf.setMapOutputKeyClass(StockKey.class); conf.setMapOutputValueClass(Text.class); conf.setPartitionerClass((Class<? extends Partitioner<StockKey, DoubleWritable>>) KeyPartitioner.class); conf.setMapperClass((Class<? extends Mapper<LongWritable, Text, StockKey, DoubleWritable>>) StockMapper.class); conf.setReducerClass((Class<? extends Reducer<StockKey, DoubleWritable, Text, Text>>) StockReducer.class); and here is the code of the partitioner class: public class KeyPartitioner extends Partitioner<StockKey, Text> { @Override public int getPartition(StockKey arg0, Text arg1, int arg2) { int partition = arg0.name.hashCode() % arg2; return partition; } }

    Read the article

  • i have this code but when i run it i get an exception:

    - by nisnis84
    i have this code but when i run it i get an exception: java.security.AccessControlException: access denied (java.net.SocketPermission 127.0.0.1:8081 connect,resolve) this is the code, the server running good but the client dont work <OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" width="615" height="360" codebase="http://java.sun.com/products/plugin/autodl/jinstall-1_4-windows-i586.cab#Version=1,4,0,mn"> <PARAM name="code" value="client/LlamaChat.class"> <PARAM name="archive" value="LlamaChat.jar"> <PARAM name="type" value="application/x-java-applet;version=1.4"> <PARAM name="scriptable" value="true"> <PARAM name="username" value="[replace with username]"> <PARAM name="port" value="[replace with port]"> <COMMENT> <EMBED type="application/x-java-applet;version=1.4" width="615" height="360" code="client/LlamaChat.class" archive="LlamaChat.jar" pluginspage="http://java.sun.com/j2se/1.4.1/download.html" username="nis" port="8081" <NOEMBED> No Java 1.4 plugin </NOEMBED></EMBED> </COMMENT> </OBJECT>

    Read the article

  • Portable Eclipse

    - by Jeach
    I'm trying to port my entire 'workspace' to a USB key (including the Eclipse executable) so that I can carry my work anywhere with me and work off the key directly. My directory hierarchy is similar to this: /workspace/eclipse - Where my current eclipse binary is stored /workspace/codebase - Where I keep the root of all my eclipse projects /workspace/resources - Where I keep all project files (images, docs, libs, etc.) It all works perfectly fine on one system. But when I change over to another system, the USB key gets mounted on another drive. For example, on my laptop, I get 'E:\', on my PC, I get 'K:\' and at work I get 'F:\', etc, etc. This means that because Eclipse (for 'some' reason) seems to only use full path names (including driver letters) in every single one of its configuration files (such as .classpath), nothing ever works when I want to work on another system. I put a 'libs' directory in the base of every project and populate it with its dependent JAR files. Why doesn't it use relative names instead, so that I could specify something like "../../libs/log4j.jar"? Anyone know how to fix this problem? Does anyone know of a workaround for this? For some reason, I really doubt I'm the first developer to do this! Thanks for your help and any suggestions.

    Read the article

  • Remote interface lookup-problem in Glassfish3

    - by andersmo
    I have deployed a war-file, with actionclasses and a facade, and a jar-file with ejb-components (a stateless bean, a couple of entities and a persistence.xml) on glassfish3. My problem is that i cant find my remote interface to the stateless bean from my facade. My bean and interface looks like: @Remote public interface RecordService {... @Stateless(name="RecordServiceBean", mappedName="ejb/RecordServiceJNDI") public class RecordServiceImpl implements RecordService { @PersistenceContext(unitName="record_persistence_ctx") private EntityManager em;... and if i look in the server.log the portable jndi looks like: Portable JNDI names for EJB RecordServiceBean : [java:global/recordEjb/RecordServiceBean, java:global/recordEjb/RecordServiceBean!domain.service.RecordService]|#] and my facade: ...InitialContext ctx= new InitialContext(); try{ recordService = (RecordService) ctx.lookup("java:global/recordEjb/RecordServiceBean!domain.service.RecordService"); } catch(Throwable t){ System.out.println("ooops"); try{ recordService = (RecordService)ctx.lookup("java:global/recordEjb/RecordServiceImpl"); } catch(Throwable t2){ System.out.println("noooo!"); }... } and when the facade makes the first call this exception occur: javax.naming.NamingException: Lookup failed for 'java:global/recordEjb/RecordServiceBean!domain.service.RecordService' in SerialContext [Root exception is javax.naming.NamingException: ejb ref resolution error for remote business interfacedomain.service.RecordService [Root exception is java.lang.ClassNotFoundException: domain.service.RecordService]] and the second call: javax.naming.NamingException: Lookup failed for 'java:global/recordEjb/RecordServiceBean' in SerialContext [Root exception is javax.naming.NamingException: ejb ref resolution error for remote business interfacedomain.service.RecordService [Root exception is java.lang.ClassNotFoundException: domain.service.RecordService]] I have also tested to inject the bean with the @EJB-annotation: @EJB(name="RecordServiceBean") private RecordService recordService; But that doesnt work either. What have i missed? I tried with an ejb-jar.xml but that shouldnt be nessesary. Is there anyone who can tell me how to fix this problem?

    Read the article

  • Releasing from development into production in maven

    - by Bruce
    Hi all, I'm confused about the use of maven in development and production environments - I'm sure it's something simple that I'm missing. Grateful for any help.. I set up maven inside eclipse on my local machine and wrote some software. I really like how it's made things like including dependent jars very easy. So that's my development environment. But now I want to release the project to production on a remote server. I've searched the documentation, but I can't figure out how it's supposed to work or what the maven best practice is.. Are you supposed to: a) Also be running maven on your production environment, and upload all your files to your production environment and rebuild your project there? (Something in me baulks at the idea of rebuilding 'released' code on the production server, so I'm fairly sure this isn't right..) b) use mvn:package to create your jar file and then copy that up to production? (But then what of all those nice dependencies? Isn't there a danger that your tested code is now going to be running against different versions of the dependent jars in the production environment, possibly breaking your code? Or missing a jar..?) c) Something else that I'm not figuring out.. Thanks in advance for any help!

    Read the article

  • Referencing java resource files for cold fusion

    - by Chimeara
    I am using a .Jar file containing a .properties file in my CF code, however it seems unable to find the .properties file when run from CF. My java code is: String key =""; String value =""; try { File file = new File("src/test.properties"); FileInputStream fileInput = new FileInputStream(file); Properties properties = new Properties(); properties.load(fileInput); fileInput.close(); Enumeration enuKeys = properties.keys(); while (enuKeys.hasMoreElements()) { key = (String) enuKeys.nextElement(); value = properties.getProperty(key); //System.out.println(key + ": " + value); } } catch (FileNotFoundException e) { e.printStackTrace(); key ="error"; } catch (IOException e) { e.printStackTrace(); key ="error"; } return(key + ": " + value); I have my test.properties file in the project src folder, and make sure it is selected when compiling, when run from eclipse it gives the expected key and value, however when run from CF I get the caught errors. My CF code is simply: propTest = CreateObject("java","package.class"); testResults = propTest.main2(); Is there a special way to reference the .properties file so CF can access it, or do I need to include the file outside the .jar somewhere?

    Read the article

  • HIbernate 3.5.1 - can I just drop in EHCache 2.0.1?

    - by caerphilly
    I'm using Hibernate 3.5.1, which comes with EHCache 1.5 bundled. If I want to use the latest EHCache release (2.0.1), is it just a matter of removing the ehcache-1.5.jar from my project, and replacing with ehcache-core-2.0.1.jar? Any issues to be aware of? Also - is a cache "region" in the Hibernate mapping file that same as a cache "name" in the ehcache configuration xml? What I want to do is define 2 named cache regions - one for read-only reference entities that won't change (lookup lists etc), and one for all other entities. So in ehcache I want to define two elements; <cache name="readonly"> ... </cache> <cache name="mutable"> ... </cache> And then in my Hibernate mapping files, I will specify the cache to be used for each entity: <hibernate-mapping> <class name="lookuplist"> <cache region="readonly" usage="read-only"/> <property> ... </property> </class> </hibernate-mapping> Will that work? Some of the documentation seems to imply that a separate region/cache gets created for each mapped class... Thanks.

    Read the article

  • Converting a soap message to a document using wssj

    - by ellander
    I have been supplied with a jar file that should enable me to connect to a 3rd party system. When I run the necessary class I get an error which states that the namespace for the prefix "SOAPENV" has not been declared. Using jad I have decompiled the class files to try suss out what is going on and the error seems to occur when a soap message is being converted to a document. Unfortunately I don't know much about wssj. Can anyone suggest what the problem might be? I'm wondering if it's an incompatibility issue as it's not a recently created jar file and the decompiled code looks different to all the examples I can find. For example, in this section the examples have addNamesSpaceDeclaration rather than addAttribute... MessageFactory factory = MessageFactory.newInstance(); SOAPFactory sf = SOAPFactory.newInstance(); SOAPMessage msg = factory.createMessage(); MimeHeaders headers = msg.getMimeHeaders(); headers.addHeader("Content-Type", "text/xml"); SOAPEnvelope env = msg.getSOAPPart().getEnvelope(); env.addAttribute(sf.createName("xmlns:xsi"), "http://www.w3.org/2001/XMLSchema-instance");

    Read the article

  • Jasper Reports and iReport issue

    - by William
    I am having an issue with JasperReports I can not solve. I am using Eclipse, OpenReports 3.2 and IReport 3.7 The issue I am having is that the report does nothing. When I preview the report in IReport I can at least get a "Document has no pages" message but when I try to open it using OpenReports it doesn't do anything. I get the open reports header and the copyright message but nothing between them. I was able to track it down to line 150 in ReportRunAction.java in OpenReports. That line is: jasperPrint = jasperEngine.fillReport(reportInput); At least that is the line the page dies on. It trips the catch block that the line is inside of but the error is empty. When I try to print the description it is null. I can't swear that the issue isn't that parameter. Through looking around all I have been able to find is something about how the report needs to be compiled with the same version of the jasperreports.jar that OpenReports uses. I have no idea how to tell if/what version of jasper reports is being bundled into the .jasper file though. Is that my problem? If so how do I tell/set the version of the jar that gets bundled? If not; help!

    Read the article

  • How do I configure a mail server for use with JavaMail?

    - by bobby
    I'm trying to work with the below code: import javax.servlet.*; import javax.servlet.http.*; import java.io.*; import javax.mail.*; import javax.mail.internet.*; // important import javax.mail.event.*; // important import java.net.*; import java.util.*; public class servletmail extends HttpServlet { public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException { PrintWriter out=response.getWriter(); response.setContentType("text/html"); try { Properties props=new Properties(); props.put("mail.smtp.host","localhost"); // 'localhost' for testing Session session1 = Session.getDefaultInstance(props,null); String s1 = request.getParameter("text1"); //sender (from) String s2 = request.getParameter("text2"); String s3 = request.getParameter("text3"); String s4 = request.getParameter("area1"); Message message =new MimeMessage(session1); message.setFrom(new InternetAddress(s1)); message.setRecipients(Message.RecipientType.TO,InternetAddress.parse(s2,false)); message.setSubject(s3); message.setText(s4); Transport.send(message); out.println("mail has been sent"); } catch(Exception ex) { System.out.println("ERROR....."+ex); } } } I'm using mail.jar and activation.jar. But I can't understand how I should configure it with a mail server. Which mail server should I use? Will I be able to send an email using above code? What are the requirements a mail server? How should I configure it?

    Read the article

  • Mobile enabled web apps with ASP.NET MVC 3 and jQuery Mobile

    - by shiju
    In my previous blog posts, I have demonstrated a simple web app using ASP.NET MVC 3 and EF Code First. In this post, I will be focus on making this application for mobile devices. A single web site will be used for both mobile browsers and desktop browsers. If users are accessing the web app from mobile browsers, users will be redirect to mobile specific pages and will get normal pages if users are accessing from desktop browsers. In this demo app, the mobile specific pages are maintained in an ASP.NET MVC Area named Mobile and mobile users will be redirect to MVC Area Mobile. Let’s add a new area named Mobile to the ASP.NET MVC app. For adding Area, right click the ASP.NET MVC project and  select Area from Add option. Our mobile specific pages using jQuery Mobile will be maintained in the Mobile Area. ASP.NET MVC Global filter for redirecting mobile visitors to Mobile area Let’s add an ASP.NET MVC Global filter for redirecting mobile visitors to Mobile area. The below Global filter is taken from the sample app http://aspnetmobilesamples.codeplex.com/ created by the ASP.NET team. The below filer will redirect the Mobile visitors to an ASP.NET MVC Area Mobile. public class RedirectMobileDevicesToMobileAreaAttribute : AuthorizeAttribute     {         protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)         {             // Only redirect on the first request in a session             if (!httpContext.Session.IsNewSession)                 return true;               // Don't redirect non-mobile browsers             if (!httpContext.Request.Browser.IsMobileDevice)                 return true;               // Don't redirect requests for the Mobile area             if (Regex.IsMatch(httpContext.Request.Url.PathAndQuery, "/Mobile($|/)"))                 return true;               return false;         }           protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)         {             var redirectionRouteValues = GetRedirectionRouteValues(filterContext.RequestContext);             filterContext.Result = new RedirectToRouteResult(redirectionRouteValues);         }           // Override this method if you want to customize the controller/action/parameters to which         // mobile users would be redirected. This lets you redirect users to the mobile equivalent         // of whatever resource they originally requested.         protected virtual RouteValueDictionary GetRedirectionRouteValues(RequestContext requestContext)         {             return new RouteValueDictionary(new { area = "Mobile", controller = "Home", action = "Index" });         }     } Let’s add the global filer RedirectMobileDevicesToMobileAreaAttribute to the global filter collection in the Application_Start() of Global.asax.cs file   GlobalFilters.Filters.Add(new RedirectMobileDevicesToMobileAreaAttribute(), 1); Now your mobile visitors will be redirect to the Mobile area. But the browser detection logic in the RedirectMobileDevicesToMobileAreaAttribute filter will not be working in some modern browsers and some conditions. But the good news is that ASP.NET’s browser detection feature is extensible and will be greatly working with the open source framework 51Degrees.mobi. 51Degrees.mobi is a Browser Capabilities Provider that will be working with ASP.NET’s Request.Browser and will provide more accurate and detailed information. For more details visit the documentation page at http://51degrees.codeplex.com/documentation. Let’s add a reference to 51Degrees.mobi library using NuGet We can easily add the 51Degrees.mobi from NuGet and this will update the web.config for necessary configuartions. Mobile Web App using jQuery Mobile Framework jQuery Mobile Framework is built on top of jQuery that provides top-of-the-line JavaScript in a unified User Interface that works across the most-used smartphone web browsers and tablet form factors. It provides an easy way to develop user interfaces for mobile web apps. The current version of the framework is jQuery Mobile Alpha 3. We need to include the following files to use jQuery Mobile. The jQuery Mobile CSS file (jquery.mobile-1.0a3.min.css) The jQuery library (jquery-1.5.min.js) The jQuery Mobile library (jquery.mobile-1.0a3.min.js) Let’s add the required jQuery files directly from jQuery CDN . You can download the files and host them on your own server. jQuery Mobile page structure The basic jQuery Mobile page structure is given below <!DOCTYPE html> <html>   <head>   <title>Page Title</title>   <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a1.min.css" />   <script src="http://code.jquery.com/jquery-1.5.min.js"></script>   <script src="http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.min.js"></script> </head> <body> <div data-role="page">   <div data-role="header">     <h1>Page Title</h1>   </div>   <div data-role="content">     <p>Page content goes here.</p>      </div>   <div data-role="footer">     <h4>Page Footer</h4>   </div> </div> </body> </html> The data- attributes are the new feature of HTML5 so that jQuery Mobile will be working on browsers that supporting HTML 5. You can get a detailed browser support details from http://jquerymobile.com/gbs/ . In the Head section we have included the Core jQuery javascript file and jQuery Mobile Library and the core CSS Library for the UI Element Styling. These jQuery files are minified versions and will improve the performance of page load on Mobile Devices. The jQuery Mobile pages are identified with an element with the data-role="page" attribute inside the <body> tag. <div data-role="page"> </div> Within the "page" container, any valid HTML markup can be used, but for typical pages in jQuery Mobile, the immediate children of a "page" are div element with data-roles of "header", "content", and "footer". <div data-role="page">     <div data-role="header">...</div>     <div data-role="content">...</div>     <div data-role="footer">...</div> </div> The div data-role="content" holds the main content of the HTML page and will be used for making user interaction elements. The div data-role="header" is header part of the page and div data-role="footer" is the footer part of the page. Creating Mobile specific pages in the Mobile Area Let’s create Layout page for our Mobile area <!DOCTYPE html> <html> <head>     <title>@ViewBag.Title</title>     <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.min.css" />     <script src="http://code.jquery.com/jquery-1.5.min.js"></script>     <script src="http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.min.js"></script>     </head>      <body> @RenderBody()    </body> </html> In the Layout page, I have given reference to jQuery Mobile JavaScript files and the CSS file. Let’s add an Index view page Index.chtml @{     ViewBag.Title = "Index"; } <div data-role="page"> <div data-role="header">      <h1>Expense Tracker Mobile</h1> </div> <div data-role="content">   <ul data-role="listview">     <li>@Html.Partial("_LogOnPartial")</li>      <li>@Html.ActionLink("Home", "Index", "Home")</li>      <li>@Html.ActionLink("Category", "Index", "Category")</li>                          <li>@Html.ActionLink("Expense", "Index", "Expense")</li> </ul> </div> <div data-role="footer">           Shiju Varghese | <a href="http://weblogs.asp.net/shijuvarghese">Blog     </a> | <a href="http://twitter.com/shijucv">Twitter</a>   </div> </div>   In the Index page, we have used data-role “listview” for showing our content as List View Let’s create a data entry screen create.cshtml @model MyFinance.Domain.Category @{     ViewBag.Title = "Create Category"; }   <div data-role="page"> <div data-role="header">      <h1>Create Category</h1>             @Html.ActionLink("Home", "Index","Home",null, new { @class = "ui-btn-right" })      </div>       <div data-role="content">     @using (Html.BeginForm("Create","Category",FormMethod.Post))     {       <div data-role="fieldcontain">        @Html.LabelFor(model => model.Name)        @Html.EditorFor(model => model.Name)        <div>           @Html.ValidationMessageFor(m => m.Name)        </div>         </div>         <div data-role="fieldcontain">         @Html.LabelFor(model => model.Description)         @Html.EditorFor(model => model.Description)                   </div>                    <div class="ui-body ui-body-b">         <button type="submit" data-role="button" data-theme="b">Save</button>       </div>     }        </div> </div>   In jQuery Mobile, the form elements should be placed inside the data-role="fieldcontain" The below screen shots show the pages rendered in mobile browser Index Page Create Page Source Code You can download the source code from http://efmvc.codeplex.com   Summary We have created a single  web app for desktop browsers and mobile browsers. If a user access the site from desktop browsers, users will get normal web pages and get mobile specific pages if users access from mobile browsers. If users are accessing the website from mobile devices, we will redirect to a ASP.NET MVC area Mobile. For redirecting to the Mobile area, we have used a Global filer for the redirection logic and used open source framework 51Degrees.mobi for the better support for mobile browser detection. In the Mobile area, we have created the pages using jQuery Mobile and users will get mobile friendly web pages. We can create great mobile web apps using ASP.NET MVC  and jQuery Mobile Framework.

    Read the article

  • jQuery and Windows Azure

    - by Stephen Walther
    The goal of this blog entry is to describe how you can host a simple Ajax application created with jQuery in the Windows Azure cloud. In this blog entry, I make no assumptions. I assume that you have never used Windows Azure and I am going to walk through the steps required to host the application in the cloud in agonizing detail. Our application will consist of a single HTML page and a single service. The HTML page will contain jQuery code that invokes the service to retrieve and display set of records. There are five steps that you must complete to host the jQuery application: Sign up for Windows Azure Create a Hosted Service Install the Windows Azure Tools for Visual Studio Create a Windows Azure Cloud Service Deploy the Cloud Service Sign Up for Windows Azure Go to http://www.microsoft.com/windowsazure/ and click the Sign up Now button. Select one of the offers. I selected the Introductory Special offer because it is free and I just wanted to experiment with Windows Azure for the purposes of this blog entry.     To sign up, you will need a Windows Live ID and you will need to enter a credit card number. After you finish the sign up process, you will receive an email that explains how to activate your account. Accessing the Developer Portal After you create your account and your account is activated, you can access the Windows Azure developer portal by visiting the following URL: http://windows.azure.com/ When you first visit the developer portal, you will see the one project that you created when you set up your Windows Azure account (In a fit of creativity, I named my project StephenWalther).     Creating a New Windows Azure Hosted Service Before you can host an application in the cloud, you must first add a hosted service to your project. Click your project on the summary page and click the New Service link. You are presented with the option of creating either a new Storage Account or a new Hosted Services.     Because we have code that we want to run in the cloud – the WCF Service -- we want to select the Hosted Services option. After you select this option, you must provide a name and description for your service. This information is used on the developer portal so you can distinguish your services.     When you create a new hosted service, you must enter a unique name for your service (I selected jQueryApp) and you must select a region for this service (I selected Anywhere US). Click the Create button to create the new hosted service.   Install the Windows Azure Tools for Visual Studio We’ll use Visual Studio to create our jQuery project. Before you can use Visual Studio with Windows Azure, you must first install the Windows Azure Tools for Visual Studio. Go to http://www.microsoft.com/windowsazure/ and click the Get Tools and SDK button. The Windows Azure Tools for Visual Studio works with both Visual Studio 2008 and Visual Studio 2010.   Installation of the Windows Azure Tools for Visual Studio is painless. You just need to check some agreement checkboxes and click the Next button a few times and installation will begin:   Creating a Windows Azure Application After you install the Windows Azure Tools for Visual Studio, you can choose to create a Windows Azure Cloud Service by selecting the menu option File, New Project and selecting the Windows Azure Cloud Service project template. I named my new Cloud Service with the name jQueryApp.     Next, you need to select the type of Cloud Service project that you want to create from the New Cloud Service Project dialog.   I selected the C# ASP.NET Web Role option. Alternatively, I could have picked the ASP.NET MVC 2 Web Role option if I wanted to use jQuery with ASP.NET MVC or even the CGI Web Role option if I wanted to use jQuery with PHP. After you complete these steps, you end up with two projects in your Visual Studio solution. The project named WebRole1 represents your ASP.NET application and we will use this project to create our jQuery application. Creating the jQuery Application in the Cloud We are now ready to create the jQuery application. We’ll create a super simple application that displays a list of records retrieved from a WCF service (hosted in the cloud). Create a new page in the WebRole1 project named Default.htm and add the following code: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Products</title> <style type="text/css"> #productContainer div { border:solid 1px black; padding:5px; margin:5px; } </style> </head> <body> <h1>Product Catalog</h1> <div id="productContainer"></div> <script id="productTemplate" type="text/html"> <div> Name: {{= name }} <br /> Price: {{= price }} </div> </script> <script src="Scripts/jquery-1.4.2.js" type="text/javascript"></script> <script src="Scripts/jquery.tmpl.js" type="text/javascript"></script> <script type="text/javascript"> var products = [ {name:"Milk", price:4.55}, {name:"Yogurt", price:2.99}, {name:"Steak", price:23.44} ]; $("#productTemplate").render(products).appendTo("#productContainer"); </script> </body> </html> The jQuery code in this page simply displays a list of products by using a template. I am using a jQuery template to format each product. You can learn more about using jQuery templates by reading the following blog entry by Scott Guthrie: http://weblogs.asp.net/scottgu/archive/2010/05/07/jquery-templates-and-data-linking-and-microsoft-contributing-to-jquery.aspx You can test whether the Default.htm page is working correctly by running your application (hit the F5 key). The first time that you run your application, a database is set up on your local machine to simulate cloud storage. You will see the following dialog: If the Default.htm page works as expected, you should see the list of three products: Adding an Ajax-Enabled WCF Service In the previous section, we created a simple jQuery application that displays an array by using a template. The application is a little too simple because the data is static. In this section, we’ll modify the page so that the data is retrieved from a WCF service instead of an array. First, we need to add a new Ajax-enabled WCF Service to the WebRole1 project. Select the menu option Project, Add New Item and select the Ajax-enabled WCF Service project item. Name the new service ProductService.svc. Modify the service so that it returns a static collection of products. The final code for the ProductService.svc should look like this: using System.Collections.Generic; using System.ServiceModel; using System.ServiceModel.Activation; namespace WebRole1 { public class Product { public string name { get; set; } public decimal price { get; set; } } [ServiceContract(Namespace = "")] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class ProductService { [OperationContract] public IList<Product> SelectProducts() { var products = new List<Product>(); products.Add(new Product {name="Milk", price=4.55m} ); products.Add(new Product { name = "Yogurt", price = 2.99m }); products.Add(new Product { name = "Steak", price = 23.44m }); return products; } } }   In real life, you would want to retrieve the list of products from storage instead of a static array. We are being lazy here. Next you need to modify the Default.htm page to use the ProductService.svc. The jQuery script in the following updated Default.htm page makes an Ajax call to the WCF service. The data retrieved from the ProductService.svc is displayed in the client template. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Products</title> <style type="text/css"> #productContainer div { border:solid 1px black; padding:5px; margin:5px; } </style> </head> <body> <h1>Product Catalog</h1> <div id="productContainer"></div> <script id="productTemplate" type="text/html"> <div> Name: {{= name }} <br /> Price: {{= price }} </div> </script> <script src="Scripts/jquery-1.4.2.js" type="text/javascript"></script> <script src="Scripts/jquery.tmpl.js" type="text/javascript"></script> <script type="text/javascript"> $.post("ProductService.svc/SelectProducts", function (results) { var products = results["d"]; $("#productTemplate").render(products).appendTo("#productContainer"); }); </script> </body> </html>   Deploying the jQuery Application to the Cloud Now that we have created our jQuery application, we are ready to deploy our application to the cloud so that the whole world can use it. Right-click your jQueryApp project in the Solution Explorer window and select the Publish menu option. When you select publish, your application and your application configuration information is packaged up into two files named jQueryApp.cspkg and ServiceConfiguration.cscfg. Visual Studio opens the directory that contains the two files. In order to deploy these files to the Windows Azure cloud, you must upload these files yourself. Return to the Windows Azure Developers Portal at the following address: http://windows.azure.com/ Select your project and select the jQueryApp service. You will see a mysterious cube. Click the Deploy button to upload your application.   Next, you need to browse to the location on your hard drive where the jQueryApp project was published and select both the packaged application and the packaged application configuration file. Supply the deployment with a name and click the Deploy button.     While your application is in the process of being deployed, you can view a progress bar.     Running the jQuery Application in the Cloud Finally, you can run your jQuery application in the cloud by clicking the Run button.   It might take several minutes for your application to initialize (go grab a coffee). After WebRole1 finishes initializing, you can navigate to the following URL to view your live jQuery application in the cloud: http://jqueryapp.cloudapp.net/default.htm The page is hosted on the Windows Azure cloud and the WCF service executes every time that you request the page to retrieve the list of products. Summary Because we started from scratch, we needed to complete several steps to create and deploy our jQuery application to the Windows Azure cloud. We needed to create a Windows Azure account, create a hosted service, install the Windows Azure Tools for Visual Studio, create the jQuery application, and deploy it to the cloud. Now that we have finished this process once, modifying our existing cloud application or creating a new cloud application is easy. jQuery and Windows Azure work nicely together. We can take advantage of jQuery to build applications that run in the browser and we can take advantage of Windows Azure to host the backend services required by our jQuery application. The big benefit of Windows Azure is that it enables us to scale. If, all of the sudden, our jQuery application explodes in popularity, Windows Azure enables us to easily scale up to meet the demand. We can handle anything that the Internet might throw at us.

    Read the article

  • Metro Walkthrough: Creating a Task List with a ListView and IndexedDB

    - by Stephen.Walther
    The goal of this blog entry is to describe how you can work with data in a Metro style application written with JavaScript. In particular, we create a super simple Task List application which enables you to create and delete tasks. Here’s a video which demonstrates how the Task List application works: In order to build this application, I had to take advantage of several features of the WinJS library and technologies including: IndexedDB – The Task List application stores data in an IndexedDB database. HTML5 Form Validation – The Task List application uses HTML5 validation to ensure that a required field has a value. ListView Control – The Task List application displays the tasks retrieved from the IndexedDB database in a WinJS ListView control. Creating the IndexedDB Database The Task List application stores all of its data in an IndexedDB database named TasksDB. This database is opened/created with the following code: var db; var req = window.msIndexedDB.open("TasksDB", 1); req.onerror = function () { console.log("Could not open database"); }; req.onupgradeneeded = function (evt) { var newDB = evt.target.result; newDB.createObjectStore("tasks", { keyPath: "id", autoIncrement:true }); }; The msIndexedDB.open() method accepts two parameters: the name of the database to open and the version of the database to open. If a database with a matching version already exists, then calling the msIndexedDB.open() method opens a connection to the existing database. If the database does not exist then the upgradeneeded event is raised. You handle the upgradeneeded event to create a new database. In the code above, the upgradeneeded event handler creates an object store named “tasks” (An object store roughly corresponds to a database table). When you add items to the tasks object store then each item gets an id property with an auto-incremented value automatically. The code above also includes an error event handler. If the IndexedDB database cannot be opened or created, for whatever reason, then an error message is written to the Visual Studio JavaScript Console window. Displaying a List of Tasks The TaskList application retrieves its list of tasks from the tasks object store, which we created above, and displays the list of tasks in a ListView control. Here is how the ListView control is declared: <div id="tasksListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource: TaskList.tasks.dataSource, itemTemplate: select('#taskTemplate'), tapBehavior: 'toggleSelect', selectionMode: 'multi', layout: { type: WinJS.UI.ListLayout } }"> </div> The ListView control is bound to the TaskList.tasks.dataSource data source. The TaskList.tasks.dataSource is created with the following code: // Create the data source var tasks = new WinJS.Binding.List(); // Open the database var db; var req = window.msIndexedDB.open("TasksDB", 1); req.onerror = function () { console.log("Could not open database"); }; req.onupgradeneeded = function (evt) { var newDB = evt.target.result; newDB.createObjectStore("tasks", { keyPath: "id", autoIncrement:true }); }; // Load the data source with data from the database req.onsuccess = function () { db = req.result; var tran = db.transaction("tasks"); tran.objectStore("tasks").openCursor().onsuccess = function(event) { var cursor = event.target.result; if (cursor) { tasks.dataSource.insertAtEnd(null, cursor.value); cursor.continue(); }; }; }; // Expose the data source and functions WinJS.Namespace.define("TaskList", { tasks: tasks }); Notice the success event handler. This handler is called when a database is successfully opened/created. In the code above, all of the items from the tasks object store are retrieved into a cursor and added to a WinJS.Binding.List object named tasks. Because the ListView control is bound to the WinJS.Binding.List object, copying the tasks from the object store into the WinJS.Binding.List object causes the tasks to appear in the ListView: Adding a New Task You add a new task in the Task List application by entering the title of a new task into an HTML form and clicking the Add button. Here’s the markup for creating the form: <form id="addTaskForm"> <input id="newTaskTitle" title="New Task" required /> <button>Add</button> </form> Notice that the INPUT element includes a required attribute. In a Metro application, you can take advantage of HTML5 Validation to validate form fields. If you don’t enter a value for the newTaskTitle field then the following validation error message is displayed: For a brief introduction to HTML5 validation, see my previous blog entry: http://stephenwalther.com/blog/archive/2012/03/13/html5-form-validation.aspx When you click the Add button, the form is submitted and the form submit event is raised. The following code is executed in the default.js file: // Handle Add Task document.getElementById("addTaskForm").addEventListener("submit", function (evt) { evt.preventDefault(); var newTaskTitle = document.getElementById("newTaskTitle"); TaskList.addTask({ title: newTaskTitle.value }); newTaskTitle.value = ""; }); The code above retrieves the title of the new task and calls the addTask() method in the tasks.js file. Here’s the code for the addTask() method which is responsible for actually adding the new task to the IndexedDB database: // Add a new task function addTask(taskToAdd) { var transaction = db.transaction("tasks", "readwrite"); var addRequest = transaction.objectStore("tasks").add(taskToAdd); addRequest.onsuccess = function (evt) { taskToAdd.id = evt.target.result; tasks.dataSource.insertAtEnd(null, taskToAdd); } } The code above does two things. First, it adds the new task to the tasks object store in the IndexedDB database. Second, it adds the new task to the data source bound to the ListView. The dataSource.insertAtEnd() method is called to add the new task to the data source so the new task will appear in the ListView (with a nice little animation). Deleting Existing Tasks The Task List application enables you to select one or more tasks by clicking or tapping on one or more tasks in the ListView. When you click the Delete button, the selected tasks are removed from both the IndexedDB database and the ListView. For example, in the following screenshot, two tasks are selected. The selected tasks appear with a teal background and a checkmark: When you click the Delete button, the following code in the default.js file is executed: // Handle Delete Tasks document.getElementById("btnDeleteTasks").addEventListener("click", function (evt) { tasksListView.winControl.selection.getItems().then(function(items) { items.forEach(function (item) { TaskList.deleteTask(item); }); }); }); The selected tasks are retrieved with the TaskList selection.getItem() method. In the code above, the deleteTask() method is called for each of the selected tasks. Here’s the code for the deleteTask() method: // Delete an existing task function deleteTask(listViewItem) { // Database key != ListView key var dbKey = listViewItem.data.id; var listViewKey = listViewItem.key; // Remove item from db and, if success, remove item from ListView var transaction = db.transaction("tasks", “readwrite”); var deleteRequest = transaction.objectStore("tasks").delete(dbKey); deleteRequest.onsuccess = function () { tasks.dataSource.remove(listViewKey); } } This code does two things: it deletes the existing task from the database and removes the existing task from the ListView. In both cases, the right task is removed by using the key associated with the task. However, the task key is different in the case of the database and in the case of the ListView. In the case of the database, the task key is the value of the task id property. In the case of the ListView, on the other hand, the task key is auto-generated by the ListView. When the task is removed from the ListView, an animation is used to collapse the tasks which appear above and below the task which was removed. The Complete Code Above, I did a lot of jumping around between different files in the application and I left out sections of code. For the sake of completeness, I want to include the entire code here: the default.html, default.js, and tasks.js files. Here are the contents of the default.html file. This file contains the UI for the Task List application: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Task List</title> <!-- WinJS references --> <link href="//Microsoft.WinJS.0.6/css/ui-dark.css" rel="stylesheet"> <script src="//Microsoft.WinJS.0.6/js/base.js"></script> <script src="//Microsoft.WinJS.0.6/js/ui.js"></script> <!-- TaskList references --> <link href="/css/default.css" rel="stylesheet"> <script src="/js/default.js"></script> <script type="text/javascript" src="js/tasks.js"></script> <style type="text/css"> body { font-size: x-large; } form { display: inline; } #appContainer { margin: 20px; width: 600px; } .win-container { padding: 10px; } </style> </head> <body> <div> <!-- Templates --> <div id="taskTemplate" data-win-control="WinJS.Binding.Template"> <div> <span data-win-bind="innerText:title"></span> </div> </div> <h1>Super Task List</h1> <div id="appContainer"> <form id="addTaskForm"> <input id="newTaskTitle" title="New Task" required /> <button>Add</button> </form> <button id="btnDeleteTasks">Delete</button> <div id="tasksListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource: TaskList.tasks.dataSource, itemTemplate: select('#taskTemplate'), tapBehavior: 'toggleSelect', selectionMode: 'multi', layout: { type: WinJS.UI.ListLayout } }"> </div> </div> </div> </body> </html> Here is the code for the default.js file. This code wires up the Add Task form and Delete button: (function () { "use strict"; var app = WinJS.Application; app.onactivated = function (eventObject) { if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) { WinJS.UI.processAll().then(function () { // Get reference to Tasks ListView var tasksListView = document.getElementById("tasksListView"); // Handle Add Task document.getElementById("addTaskForm").addEventListener("submit", function (evt) { evt.preventDefault(); var newTaskTitle = document.getElementById("newTaskTitle"); TaskList.addTask({ title: newTaskTitle.value }); newTaskTitle.value = ""; }); // Handle Delete Tasks document.getElementById("btnDeleteTasks").addEventListener("click", function (evt) { tasksListView.winControl.selection.getItems().then(function(items) { items.forEach(function (item) { TaskList.deleteTask(item); }); }); }); }); } }; app.start(); })(); Finally, here is the tasks.js file. This file contains all of the code for opening, creating, and interacting with IndexedDB: (function () { "use strict"; // Create the data source var tasks = new WinJS.Binding.List(); // Open the database var db; var req = window.msIndexedDB.open("TasksDB", 1); req.onerror = function () { console.log("Could not open database"); }; req.onupgradeneeded = function (evt) { var newDB = evt.target.result; newDB.createObjectStore("tasks", { keyPath: "id", autoIncrement:true }); }; // Load the data source with data from the database req.onsuccess = function () { db = req.result; var tran = db.transaction("tasks"); tran.objectStore("tasks").openCursor().onsuccess = function(event) { var cursor = event.target.result; if (cursor) { tasks.dataSource.insertAtEnd(null, cursor.value); cursor.continue(); }; }; }; // Add a new task function addTask(taskToAdd) { var transaction = db.transaction("tasks", "readwrite"); var addRequest = transaction.objectStore("tasks").add(taskToAdd); addRequest.onsuccess = function (evt) { taskToAdd.id = evt.target.result; tasks.dataSource.insertAtEnd(null, taskToAdd); } } // Delete an existing task function deleteTask(listViewItem) { // Database key != ListView key var dbKey = listViewItem.data.id; var listViewKey = listViewItem.key; // Remove item from db and, if success, remove item from ListView var transaction = db.transaction("tasks", "readwrite"); var deleteRequest = transaction.objectStore("tasks").delete(dbKey); deleteRequest.onsuccess = function () { tasks.dataSource.remove(listViewKey); } } // Expose the data source and functions WinJS.Namespace.define("TaskList", { tasks: tasks, addTask: addTask, deleteTask: deleteTask }); })(); Summary I wrote this blog entry because I wanted to create a walkthrough of building a simple database-driven application. In particular, I wanted to demonstrate how you can use a ListView control with an IndexedDB database to store and retrieve database data.

    Read the article

  • Metro Walkthrough: Creating a Task List with a ListView and IndexedDB

    - by Stephen.Walther
    The goal of this blog entry is to describe how you can work with data in a Metro style application written with JavaScript. In particular, we create a super simple Task List application which enables you to create and delete tasks. Here’s a video which demonstrates how the Task List application works: In order to build this application, I had to take advantage of several features of the WinJS library and technologies including: IndexedDB – The Task List application stores data in an IndexedDB database. HTML5 Form Validation – The Task List application uses HTML5 validation to ensure that a required field has a value. ListView Control – The Task List application displays the tasks retrieved from the IndexedDB database in a WinJS ListView control. Creating the IndexedDB Database The Task List application stores all of its data in an IndexedDB database named TasksDB. This database is opened/created with the following code: var db; var req = window.msIndexedDB.open("TasksDB", 1); req.onerror = function () { console.log("Could not open database"); }; req.onupgradeneeded = function (evt) { var newDB = evt.target.result; newDB.createObjectStore("tasks", { keyPath: "id", autoIncrement:true }); }; The msIndexedDB.open() method accepts two parameters: the name of the database to open and the version of the database to open. If a database with a matching version already exists, then calling the msIndexedDB.open() method opens a connection to the existing database. If the database does not exist then the upgradeneeded event is raised. You handle the upgradeneeded event to create a new database. In the code above, the upgradeneeded event handler creates an object store named “tasks” (An object store roughly corresponds to a database table). When you add items to the tasks object store then each item gets an id property with an auto-incremented value automatically. The code above also includes an error event handler. If the IndexedDB database cannot be opened or created, for whatever reason, then an error message is written to the Visual Studio JavaScript Console window. Displaying a List of Tasks The TaskList application retrieves its list of tasks from the tasks object store, which we created above, and displays the list of tasks in a ListView control. Here is how the ListView control is declared: <div id="tasksListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource: TaskList.tasks.dataSource, itemTemplate: select('#taskTemplate'), tapBehavior: 'toggleSelect', selectionMode: 'multi', layout: { type: WinJS.UI.ListLayout } }"> </div> The ListView control is bound to the TaskList.tasks.dataSource data source. The TaskList.tasks.dataSource is created with the following code: // Create the data source var tasks = new WinJS.Binding.List(); // Open the database var db; var req = window.msIndexedDB.open("TasksDB", 1); req.onerror = function () { console.log("Could not open database"); }; req.onupgradeneeded = function (evt) { var newDB = evt.target.result; newDB.createObjectStore("tasks", { keyPath: "id", autoIncrement:true }); }; // Load the data source with data from the database req.onsuccess = function () { db = req.result; var tran = db.transaction("tasks"); tran.objectStore("tasks").openCursor().onsuccess = function(event) { var cursor = event.target.result; tasks.dataSource.beginEdits(); if (cursor) { tasks.dataSource.insertAtEnd(null, cursor.value); cursor.continue(); } else { tasks.dataSource.endEdits(); }; }; }; // Expose the data source and functions WinJS.Namespace.define("TaskList", { tasks: tasks }); Notice the success event handler. This handler is called when a database is successfully opened/created. In the code above, all of the items from the tasks object store are retrieved into a cursor and added to a WinJS.Binding.List object named tasks. Because the ListView control is bound to the WinJS.Binding.List object, copying the tasks from the object store into the WinJS.Binding.List object causes the tasks to appear in the ListView: Adding a New Task You add a new task in the Task List application by entering the title of a new task into an HTML form and clicking the Add button. Here’s the markup for creating the form: <form id="addTaskForm"> <input id="newTaskTitle" title="New Task" required /> <button>Add</button> </form> Notice that the INPUT element includes a required attribute. In a Metro application, you can take advantage of HTML5 Validation to validate form fields. If you don’t enter a value for the newTaskTitle field then the following validation error message is displayed: For a brief introduction to HTML5 validation, see my previous blog entry: http://stephenwalther.com/blog/archive/2012/03/13/html5-form-validation.aspx When you click the Add button, the form is submitted and the form submit event is raised. The following code is executed in the default.js file: // Handle Add Task document.getElementById("addTaskForm").addEventListener("submit", function (evt) { evt.preventDefault(); var newTaskTitle = document.getElementById("newTaskTitle"); TaskList.addTask({ title: newTaskTitle.value }); newTaskTitle.value = ""; }); The code above retrieves the title of the new task and calls the addTask() method in the tasks.js file. Here’s the code for the addTask() method which is responsible for actually adding the new task to the IndexedDB database: // Add a new task function addTask(taskToAdd) { var transaction = db.transaction("tasks", IDBTransaction.READ_WRITE); var addRequest = transaction.objectStore("tasks").add(taskToAdd); addRequest.onsuccess = function (evt) { taskToAdd.id = evt.target.result; tasks.dataSource.insertAtEnd(null, taskToAdd); } } The code above does two things. First, it adds the new task to the tasks object store in the IndexedDB database. Second, it adds the new task to the data source bound to the ListView. The dataSource.insertAtEnd() method is called to add the new task to the data source so the new task will appear in the ListView (with a nice little animation). Deleting Existing Tasks The Task List application enables you to select one or more tasks by clicking or tapping on one or more tasks in the ListView. When you click the Delete button, the selected tasks are removed from both the IndexedDB database and the ListView. For example, in the following screenshot, two tasks are selected. The selected tasks appear with a teal background and a checkmark: When you click the Delete button, the following code in the default.js file is executed: // Handle Delete Tasks document.getElementById("btnDeleteTasks").addEventListener("click", function (evt) { tasksListView.winControl.selection.getItems().then(function(items) { items.forEach(function (item) { TaskList.deleteTask(item); }); }); }); The selected tasks are retrieved with the TaskList selection.getItem() method. In the code above, the deleteTask() method is called for each of the selected tasks. Here’s the code for the deleteTask() method: // Delete an existing task function deleteTask(listViewItem) { // Database key != ListView key var dbKey = listViewItem.data.id; var listViewKey = listViewItem.key; // Remove item from db and, if success, remove item from ListView var transaction = db.transaction("tasks", IDBTransaction.READ_WRITE); var deleteRequest = transaction.objectStore("tasks").delete(dbKey); deleteRequest.onsuccess = function () { tasks.dataSource.remove(listViewKey); } } This code does two things: it deletes the existing task from the database and removes the existing task from the ListView. In both cases, the right task is removed by using the key associated with the task. However, the task key is different in the case of the database and in the case of the ListView. In the case of the database, the task key is the value of the task id property. In the case of the ListView, on the other hand, the task key is auto-generated by the ListView. When the task is removed from the ListView, an animation is used to collapse the tasks which appear above and below the task which was removed. The Complete Code Above, I did a lot of jumping around between different files in the application and I left out sections of code. For the sake of completeness, I want to include the entire code here: the default.html, default.js, and tasks.js files. Here are the contents of the default.html file. This file contains the UI for the Task List application: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Task List</title> <!-- WinJS references --> <link href="//Microsoft.WinJS.0.6/css/ui-dark.css" rel="stylesheet"> <script src="//Microsoft.WinJS.0.6/js/base.js"></script> <script src="//Microsoft.WinJS.0.6/js/ui.js"></script> <!-- TaskList references --> <link href="/css/default.css" rel="stylesheet"> <script src="/js/default.js"></script> <script type="text/javascript" src="js/tasks.js"></script> <style type="text/css"> body { font-size: x-large; } form { display: inline; } #appContainer { margin: 20px; width: 600px; } .win-container { padding: 10px; } </style> </head> <body> <div> <!-- Templates --> <div id="taskTemplate" data-win-control="WinJS.Binding.Template"> <div> <span data-win-bind="innerText:title"></span> </div> </div> <h1>Super Task List</h1> <div id="appContainer"> <form id="addTaskForm"> <input id="newTaskTitle" title="New Task" required /> <button>Add</button> </form> <button id="btnDeleteTasks">Delete</button> <div id="tasksListView" data-win-control="WinJS.UI.ListView" data-win-options="{ itemDataSource: TaskList.tasks.dataSource, itemTemplate: select('#taskTemplate'), tapBehavior: 'toggleSelect', selectionMode: 'multi', layout: { type: WinJS.UI.ListLayout } }"> </div> </div> </div> </body> </html> Here is the code for the default.js file. This code wires up the Add Task form and Delete button: (function () { "use strict"; var app = WinJS.Application; app.onactivated = function (eventObject) { if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) { WinJS.UI.processAll().then(function () { // Get reference to Tasks ListView var tasksListView = document.getElementById("tasksListView"); // Handle Add Task document.getElementById("addTaskForm").addEventListener("submit", function (evt) { evt.preventDefault(); var newTaskTitle = document.getElementById("newTaskTitle"); TaskList.addTask({ title: newTaskTitle.value }); newTaskTitle.value = ""; }); // Handle Delete Tasks document.getElementById("btnDeleteTasks").addEventListener("click", function (evt) { tasksListView.winControl.selection.getItems().then(function(items) { items.forEach(function (item) { TaskList.deleteTask(item); }); }); }); }); } }; app.start(); })(); Finally, here is the tasks.js file. This file contains all of the code for opening, creating, and interacting with IndexedDB: (function () { "use strict"; // Create the data source var tasks = new WinJS.Binding.List(); // Open the database var db; var req = window.msIndexedDB.open("TasksDB", 1); req.onerror = function () { console.log("Could not open database"); }; req.onupgradeneeded = function (evt) { var newDB = evt.target.result; newDB.createObjectStore("tasks", { keyPath: "id", autoIncrement:true }); }; // Load the data source with data from the database req.onsuccess = function () { db = req.result; var tran = db.transaction("tasks"); tran.objectStore("tasks").openCursor().onsuccess = function(event) { var cursor = event.target.result; tasks.dataSource.beginEdits(); if (cursor) { tasks.dataSource.insertAtEnd(null, cursor.value); cursor.continue(); } else { tasks.dataSource.endEdits(); }; }; }; // Add a new task function addTask(taskToAdd) { var transaction = db.transaction("tasks", IDBTransaction.READ_WRITE); var addRequest = transaction.objectStore("tasks").add(taskToAdd); addRequest.onsuccess = function (evt) { taskToAdd.id = evt.target.result; tasks.dataSource.insertAtEnd(null, taskToAdd); } } // Delete an existing task function deleteTask(listViewItem) { // Database key != ListView key var dbKey = listViewItem.data.id; var listViewKey = listViewItem.key; // Remove item from db and, if success, remove item from ListView var transaction = db.transaction("tasks", IDBTransaction.READ_WRITE); var deleteRequest = transaction.objectStore("tasks").delete(dbKey); deleteRequest.onsuccess = function () { tasks.dataSource.remove(listViewKey); } } // Expose the data source and functions WinJS.Namespace.define("TaskList", { tasks: tasks, addTask: addTask, deleteTask: deleteTask }); })(); Summary I wrote this blog entry because I wanted to create a walkthrough of building a simple database-driven application. In particular, I wanted to demonstrate how you can use a ListView control with an IndexedDB database to store and retrieve database data.

    Read the article

< Previous Page | 121 122 123 124 125 126 127 128 129 130 131 132  | Next Page >