DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
View Events Video Library
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modern Digital Website Security: Prepare to face any form of malicious web activity and enable your sites to optimally serve your customers.

Containers Trend Report: Explore the current state of containers, containerization strategies, and modernizing architecture.

Low-Code Development: Learn the concepts of low code, features + use cases for professional devs, and the low-code implementation process.

E-Commerce Development Essentials: Considering starting or working on an e-commerce business? Learn how to create a backend that scales.

Avatar

Raymond Camden

[Deactivated] [Suspended]

Senior Developer Evangelist at Adobe

Lafayette, US

Joined Jun 2006

https://www.raymondcamden.com

About

Raymond Camden is a Senior Developer Evangelist for Adobe. He works on the Document Services APIs to build powerful (and typically cat-related) PDF demos. He is the author of multiple books on web development and has been actively blogging and presenting for almost twenty years. Raymond can be reached at his blog (www.raymondcamden.com), @raymondcamden on Twitter, or via email at raymondcamden@gmail.com.

Stats

Reputation: 1696
Pageviews: 2.3M
Articles: 24
Comments: 31
  • Articles
  • Refcards
  • Comments

Articles

article thumbnail
Digging Out Data With Adobe PDF Extract API
Take a look at how the Adobe PDF Extract service can dig out important scientific data buried in PDF libraries.
Updated June 15, 2022
· 4,136 Views · 4 Likes
article thumbnail
Using the PDF Embed API With Vue.js
Getting more control of PDF experiences in the browser.
Updated April 14, 2022
· 12,997 Views · 4 Likes
article thumbnail
Saving Form Data in Client-side Storage
A look at using vanilla JavaScript to automatically store and cache form data as a user enters information.
April 13, 2022
· 2,397 Views · 3 Likes
article thumbnail
Formatting Tips and Tricks for Adobe Document Generation API
Expert tips of formatting control with the Adobe Document Generation API.
Updated April 13, 2022
· 10,665 Views · 5 Likes
article thumbnail
Creating Your Own Schema With the Adobe Document Generation Word Add-in
Learn about Adobe Document Generation API updates to make it simpler to use.
Updated April 11, 2022
· 4,353 Views · 4 Likes
article thumbnail
Document Generation With Dynamic Image Generation
Using dynamic images in a document generation process to make the dynamic even more dynamic.
Updated April 10, 2022
· 11,125 Views · 4 Likes
article thumbnail
Using PDFs With the Jamstack: Adding Search With Text Extraction
Adobe PDF Extraction can help enable search features for your PDF library.
Updated April 9, 2022
· 5,474 Views · 5 Likes
article thumbnail
Using Adobe PDF Services With Amazon Lambda
Learn about Amazon Lambda, a powerful leader in the serverless space and most likely the product most credited for kick-starting the serverless movement.
Updated April 8, 2022
· 4,323 Views · 5 Likes
article thumbnail
Hands-On With Adobe Document Generation API
Adobe Document Generation API will take your Word document template, inject your data, and then output a Word document (or PDF) as the result. How about a simple demo?
Updated March 19, 2022
· 10,644 Views · 7 Likes
article thumbnail
JavaScript: Building Table Sorting and Pagination
Adding sorting and pagination to tables in JavaScript.
March 19, 2022
· 3,297 Views · 4 Likes
article thumbnail
If This, Then That: Conditional Logic and Document Generation
This is a deep dive into conditional logic with Document Generation APIs — this quick read is full of helpful tips and tricks to master this concept today.
Updated March 8, 2022
· 11,689 Views · 5 Likes
article thumbnail
Generating and Protecting Invoices With Adobe Document Generation and PDF Services
An example of using both Adobe Document Generation as well as Adobe PDF Services to dynamically generate and protect a set of PDF invoices.
Updated March 2, 2022
· 19,472 Views · 5 Likes
article thumbnail
Fun (Scary?) Webcam Demo
Using the Windy API to find local public webcams.
January 11, 2022
· 4,504 Views · 2 Likes
article thumbnail
Important Note for Targeting iOS Emulators in Cordova
A great tip to help you work out which emulators are available when testing your applications
October 15, 2015
· 4,424 Views · 2 Likes
article thumbnail
A look at New Relic Browser
while at fluent conf this year, i was walking by the new relic booth when i noticed something interesting – a product called new relic browser. back when i converted my blog to wordpress, i ran into a lot of problems. my server went down, wordpress crashed, it was a bit frustrating. (much like how lemonade in a paper cut is a bit frustrating.) one of the tools i used to help diagnose my server was the new relic server monitor . outside of a few issues installing, i was really impressed with the level of detail the monitor provided. while it wasn’t the final solution for fixing my problem, it definitely helped me pinpoint what was sucking up all the ram on my box, and helped me check my changes to ensure things were going well. best of all, this was entirely free. i’ll give them huge props for offering such a powerful tool for no up front money. because i had such a good experience with them on the server side, i thought i’d give their browser product a try as well. as you can guess, this tool is meant to help you gain insights into how well your web application is performing. i decided to try it on my blog, which, admittedly, is probably not the best use case for this product. wordpress isn’t something i need to hack up and outside of the performance issues i had on the server side, i figured the client side was pretty much good enough. it certainly seemed good enough to me. but at the same time, my blog gets quite a bit of traffic so i figured it would also provide a good set of data to dig into as well. setup is relatively simple. you begin by selecting a deployment method: i selected copy/paste as i figured that would be simpler. on the next page, i said i was not using apm, even though i guess i kinda was. i was trying to test this as someone who was not also using the server side product, so there may be things i missed out on. typically when i try products like this though i try to keep things as simple as possible. the final step was copying a ginormous javascript string into my wordpress template. so that was that. i copied in the code, cleared my wordpress cache, and then promptly forgot about it for a week or so. i then took a look back at my stats. there’s a tremendous amount of information you get right on the front dashboard. first off – note the browser load times. i’m averaging 6.8 seconds or so which is quite high and not what i expected. for over ten years i ran my blog with very precise knowledge of what i had going on within my templates. with wordpress, i’ve kinda gotten lazy about it and have given up being so deeply involved. this gives me a clue that maybe i need to take a closer look at my template and plugins and see if i need everything i’ve got. also note the error graph. on average, 2% of my pages have javascript errors. the real question is – how often do those javascript errors impact the core thing people need to do on my site – read a blog post. as i said, the dashboard is pretty packed, but let’s go deeper. first, the page views report. this report shows recent pages and which page requests are consuming the most load time. you can mouse over each line item for a detailed view: you can also switch the “sort by” to show average page load time: and yes – that twenty plus second item on top there made me crap my pants. honestly i’m not sure why that page averaged so high as it is relatively simple, but it does give me something to dig into deeper. the next link, session traces , is not what you may think. i had assumed this was a report of a ‘session’ for one visitor to my blog. instead, it is a deep look at one particular web page. and when i say deep, i mean deep. here is a top level report for one session: note all the detail in the chart. you can then scroll through the session and look at every particular darn thing in the one request. for example, here i can look at what google analytics is doing. the next report shows you the ajax requests your web app is making. you get details on what is making requests as well as throughput and data size. i can say from experience that the data size chart could be really useful. back when i first learned ajax i made the mistake of not considering the size of my packets and my applications suffered through it. this is a rather long page so i’ve split the screen shot into two parts. i’m thinking that in ‘real’ web app the ajax report will be the number one place you’ll find nuggets of information. of similar importance is the js errors report. clicking on a particular item will give you details: if you click on the instance details, you can see the line number where this error was thrown. while not this particular error, earlier i found an issue with gravatar. i didn’t think i was using gravatar, but it turned out one plugin was making use of it and throwing an error. i modified the plugin and the error went away. the browsers report gives you details about what types of browsers are hitting your site and how well they perform. i mentioned how i was a bit surprised by the page load times on my site, well in this report i can see what browsers are having the worst issues with page load: look at that jump for ie and opera! that’s fascinating to me. it doesn’t necessarily mean those are bad browsers, but it gives me an area to focus in if i were to start digging into my site performance. you can then go to the geo report to see how different areas of the world (and america) handle your site. along with just reporting, you can also create alerts too. you get a default alert policy out of the box and can define your own as well. this is fairly similar to what you get in the server product as well. from what i can see, this is a really darn good tool, and as i said, i had great success with the server tool. so how much does it cost? here is the price plans as of the time i wrote the post: 150 a month isn’t necessarily cheap, but heck, that’s my rate for development (yes, that’s what i charge by the hour) and considering how much data you get the forensic information is easily worth it. the free (lite) version also has fewer reports. if you go to their pricing page you can see what you don’t get at that tier, but note that you get 14 days of free access to the top tier to see if it is worth it.
June 24, 2015
· 477 Views · 0 Likes
article thumbnail
Coldfusion Example: Using jQuery UI Accordion with a ColdFusion Query
A reader pinged me yesterday with a simple problem that I thought would be good to share on the blog. He had a query of events that he wanted to use with jQuery UI's Accordion control. The Accordion control simply takes content and splits into various "panes" with one visible at a time. For his data, he wanted to split his content into panes designated by a unique month and year. Here is a quick demo of that in action. I began by creating a query to store my data. I created a query with a date and title property and then random chose to add 0 to 3 "events" over the next twelve months. I specifically wanted to support 0 to ensure my demo handled noticing months without any data. 01. 04. 05.q = queryNew("date,title"); 06.for(i=1; i<12; i++) { 07. //for each month, we add 0-3 events (some months may not have data) 08. toAdd = randRange(0, 3); 09. 10. for(k=0; k To handle creating the accordion, I had to follow the rules jQuery UI set up for the control. Basically - wrap the entire set of data in a div, and separate each "pane" with an h3 and inner div. To handle this, I have to know when a new unique month/year "block" starts. I store this in a variable, lastDateStr, and just check it in every iteration over the query. I also need to ensure that on the last row I close the div. 01. 02. 03. 04. 05. 06. 07. 08. 09. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. #thisDateStr# 30. 31. 32. 33. 34. 35. 36. #title# 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. And the end result: So, not rocket science, but hopefully helpful to someone. Here is the entire template if you want to try it yourself. 01. 04. 05.q = queryNew("date,title"); 06.for(i=1; i<12; i++) { 07. //for each month, we add 0-3 events (some months may not have data) 08. toAdd = randRange(0, 3); 09. 10. for(k=0; k 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. #thisDateStr# 46. 47. 48. 49. 50. 51. 52. #title# 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63.
November 13, 2014
· 4,177 Views · 0 Likes
article thumbnail
First Release of Cordova Brackets Extension
I blogged about this a few days ago, but I think I'm ready to really release my Cordova Brackets extension. The code is pretty much crap and it's really lacking in providing good feedback while it works, but the initial feature list is complete. Assuming you've got the Cordova CLI installed already, you can, via Brackets: Add and remove platforms. Warning - if Cordova needs to grab the bits for the platform (it does this once), it will be slow, and again, my extension isn't providing feedback about the operation until it is done, so, like, don't do anything. Go get coffee. Emulate for a platform. Not use run. It doesn't work, which means I kinda lied when I said the initial feature list was complete, but I'm OK with that. List plugins, along with the version. Add plugins, and I've got a nice autocomplete so you can quickly find the right plugin. Remove plugins too. There are bugs around this, so, be careful. You can see this in action in this thrilling video below. Oddly it is a bit out of focus for the first few seconds, but then it clears up. I blame gremlins. It is now available via the Extension Manager so you can install it directly from within Brackets. If you want to help work on the source, pull a fork over at https://github.com/cfjedimaster/Cordova-Extension. If you really like it, visit the Amazon wishlist and pick up that Marvel Lego game. ;)
July 21, 2014
· 4,076 Views · 0 Likes
article thumbnail
Cordova Sample: Check for a File and Download if it Isn't There
I've begun work on trying to answer the questions I gathered concerning Cordova's FileSystem support. As I work through the questions I'm trying to build "real" samples to go along with the text. My first sample is a simple one, but I think it is pretty relevant for the types of things folks may do with Cordova and the file system - checking to see if a file exists locally and if not - fetching it. I'll begin by sharing the code and then explaining the parts. Here is the entire JavaScript file for the application. (Earlier today, Andrew Grieve shared a way my code could be simplified by a good 1/3rd. The code below reflects his update and has been changed since my original writing of the blog post.) document.addEventListener("deviceready", init, false); //The directory to store data var store; //Used for status updates var $status; //URL of our asset var assetURL = "https://raw.githubusercontent.com/cfjedimaster/Cordova-Examples/master/readme.md"; //File name of our important data file we didn't ship with the app var fileName = "mydatafile.txt"; function init() { $status = document.querySelector("#status"); $status.innerHTML = "Checking for data file."; store = cordova.file.dataDirectory; //Check for the file. window.resolveLocalFileSystemURL(store + fileName, appStart, downloadAsset); } function downloadAsset() { var fileTransfer = new FileTransfer(); console.log("About to start transfer"); fileTransfer.download(assetURL, store + fileName, function(entry) { console.log("Success!"); appStart(); }, function(err) { console.log("Error"); console.dir(err); }); } //I'm only called when the file exists or has been downloaded. function appStart() { $status.innerHTML = "App ready!"; } Ok, let's break it down. The first step is to check to see if our file exists already. The question is - where should we store the file? If you look at the docs for the FileSystem, you will see that the latest version of the plugin adds some useful aliases for common folders. Unfortunately, the docs are not exactly clear about how some of these aliases work. I asked for help (both on the PhoneGap Google group and the Cordova development list) and got some good responses from Kerri Shotts and Julio Sanchez. The directory that I thought made sense, cordova.file.applicationStorageDirectory, is incorrectly documented as being writeable in iOS. A pull request has already been filed to fix this mistake. For my application, the most appropriate directory is the next one, cordova.file.dataDirectory. Once I have my directory alias, I can make use of resolveLocalFileSystem on the directory plus desired file name to see if it exists. The third argument, downloadAsset, will only be run on an error, in this case a file not existing. If the file does not exist, we then have to download it. For this we use a second plugin, FileTransfer. This is where one more point of confusion comes in. We need to convert that earlier DirectoryEntry object, the one we used to get an API for files and directories, back to a URL so we can give a path to the Download API. So to recap - we've got a few moving parts here. We've got a directory alias, built into the plugin for easily finding common folders for our application. Again, the docs here are currently a bit wrong but they should be corrected soon. From that we can quickly see if our desired file exists, and if not, use the FileTransfer plugin to download it. Simple... but even a simple application caused me a bit of trouble, so hopefully this helps others. You can get the full source code here: https://github.com/cfjedimaster/Cordova-Examples/tree/master/checkanddownload
July 10, 2014
· 14,905 Views · 0 Likes
article thumbnail
My First Native iOS App: Death Clock
A few days ago I returned from a week of Objective-C and iOS training. I wanted to build an app on my own just to see what I could do and how comfortable I felt with the technology away from the Nerd Ranch. While it isn't pretty and the code is probably wrong in multiple ways, I've been able to create a native version of the Death Clock. I used a UINavigationController to handle my views. I like the simple push, pop architecture and that you can disable the navigation bar. I wanted a "full screen" view for my application so that was important. The application is split into two sections. The initial screen is a simple config. For the application I decided to only use birthdate and not gender. I wish there was a bit more control over the data picker widget. It seems huge to me. I spent about 30 seconds on the button so pardon the low tech look. The application also makes use of NSUserDefaults to record your birthdate for future loads. Want to see what this screen looks like? Check it out: // // RKCConfigViewController.m // Death Clock // // Created by Raymond Camden on 3/24/14. // Copyright (c) 2014 Raymond Camden. All rights reserved. // #import "RKCConfigViewController.h" #import "RKCDeathClockViewController.h" @interface RKCConfigViewController() @property (nonatomic, weak) IBOutlet UIDatePicker *birthdayPicker; @property (nonatomic, weak) IBOutlet UIButton *startDeathClock; @property (nonatomic, strong) NSDate *birthday; @end @implementation RKCConfigViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { //check for default NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSDate *defaultBD = [defaults objectForKey:@"Birthday"]; NSLog(@"%@", defaultBD); if(defaultBD) _birthday = defaultBD; else _birthday = [[NSDate alloc] init]; } return self; } - (void)viewDidLoad { [super viewDidLoad]; //no times, just m/d/y _birthdayPicker.datePickerMode = UIDatePickerModeDate; _birthdayPicker.date = _birthday; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; //you weren't born in the future self.birthdayPicker.maximumDate = [[NSDate alloc] init]; //set an initial data _birthday = [[NSDate alloc] init]; } - (IBAction)setBirthDay:(id)sender { _birthday = self.birthdayPicker.date; NSLog(@"Set bday for %@", self.birthday); NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults setObject:_birthday forKey:@"Birthday"]; } - (IBAction)startDeathClock:(id)sender { NSLog(@"CLICK ME BABY"); RKCDeathClockViewController *dvc = [[RKCDeathClockViewController alloc] init]; dvc.birthday = _birthday; [self.navigationController pushViewController:dvc animated:NO]; } @end The second view is the actual counter. This isn't terribly exciting. I've got the actual death date and then the number of seconds. And that's it. Want to see all the code? I created a new GitHub repo so I could store my examples. To be clear, do not consider this anything near "good" iOS programming. I just wanted to share. Objective-C Examples Later this week I think I may try to get this into the App Store. I figure I don't have much chance of it being accepted, but it can't hurt, right?
April 2, 2014
· 2,787 Views · 0 Likes
article thumbnail
AngularJS IndexedDB Demo
over the past few months i've had a series of articles ( part 1 , part 2 , part 3 ) discussing indexeddb. in the last article i built a full, if rather simple, application that let you write notes. (i'm a sucker for note taking applications.) when i built the application, i intentionally did not use a framework. i tried to write nice, clear code of course, but i wanted to avoid anything that wasn't 100% necessary to demonstrate the application and indexeddb. in the perspective of an article, i think this was the right decision to make. i wanted my readers to focus on the feature and not anything else. but i thought this would be an excellent opportunity to try angularjs again. for the most part, this conversion worked perfectly. this may sound lame, but i found myself grinning as i built this application. i'm a firm believer that if something makes you happy then it is probably good for you. ;) i still find myself a bit... not confused... but slowed down by the module system and dependency injection. these are both things i grasp in general, but in angularjs they feel a bit awkward to me. it feels like something i'll never be able to code from memory, but will need to reference older applications to remind me. i'm not saying they are wrong of course, they just don't feel natural to me yet. on the flip side, the binding support is incredible. i love working with html templates and $scope. it feels incredibly powerful. heck, being able to add an input field and use it as a filter in approximately 30 seconds was mind blowing. one issue i ran into and i'm not convinced i created the best solution for was the async nature of indexeddb's database open logic. angularjs has a promises library built in and it works incredibly well for my application in general. but i needed the entire application to be bootstrapped to an async call for database startup. i got around that with two things that felt a bit like a hack. first, my home view (get all notes) ran a call to an init function to ensure the db was already open. so consider this init(): function init() { var deferred = $q.defer(); if(setup) { deferred.resolve(true); return deferred.promise; } var openrequest = window.indexeddb.open("indexeddb_angular",1); openrequest.onerror = function(e) { console.log("error opening db"); console.dir(e); deferred.reject(e.tostring()); }; openrequest.onupgradeneeded = function(e) { var thisdb = e.target.result; var objectstore; //create note os if(!thisdb.objectstorenames.contains("note")) { objectstore = thisdb.createobjectstore("note", { keypath: "id", autoincrement:true }); objectstore.createindex("titlelc", "titlelc", { unique: false }); objectstore.createindex("tags","tags", {unique:false,multientry:true}); } }; openrequest.onsuccess = function(e) { db = e.target.result; db.onerror = function(event) { // generic error handler for all errors targeted at this database's // requests! deferred.reject("database error: " + event.target.errorcode); }; setup=true; deferred.resolve(true); }; return deferred.promise; } this logic is similar to what i had in the non-framework app but i've made use of promises and a flag to remember when i've already opened the database. this lets me then tie to init() in my getnotes logic. function getnotes() { var deferred = $q.defer(); init().then(function() { var result = []; var handleresult = function(event) { var cursor = event.target.result; if (cursor) { result.push({key:cursor.key, title:cursor.value.title, updated:cursor.value.updated}); cursor.continue(); } }; var transaction = db.transaction(["note"], "readonly"); var objectstore = transaction.objectstore("note"); objectstore.opencursor().onsuccess = handleresult; transaction.oncomplete = function(event) { deferred.resolve(result); }; }); return deferred.promise; } all of this worked ok - but i ran into an issue on the other pages of my application. if for example you bookmarked the edit link for a note, you would run into an error. i could have applied the same fix in my service layer (run init first), but it just felt wrong. so instead i did this in my app.js: $rootscope.$on("$routechangestart", function(event,currentroute, previousroute){ if(!persistanceservice.ready() && $location.path() != '/home') { $location.path('/home'); }; }); the ready call was simply a wrapper to the flag variable. so yeah, this worked for me, but i still think there is (probably) a nicer solution. anyway, if you want to check it out, just hit the demo link below. i want to give a shoutout to sharon diorio for giving me a lot of help/tips/support while i built this app. p.s. i assume this is obvious, but i'm not really offering this up as a "best practices" angularjs application. i assume i could have done about every part better. ;)
February 25, 2014
· 16,657 Views · 0 Likes
article thumbnail
IndexedDB and Date Example
about an hour ago i gave a presentation on indexeddb. one of the attendees asked about dates and being able to filter based on a date range. i told him that my assumption was that you would need to convert the dates into numbers and use a number-based range. turns out i was wrong. here is an example. i began by creating an objectstore that used an index on the created field. since our intent is to search via a date field, i decided "created" would be a good name. i also named my objectstore as "data". boring, but it works. var openrequest = indexeddb.open("idbpreso_date1",1); openrequest.onupgradeneeded = function(e) { var thisdb = e.target.result; if(!thisdb.objectstorenames.contains("data")) { var os = thisdb.createobjectstore("data", {autoincrement:true}); os.createindex("created", "created", {unique:false}); } } next - i built a simple way to seed data. i based on a button click event to add 10 objects. each object will have one property, created, and the date object will be based on a random date from now till 7 days in the future. function doseed() { var now = new date(); for(var i=0; i<10; i++) { var daydiff = getrandomint(1, 7); var thisdate = new date(); thisdate.setdate(now.getdate() + daydiff); db.transaction(["data"],"readwrite").objectstore("data").add({created:thisdate}); } } //credit: mozilla developer center function getrandomint (min, max) { return math.floor(math.random() * (max - min + 1)) + min; } note that since indexeddb calls are asynchronous, my code should handle updating the user to let them know when the operation is done. since this is just a quick demo though, and since that add operation will complete incredibly fast, i decided to not worry about it. so at this point we'd have an application that lets us add data containing a created property with a valid javascript date. note i didn't change it to milliseconds. i just passed it in as is. for the final portion i added two date fields on my page. in chrome this is rendered nicely: based on these, i can then create an indexeddb range of either bounds, lowerbounds, or upperbounds. i.e., give me crap either after a date, before a date, or inside a date range. function dosearch() { var fromdate = document.queryselector("#fromdate").value; var todate = document.queryselector("#todate").value; var range; if(fromdate == "" && todate == "") return; var transaction = db.transaction(["data"],"readonly"); var store = transaction.objectstore("data"); var index = store.index("created"); if(fromdate != "") fromdate = new date(fromdate); if(todate != "") todate = new date(todate); if(fromdate != "" && todate != "") { range = idbkeyrange.bound(fromdate, todate); } else if(fromdate == "") { range = idbkeyrange.upperbound(todate); } else { range = idbkeyrange.lowerbound(fromdate); } var s = ""; index.opencursor(range).onsuccess = function(e) { var cursor = e.target.result; if(cursor) { s += "key "+cursor.key+""; for(var field in cursor.value) { s+= field+"="+cursor.value[field]+""; } s+=""; cursor.continue(); } document.queryselector("#status").innerhtml = s; } } the only conversion required here was to take the user input and turn it into "real" date objects. once done, everything works great: you can run the full demo below.
June 7, 2013
· 6,213 Views · 0 Likes
article thumbnail
Capturing camera/picture data without PhoneGap
As people know, I'm a huge fan of PhoneGap and what it allows me to do with JavaScript, HTML, and CSS. But I think it is crucial to remember that you don't always need PhoneGap. A great example of that is camera access. Did you know that recent mobile browsers support accessing the camera directly from HTML and JavaScript? Let's look at an example. Over a year ago I wrote a blog post where I created an application called "Color Thief." This application made use of PhoneGap's Camera API and a third party JavaScript library called Color Thief. I loved this example because it demonstrated how you could combine the extra power that PhoneGap provides along with existing JavaScript libraries. This morning I watched an excellent Google IO presentation (https://www.youtube.com/watch?v=EPYnGFEcis4&feature=youtube_gdata_player) on Mobile HTML. It was an overview of some of the exciting stuff you can now do with mobile HTML and JavaScript. To be clear, this was all without using wrappers like PhoneGap. In one of the examples the presenters discussed the new "capture" support for the input/file field type. This is rather simple to implement: If supported (recent Android and latest iOS), the user can then use their camera to select a picture. I decided to rebuild my old demo to skip PhoneGap completely and just make use of this feature. Here's the code: For the most part, this is pretty similar to the last version. I no longer wait for the deviceready event, but instead just listen for the document itself to load. Instead of listening for a button click, I've switched to a input field using type=file. I now listen for the change event, and on that, I see if I have access to a file. If I do, I can then use the URL object to create a pointer to the source and then simply add it to my DOM. After that, Color Thief takes over. The only tricky part I ran into was that in iOS the URL object is still prefixed. You can see how I get around that in the startup code. To be fair, this isn't 100% backwards compatible, I could add a few checks in here to ensure that things will work and gracefully let people on older phones know they can't use this feature. But the end result is nearly the exact same functionality in a web page - no PhoneGap, no native code. <br>
May 21, 2013
· 16,120 Views · 0 Likes
article thumbnail
IndexedDB in Action: Complete Sample App
After a bit more sweat and tears, I've now got a "full" (if ugly) example of an IndexedDB application. It allows you to create and delete simple notes. You can view this demo here: http://www.raymondcamden.com/demos/2012/apr/30/test5.html Right now this demo is Firefox only. It doesn't work in Chrome because of the bug I mentioned in my earlier blog post. Here's the code - and again - I want to mention (and credit) the excellent MDN tutorial for making this easier to build. Notes Add Note Save Note Nothing too scary, right? Using method chaining makes the code a bit more palatable and simpler to work with. After getting this working, I began to look at how you can retrieve data. I guess I shouldn't be surprised (and @thefalken pointed it out to me), but you are limited to primary key lookups only. So let me make sure that is clear. This is not a replacement for WebSQL. You cannot search. I guess - technically - you could search if you load everything up and iterate over it, but that's not really efficient. You can do range based filters, so for example, given a set of names I could go from Bob to Mary, but if I wanted to quickly find all the objects with property X set to Y and property Z set to A, then I'm out of luck. I was really thinking this was a Mongo-ish type solution, but I was wrong. I don't know about you - but this is kind of disappointing. Maybe my opinion will change, but right now I'm sad that WebSQL is being dumped for this.
May 3, 2012
· 7,551 Views · 0 Likes
article thumbnail
Multiple File Upload is Easy in HTML5
this won't be a terribly long post, nor one that is probably informative to a lot of people, but i finally got around to looking at the html5 specification for multiple file uploads (by that i mean allowing a user to pick multiple files from one file form field). i knew it existed i just never got around to actually looking at it. turns out it is incredibly simple. you take a file form field: and you add multiple to it (or multiple="multiple"). and... yeah, that's it. even better, it degrades perfectly. so in chrome it works, and your label switches from... to... i kept waiting for the "but, wait" moment and it never came. in ie where it fails to work, it simply remains a file upload control that works with one file, not many. because it's so simple and fallback is so good, i can't see really bothering to use another solution, like a flash uploader, but you could do a bit of massaging for it. so for example, consider if my form had the following label: multiple file: in ie, the user won't be able to select multiple files. while not the end of the world, it kind of bugs me that the label may mislead the user into trying something they can't do. (and as we know, the user will blame us, not ie.) so what to do? i did some basic research into how to use javascript to detect features. i found a few good examples that basically suggested creating a temporary dom item like so: var el = document.createelement("input"); but here's where i had issues. most of the links i found discussed how to detect new html form types , like range for example. these techniques worked by setting the type on the new element to the type you want to test and then immediately checking to see if the type still has the same value. but what about attributes? turns out dive into html5 has a great article on this. when you have your dom item, you can simply ask if the item exists. here is an example: function supportmultiple() { //do i support input type=file/multiple var el = document.createelement("input"); return ("multiple" in el); } so given that, i modified my mark up a bit. i changed the label in front of my form and hid the word "multiple": multiple file: i then added an init method to my body tag and used the following code: function supportmultiple() { //do i support input type=file/multiple var el = document.createelement("input"); return ("multiple" in el); } function init() { if(supportmultiple()) { document.queryselector("#multiplefilelabel").setattribute("style",""); } } and that worked like a charm. ie say just "file" whereas chrome and firefox had the new hotness. so yeah - that's a lot of writing about a simple little thing, but... dare i say it... i'm really getting jazzed up about html again! here's my entire test template if you want to cut and paste: normal text: multiple file: p.s. so how you actually process the upload depends on your server. my coldfusion readers are probably wondering how it handles this. good news, bad news. the bad news is that coldfusion can't (as far as i and other smarter peoiple know) handle this at all. if you want to do this in coldfusion 9, use the flash based multifile uploader instead. the good news is that coldfusion 10 handles it just file. be sure to use action value of "uploadall" of your cffile tag.
February 29, 2012
· 99,613 Views · 0 Likes

Refcards

Refcard #191

Getting Started With PhoneGap

Getting Started With PhoneGap

Comments

Digging Out Data With Adobe PDF Extract API

Apr 30, 2022 · Raymond Camden

I'm not sure. I need to make an edit and I'll see if they can move it

Using MobileFirst SQL Adapters with an Ionic Application

Oct 16, 2018 · grspain

Sorry I haven't used any of these techs in a while.

Using Loopback to Build APIs for APIs

Dec 13, 2017 · Sarah Davis

I was just about to share the URL - thank you!

Cordova/Ionic Sample App: My Sound Board

Jul 21, 2017 · John Walter

Sorry - I'm not sure what you mean. You had to add a physical speaker to your device? Please email me directly as I do not check comments here.

Ionic 2 First Drive: Making an RSS Reader

Feb 28, 2016 · James Sugrue

Ionic2 is a hybrid app so yes - the UI is the web view, althogh it is possible to use native UI components. For example, you can use native dialogs.

Important Update for Apache Cordova and Android

Dec 09, 2015 · James Sugrue

Nope - I did not. FYI, in the future, please comment on my blog itself. I didn't even know this comment existed. ;)

Dynamic Language IDEs: Aptana Ruby and DLTK Ruby

May 02, 2015 · Umberto Zappia

Err... so it is working?

Dynamic Language IDEs: Aptana Ruby and DLTK Ruby

May 02, 2015 · Umberto Zappia

Err... so it is working?

Dynamic Language IDEs: Aptana Ruby and DLTK Ruby

May 02, 2015 · Umberto Zappia

Err... so it is working?

Dynamic Language IDEs: Aptana Ruby and DLTK Ruby

May 02, 2015 · Umberto Zappia

Err... so it is working?

IndexedDB and Date Example

May 02, 2015 · Allen Coin

Err... so it is working?

IndexedDB and Date Example

May 02, 2015 · Allen Coin

Err... so it is working?

IndexedDB and Date Example

May 02, 2015 · Allen Coin

Err... so it is working?

IndexedDB and Date Example

May 02, 2015 · Allen Coin

Err... so it is working?

Microsoft Delivers a Blow to Open Source with Visual Studio 11

May 28, 2012 · Norm Chow

I'm downvoting the idiocy of how charging for a tool mean MS is attacking open source.
HTML5 Form Validation - The Constraint Validation API

Mar 22, 2012 · Amilia Crux

Hey vgrenete, why the vote down? I'm the author of the entry so just curious.
Language Comparison: Compute Factorial - Groovy, Java, and ColdFusion

May 19, 2011 · mitchp

Here are two working examples. One using a loop, one using recursion. The loop is based on Rob Brooks-Bilson's UDF from CFLib.org. I just slimmed it down a bit. Was going to paste code, but it's too much trouble to encode: http://pastebin.com/CT4f2ME1
Language Comparison: Compute Factorial - Groovy, Java, and ColdFusion

May 19, 2011 · mitchp

The ColdFusion code sample is _seriously_ broken. I'm assuming a bad paste. But folks - please do not assume that is valid CFML.
Linux command line tips: job management

Apr 11, 2011 · Nick Gibson

All versions have an admin - so that's not a problem. And yeah - I can see how the EFR could be explained a bit nicer. It's a bit clear in the PDF I think, but not the HTML version.
6 Reasons Why Our Start Up Company Uses ColdFusion

Apr 11, 2011 · mitchp

All versions have an admin - so that's not a problem. And yeah - I can see how the EFR could be explained a bit nicer. It's a bit clear in the PDF I think, but not the HTML version.
Linux command line tips: job management

Apr 07, 2011 · Nick Gibson

@Michael: What features are only available in Ent? As far as I know, it's limit to CAR backups and the Admin API. Everything else is simply throttled a bit slower.

Wow - your view on PHP OS is the first I've heard. I've always been told PHP > CF because of all the OS libraries out there. It's nice to hear a perspective like this. Obviously, it can apply to CF OS as well. Not everything out there is supurb.

6 Reasons Why Our Start Up Company Uses ColdFusion

Apr 07, 2011 · mitchp

@Michael: What features are only available in Ent? As far as I know, it's limit to CAR backups and the Admin API. Everything else is simply throttled a bit slower.

Wow - your view on PHP OS is the first I've heard. I've always been told PHP > CF because of all the OS libraries out there. It's nice to hear a perspective like this. Obviously, it can apply to CF OS as well. Not everything out there is supurb.

Linux command line tips: job management

Apr 06, 2011 · Nick Gibson

@Jakob: No, ColdFusion did not kill MySpace. Poor programming and design decisions did -just as it would kill _any_ web site. Their CTO (CEO? I forget) once bragged that they simply threw stuff up on the server w/o testing.

@Michael: Just a few small counter parts. Much like PHP/Perl had Excel support for years via libraries, so did CF. What you saw in CF9 was _baked in_ support for Excel, ie, no need to go to an external library. While CF's open source libraries may not yet compare to what is available for PHP, there _is_ quite a bit out there. Have a look at the close to 900 ColdFusion related OS projects at RIAForge and the number of UDFs available at CFLib.org. Again - not saying there is much available as PHP, but there's a strong presense. :)

6 Reasons Why Our Start Up Company Uses ColdFusion

Apr 06, 2011 · mitchp

@Jakob: No, ColdFusion did not kill MySpace. Poor programming and design decisions did -just as it would kill _any_ web site. Their CTO (CEO? I forget) once bragged that they simply threw stuff up on the server w/o testing.

@Michael: Just a few small counter parts. Much like PHP/Perl had Excel support for years via libraries, so did CF. What you saw in CF9 was _baked in_ support for Excel, ie, no need to go to an external library. While CF's open source libraries may not yet compare to what is available for PHP, there _is_ quite a bit out there. Have a look at the close to 900 ColdFusion related OS projects at RIAForge and the number of UDFs available at CFLib.org. Again - not saying there is much available as PHP, but there's a strong presense. :)

The language wars and the TIOBE index

Feb 15, 2010 · Christopher Wong

A vote up for me because it helps demonstrate how flawed TIOBE is.
List of Open Source Defect/Issue Tracking Systems

Nov 21, 2009 · guru js

I can think of quite a few he missed (especially in the ColdFusion world), but unfortunately he has closed the comments on his blog and doesn't seem to provide a way to contact him.
A Fast Gateway to OOP in Java using NetBeans IDE

Feb 18, 2008 · Lebon Bon Lebon

But if part of switcihng to MG is to remove dependancies on things like Form versus URL, why would you _add_ dependancies back in when you have a NON dependant way of getting the same info?

"Bad" may be too strong a word - but I do think it would be "better". ;)

Get All Form Fields in ModelGlue the Elegant Way

Feb 18, 2008 · Boyan Kostadinov

But if part of switcihng to MG is to remove dependancies on things like Form versus URL, why would you _add_ dependancies back in when you have a NON dependant way of getting the same info?

"Bad" may be too strong a word - but I do think it would be "better". ;)

A Fast Gateway to OOP in Java using NetBeans IDE

Feb 18, 2008 · Lebon Bon Lebon

I have a few small problems with this. First off - you mention that everytime you change your form you have to change your bean. Normally you change your model first. Ie, if I add a new column to my Foo type, I'd update my model CFCs, and then any views (including the form), that would take it.

Secondly, your use of getValue("fieldNames") is a mistake in my book. It ties your controller code to a HTTP Form. What if you switch to a Flex front end? MG already has a built in way to get all the values - event.getAllValues().This will return a struct of all values in the Event scope and is (imho) the "proper" way to do it.

Get All Form Fields in ModelGlue the Elegant Way

Feb 18, 2008 · Boyan Kostadinov

I have a few small problems with this. First off - you mention that everytime you change your form you have to change your bean. Normally you change your model first. Ie, if I add a new column to my Foo type, I'd update my model CFCs, and then any views (including the form), that would take it.

Secondly, your use of getValue("fieldNames") is a mistake in my book. It ties your controller code to a HTTP Form. What if you switch to a Flex front end? MG already has a built in way to get all the values - event.getAllValues().This will return a struct of all values in the Event scope and is (imho) the "proper" way to do it.

What shouldn't you be doing in ColdFusion?

Sep 26, 2007 · Gerd Storm

And your comments are helpful how?

User has been successfully modified

Failed to modify user

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: