tag:blogger.com,1999:blog-19557390174124089852024-03-13T13:45:07.140-07:00The Hard WayNothing is easy. Everything is hard. <br>
Please update your documentation.metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.comBlogger81125tag:blogger.com,1999:blog-1955739017412408985.post-11996481770584915682022-03-04T12:32:00.000-08:002022-03-04T12:32:09.792-08:00Angular: Can't bind to 'ngIfContext' since it isn't a known property of 'ng-container'<p>After a bit of refactoring our codebase this error started showing up during tests.</p>
<pre class="brush:plain">Can't bind to 'ngIfContext' since it isn't a known property of 'ng-container'</pre>
<p>I found a few results from google but nothing that solved the problem. I started pulling out <b>*ngIf</b> from the tags in the template that was linked to the component and finally found the line causing the problem.</p>
<pre class="brush:html"><ng-container *ngIf="group.subgroups; else singleGroup; context: {$implicit: group }"></pre>
<p><b>*ngIf</b> does not support the <i>context</i> argument. The <i>context</i> argument works on <b>*ngTemplateOutlet</b> property.</p>metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com0tag:blogger.com,1999:blog-1955739017412408985.post-322170694718148242021-05-06T15:31:00.006-07:002021-05-06T15:55:26.640-07:00RxJs / Angular: Changing a request parameter after a failure using retry<p>I'm making a request for a window of data based on a date and a range. The result of the request can be empty requiring me to make another request and change some parameters. The previous way I made the request was a recursive function that worked well but it can be a lot better.</p><p>Using a combination of rxjs pipe operators this can be one chain that works beautifully.</p><p> </p>
<pre class="brush:javascript">constructor(private http: HttpClient){}
someFunction() {
const retryObject = { foo: 1};
return of(retryObject)
.pipe(
switchMap(obj => {
return this.http(`http://some.name?foo=${obj.foo}`);
}),
map(result => {
if (result.error) {
// Update the foo value and it will try the request again with the new value
retryObject.foo++;
throw 'an error happened';
}
// Happy path
}),
retry([HOW MANY TIMES YOU WANT TO TRY THE REQUEST])
).subscribe(result => {
// Do something with your data
})
}
</pre>
<p>The magic here is the <a href="https://www.learnrxjs.io/learn-rxjs/operators/error_handling/retry" target="_blank">retry</a> pipe in combination with throwing an error. The linked page used throwError but it didn't retry the request. You can't pass in a string or number into the of operator. Javascript is pass-by-value for those. You need a reference to an object that can be updated.</p>metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com0tag:blogger.com,1999:blog-1955739017412408985.post-38697585872153031722015-10-02T12:53:00.001-07:002015-10-02T14:03:47.861-07:00Ionic Framework / UI Router: Remove a query parameter from the URII've been working with Ionic Framework for most of the year and finally launched the alpha version of my project. I've enjoyed working with it, but like everything you'll run into something that makes you bang your head on the desk for a few days. The most recent case of this was trying to remove a parameter from the URI.<br />
<br />
If a user needs to reset their password I send them a URI that looks something like this.<br />
<b>http://this.that/login?resetKey=1234</b><br />
<br />
After the user finishes the steps to reset I want to clean up the URI so if they hit the refresh button it doesn't trigger the reset process again.<br />
<b>http://this.that/login</b><br />
<br />
I had the worse time finding an answer on google. After a few days of digging through <a href="http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$state" target="_blank">UI Router documentation</a> I finally found a combination that worked.<br />
<br />
First you need to inject the <b>$state</b> param into your controller. We'll use the <b>go</b> method and redirect to the current URI using the current router name. The current route name can be accessed through the <b>$state.current.name</b> property.<b> </b>Next we need to specify the parameter we want to remove from the URI. We'll use an object with the key as the param name and the value will be null. Lastly we don't want to trigger the route again so we'll set the <i>notify</i> property to false.<br />
<br />
The final command looks like this.<br />
<pre class="brush:javascript">$state.go($state.current.name,{'resetKey': null},{'notify': false});
</pre>
<br />
Such a simple command. So much digging. UGH!metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com0tag:blogger.com,1999:blog-1955739017412408985.post-5351810957056262142015-06-23T16:56:00.001-07:002015-06-24T09:57:15.929-07:00HTML / CSS 3: Progress bar exampleI've been working with the progress element and trying to get it to look nice across different browsers. It doesn't help that most of the styling elements are pseudo elements.<br />
<br />
<a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress" target="_blank">Here's the MDN page on the progress element</a>.<br />
<br />
The big issue I ran into was trying to style the element for Chrome and Firefox.<br />
Chrome uses the following styles to change the look of the element:<br />
<br />
progress::-webkit-progress-bar<br />
This will style the background of the progress bar.<br />
<br />
progress::-webkit-progress-value<br />
This will style the growing value inside of the progress bar.<br />
<br />
Firefox uses the following value:<br />
progress::-moz-progress-value<br />
This will only let you style the growing value inside of the progress bar. You can't style the background.<br />
<br />
The other catch is you can't combine the values in your css. For example this won't work<br />
<br />
<pre class="brush: css">progress::-moz-progress-value,
progress::-webkit-progress-value{
}
</pre>
<br />
None of your styles will take and the bar will fall back to it's unstyled default.<br />
<br />
Here's the html I was playing with.<br />
<a href="https://jsfiddle.net/metric152/ztdag5v5/11/" target="_blank">Here's a link to a jsFiddle of the following code</a><br />
<br />
<pre class="brush: xml"><progress class="progress-bar" max="100" value="30"></progress>
</pre>
<pre class="brush: css">/* http://www.hongkiat.com/blog/html5-progress-bar/ */
.progress-bar{
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
/* Can't share styles. Chome gets angry */
/* FF style the progress bar */
.progress-bar::-moz-progress-value{
background: #3399ff;
border-radius: 12px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25) inset;
}
/* Chrome style the background of the progress bar */
.progress-bar::-webkit-progress-bar{
background: silver;
border-radius: 12px;
}
/* Chrome style the progress value */
.progress-bar::-webkit-progress-value{
background: #3399ff;
border-radius: 12px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25) inset;
}
</pre>
metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com0tag:blogger.com,1999:blog-1955739017412408985.post-75215157248233052592014-09-17T15:00:00.001-07:002014-09-17T15:01:26.770-07:00Sencha Touch: Android Halo Light ThemeOne of the things I love about Sencha Touch is the <a href="http://www.sencha.com/blog/new-themes-in-sencha-touch-2-2/" target="_blank">built in themes</a>. Android has 4.x has two themes: Halo Dark, Halo Light. There is only one Android theme for Sencha Touch and it's dark. I've been bugging them for awhile to include a light theme and their response was "<a href="https://twitter.com/SenchaMitch/status/476497954921279489" target="_blank">You do it</a>".<br />
<br />
I googled for a long time and couldn't find a theme someone else did. I gave in and decided to make my own theme after finding <a href="http://kawanoshinobu.com/2013/07/hello-sencha-touch-flat-ui-theme/" target="_blank">this one</a>. It's beautiful. I read his breakdown and he created a theme by copying the winPho theme and made changes until he was happy. I did something similar. I copied the Android theme and started digging in.<br />
<br />
That's when I found it. There is a Sass variable in /[Sencha SDK folder]/resources/themes/stylesheets/sencha-touch/mountainview/var/_Class.scss called $dark-theme. If you set this variable to false in your local sass file for android it becomes a light theme.<br />
<br />
I wish this was explained better. It's only through source code diving can we find the true answers.metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com0tag:blogger.com,1999:blog-1955739017412408985.post-31576466105332202222014-09-17T14:42:00.001-07:002014-09-17T14:44:23.866-07:00Zend Framework 2: Using mysql functions in SQL classesThe built in ZF2 classes for sql queries have been wonderful to use. I like that it takes care of escaping data and saves you from messy string all over your codebase. I ran into a problem when trying to do something "complex".<br />
<br />
Here is an example of the SQL I was trying to write.<br />
<pre class="brush: sql">INSERT into `table` SET `col1` = FROM_UNIXTIME(?)
</pre>
<br />
When I tried running this the mysql method was quoted<br />
<pre class="brush: sql">`FROM_UNIXTIME(?)`</pre>
I started digging around and found an extra class required if you want to use functions in the escaped data spot. <a href="http://framework.zend.com/apidoc/2.3/classes/Zend.Db.Sql.Expression.html" target="_blank">It's called an expression</a>. Here is how they're used in the insert class.<br />
<br />
<pre class="brush: php">$insert->into($tableName)
->values([`col` => new \Zend\Db\Sql\Expression("FROM_UNIXTIME(?)","?", [\Zend\Db\Sql\Expression::TYPE_VALUE])]);
</pre>
<pre class="brush: php"></pre>
Now the function won't be quoted and the value can be safely escaped when execute is run.<br />
<br />
<br />
<a href="http://framework.zend.com/manual/2.3/en/modules/zend.db.sql.html#expression-expression-parameter" target="_blank">Here's some documentation on how expressions are used in a where clause.</a>metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com0tag:blogger.com,1999:blog-1955739017412408985.post-29931126362377812512014-07-28T11:46:00.003-07:002014-08-02T00:36:38.090-07:00Angular: Form element not attaching to $scopeI'm well into a redesign using AngularJS as my front-end framework. After a small learning period I'm in love. It's a fantastic way to tie your UI to your backend. That said there is still some work to be done.<br />
<br />
I'm breaking my project into modules that are included with the <a href="https://docs.angularjs.org/api/ng/directive/ngInclude" target="_blank">ng-include</a> tag. This helps shrink the code on the page into manageable chunks. It nice when you're using a <a href="http://getbootstrap.com/javascript/#modals" target="_blank">very verbose</a> framework like Bootstrap.<br />
<br />
All of my forms are wired up using <a href="https://docs.angularjs.org/guide/forms" target="_blank">Angular's form validation</a>. Once again this is fantastic. Being able to watch the inputs in real time and display helpful errors is great. I ran into an issue trying to reuse a form after I've removed it from the users view.<br />
<br />
<pre class="brush:html"><form name="createUser">
<input name="name" ng-model="formObj.name" />
<input name="email" ng-model="formObj.email" />
</form>
</pre>
<br />
I should be able to access the form in my angular in this fashion.
<br />
<br />
<pre class="brush:js">// This will reset any validation errors on the form
$scope.createUser.$setPristine();
</pre>
<br />
This wasn't working for me and I spent a lot of time trying to figure out why. Here is how my code looked.
<br />
<br />
<pre class="brush:html"><div ng-controller=“controllerName”>
<div ng-include=“ ‘path-to-the-template’ ”></div>
</div>
<!—- Inside path-to-the-template -—>
<form name="createUser">
<input name="name" ng-model="formObj.name" />
<input name="email" ng-model="formObj.email" />
</form>
</pre>
<br />
One thing to consider is when Angular is starting up the controller code the form isn't attached yet. When you click the button that submits the form it will be attached by that time. I was still unable to access the form element.<br />
<br />
<h3>
<b>Update</b></h3>
I submitted this as a <a href="https://github.com/angular/angular.js/issues/8403#issuecomment-50565265" target="_blank">bug to the git repo</a> and got a response very quickly. That team is really on top of things. Turns out when you use ng-include it creates a new scope var. This is how the setup should look.<br />
<br />
<pre class="brush:html"><!—- The vars should live in the controller. I placed them here for the example. -—>
<div ng-controller=“controllerName” ng-init="form={}; model={}" >
<div ng-include=“ ‘path-to-the-template’ ”></div>
</div>
<!—- Inside path-to-the-template -—>
<form name="form.createUser">
<input name="name" ng-model="model.name" />
<input name="email" ng-model="model.email" />
</form>
</pre>
<br />
Now the include can reference the variables from the parent scope. The form and it's input should now be accessible.metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com2tag:blogger.com,1999:blog-1955739017412408985.post-16554410896072273782014-06-27T11:12:00.002-07:002014-06-27T11:17:04.763-07:00Zend Framework 2.x Learn ZF2 by Example: Protecting our Pages - Authentication typeI'm starting to implement authentication on my web app and I ran into a problem with the example in the book.<br />
<br />
The example on page 146 uses MD5 as a encryption scheme.<br />
<br />
<pre class="brush:php">$adapter = new DbAdapter($db,
'users',
'login',
'password',
'MD5(password)');
</pre>
<br />
The adapter builds a simple SQL query that will check the table, match the user name and password then let you know if it's valid. The problem lies in the 5th parameter. When I tried to match an account I know works it kept saying the account wasn't valid. After digging into <a href="http://framework.zend.com/manual/2.0/en/modules/zend.authentication.adapter.dbtable.html#advanced-usage-by-example" target="_blank">the documentation</a> I found the 5th parameter wasn't configured right. It should be 'MD5(?)'.<br />
<br />
<pre class="brush:php">$adapter = new DbAdapter($db,
'users',
'login',
'password',
'MD5(?)');
</pre>
<br />
After the change the auth adapter works perfectly. Hope this helps save you some time.metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com0tag:blogger.com,1999:blog-1955739017412408985.post-28150176453228098892014-06-05T14:31:00.001-07:002014-06-05T14:54:44.977-07:00Sencha Touch Themes: Using built-in themes for iOS and AndroidOne of the things I like about Sencha Touch is the built in device themes. I like being able to make a web app look native.<br />
<br />
I <a href="http://docs.sencha.com/touch/2.3.1/#!/guide/theming" target="_blank">found</a> <a href="http://www.sencha.com/blog/top-5-tips-get-started-with-the-latest-sencha-product-releases/" target="_blank">many</a> <a href="http://www.sencha.com/blog/new-themes-in-sencha-touch-2-2" target="_blank">resources</a> that talked about the themes but none gave very good instructions on how to make them work. I finally found a <a href="http://vimeo.com/66191847" target="_blank">video</a> that walked you through some of the process involved in making themes work. It left out some important stuff that I found through lots of trial and even more error.<br />
<br />
I'll show you how to apply a theme to the default sencha project. You can apply these steps to your own project.<br />
<br />
<ol>
<li>Create an example app.</li>
<ul>
<li>sencha -sdk [path to sdk] generate app [AppName] [path]</li>
</ul>
<li>You'll need to create scss files for the different platforms you want to support.</li>
<ul>
<li>cupertino.scss (iOS 7 styling)</li>
<li>cupertino-classic.scss (iOS 6 styling) </li>
<li>mountainview.scss (Android)</li>
</ul>
<li>Each of these files will include two imports lines that define our theme styles.<br /><div class="p1">
<br />
@import '<span class="s1">sencha</span>-touch/<span class="s1">[platform name]</span>';</div>
<div class="p1">
@import '<span class="s1">sencha</span>-touch/[platform name]/all';<br />
<br />
[platform name] is the name of the style you're including. cupertino.scss will use "cupertino" and mountainview.scss will use "mountainview". All the platform names <a href="http://www.sencha.com/blog/top-5-tips-get-started-with-the-latest-sencha-product-releases/" target="_blank">are available here under tip 2</a>.</div>
</li>
<li><div class="p1">
Next you'll need to run "compass compile" or "compass watch" in the resources/sass folder. </div>
</li>
<li><div class="p1">
Now we have to update app.json to include the new css files that were generated by compass. Look for the css option and add each platform as an object to the css array.</div>
<div class="p1">
{</div>
<div class="p1">
"path": "resources/css/cupertino.css",</div>
<div class="p1">
"platform": ["ios"],</div>
<div class="p1">
"update": "delta"</div>
<div class="p1">
}<br />
<br />
Make sure to update the platform value with the appropriate value. The options <a href="http://docs.sencha.com/touch/2.3.1/#!/guide/theming" target="_blank">are available here under available platforms</a>.<br />
<br />
<b>IMPORTANT NOTE</b>:<b> </b>Make sure to add the "platform": ['desktop'] to the app.css entry. If you don't app.css will be included in every theme and it will break the display. </div>
<div class="p1">
<br /></div>
</li>
<li><div class="p1">
Lastly you'll need to run sencha app build to bring everything together. You can test the different templates by appending ?platform=[platform name] to your uri.<br />
eg: senchaapp.io/?platform=ios</div>
</li>
</ol>
<div>
<a href="https://github.com/metric152/sencha-themes" target="_blank">I've added the example project to github</a> so you can pull that down as an example.</div>
metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com0tag:blogger.com,1999:blog-1955739017412408985.post-53513169453498539362014-04-22T19:04:00.000-07:002014-04-22T19:04:13.997-07:00Zend Framework 2 & MAMP : Memory IssuesI ran into a problem working through the tutorial for Learn ZF2 for form validation. I reached the section where the form data would be inserted into a database and that wasn't possible using the command line PHP server. I decided to switch to MAMP because it has more stuff baked in.<br />
<br />
I quickly ran into an issue that was tough to track down. After added the database code the form no longer submitted. After ripping out lots of code and not finding an answer I called it a night. The next day I figured out the problem was with MAMP not my code. If I disabled the file validation on the form everything worked fine.<br />
<br />
This was the error I ran into<br />
<pre>Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 32 bytes) in /Volumes/zend_framework/learnzf2/vendor/zendframework/zendframework/library/Zend/Stdlib/ErrorHandler.php on line 113
</pre>
<br />
Not the most straight forward bug. Turns out the issue is the command line PHP server has a larger memory_limit size. It's 128M while MAMP is set to 32M. It overflowed after processing the file. After upping memory_limit to 128M and restarting the server everything worked fine.<br />
<br />
The memory_limit var is stored in php.ini. It can be reached by using<br />
File => Edit template => php => php 5.4
<br />
Find memory_limit and change it to 128M.metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com0tag:blogger.com,1999:blog-1955739017412408985.post-69268093798910693802014-04-09T15:41:00.000-07:002014-04-09T15:41:23.689-07:00Zend Framework 2.x Learn ZF2 by Example : Unable to render templateGetting to the MVC portion of the book and ran into an error. On page 59 it shows you how to manually include a template to aid debugging. I ran into this error when trying to see my changes.<br />
<br />
<br />
<pre>Fatal error: Uncaught exception 'Zend\View\Exception\RuntimeException' with message 'Zend\View\Renderer\PhpRenderer::render: Unable to render template "debug/layout/sidebar"; resolver could not resolve to a file' in /Volumes/zend_framework/learnzf2/vendor/zendframework/zendframework/library/Zend/View/Renderer/PhpRenderer.php:498 Stack trace: #0 /Volumes/zend_framework/learnzf2/vendor/zendframework/zendframework/library/Zend/View/View.php(205): Zend\View\Renderer\PhpRenderer->render(Object(Zend\View\Model\ViewModel)) #1 /Volumes/zend_framework/learnzf2/vendor/zendframework/zendframework/library/Zend/Mvc/View/Http/DefaultRenderingStrategy.php(102): Zend\View\View->render(Object(Zend\View\Model\ViewModel)) #2 [internal function]: Zend\Mvc\View\Http\DefaultRenderingStrategy->render(Object(Zend\Mvc\MvcEvent)) #3 /Volumes/zend_framework/learnzf2/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(468): call_user_func(Array, Object(Zend\Mvc\MvcEvent)) #4 /Volumes/zend_framework/learnzf2/vendor/zendframe in /Volumes/zend_framework/learnzf2/vendor/zendframework/zendframework/library/Zend/View/Renderer/PhpRenderer.php on line 498
</pre>
<br />
Page 58 talks about the way templates are included. The middle of the page shows a config option called '<b>template_path_stack</b>'. This is the path the PhpRender uses to find manually included templates. There is a similar line in the Application module.config.php. I thought this would be imported into the master config but that didn't happen. You have to add this.metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com1tag:blogger.com,1999:blog-1955739017412408985.post-81117925461388132502014-04-08T12:54:00.000-07:002014-04-08T12:54:08.133-07:00Zend Framework 2.x Learn ZF2 by Example : Error creating Debug moduleI'm rewriting part of my website with Zend Framework 2 because I want to use something more mature and flexible than something I wrote years ago. I picked up the book <a href="http://www.amazon.com/Learn-ZF2-Learning-By-Example/dp/1492372218/" target="_blank">Learn ZF2 by Example</a> because it was rated well. The intro gets your feet wet and eases you in. I got stuck when trying to reproduce the steps to create a new module using <a href="https://github.com/zendframework/ZFTool" target="_blank">ZFTool</a>.<br />
<br />
On page 28 under Automatic Module Creation they want you to download a tool that will help with creating new modules. I'm not sure if the instructions are old but it not work. Running the command will give you the following error<br />
<br />
<pre>Fatal error: Uncaught exception 'Zend\ModuleManager\Exception\RuntimeException' with message 'Module (ZFTool) could not be initialized.' in /Volumes/zend_framework/learnzf2/vendor/zendframework/zendframework/library/Zend/ModuleManager/ModuleManager.php:189
Stack trace:
#0 /Volumes/zend_framework/learnzf2/vendor/zendframework/zendframework/library/Zend/ModuleManager/ModuleManager.php(163): Zend\ModuleManager\ModuleManager->loadModuleByName(Object(Zend\ModuleManager\ModuleEvent))
#1 /Volumes/zend_framework/learnzf2/vendor/zendframework/zendframework/library/Zend/ModuleManager/ModuleManager.php(90): Zend\ModuleManager\ModuleManager->loadModule('ZFTool')
#2 [internal function]: Zend\ModuleManager\ModuleManager->onLoadModules(Object(Zend\ModuleManager\ModuleEvent))
#3 /Volumes/zend_framework/learnzf2/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(468): call_user_func(Array, Object(Zend\ModuleManager\ModuleEvent))
#4 /Volumes/zend_framework/learnzf2/vendor/zendframework/zendframework/library/Zend/ in /Volumes/zend_framework/learnzf2/vendor/zendframework/zendframework/library/Zend/ModuleManager/ModuleManager.php on line 189
</pre>
<br />
Your path will vary, but the error is the same. Searching google didn't give me a good answer. The <a href="https://github.com/zendframework/ZFTool" target="_blank">ZFTool page</a> has instructions on how to install the it <a href="https://getcomposer.org/download/" target="_blank">using composer</a>. When the install finished I ran the command <b>php vendor/bin/zf.php create module Debug</b> and the new module was created.<br />
<br />
I hope this saves you some time.<br />
metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com1tag:blogger.com,1999:blog-1955739017412408985.post-66465808254354825602014-02-24T11:11:00.000-08:002014-02-25T16:32:53.063-08:00Sencha Touch: Reorder a list with drag and drop handles using SortableListPart of a project I'm working on requires the ability to reorder a list. I was pretty sure sencha touch could handle this, but couldn't figure out how to do it. <a href="http://xkcd.com/1334/" target="_blank">I searched google for a solid week</a>. I had one lead that turned bad after digging into it further. I basically gave up and moved onto the next issue when I ran across the solution buried in their documentation: <a href="http://docs.sencha.com/touch/2.3.1/#!/api/Ext.plugin.SortableList" target="_blank">SortableList</a><br />
<br />
The second problem arose from the poor documentation on this feature. Outside of the class docs there is nothing explaining how to use it. The upside is at least it's easy to <a href="http://docs.sencha.com/touch/2.3.1/source/SortableList.html#Ext-plugin-SortableList" target="_blank">view the source</a>.<br />
<br />
I ran across <a href="http://www.sencha.com/forum/showthread.php?281380-Sortablelist-plugin-doesn-t-work-as-expected&p=1030428#post1030428" target="_blank">this forum post</a> that talked about a bug in the code. This was the only code I found that gave an example of how the code works.<br />
<br />
There are a few things required to use this plugin.<br />
<br />
Step 1: Include the plugin<br />
<br />
<pre class="brush:javascript">// Make sure the plugin in include when the app builds
requires: ['Ext.plugin.SortableList'],
config:{
// Include the plugin in your config. Don't forget the period on the class name
plugins: [{xclass: 'Ext.plugin.SortableList', handleSelector: '.gripper'}],
// These are required to fix a bug that exists in the plugin
infinite: true,
variableHeights: true,
...
}
</pre>
<br />
Step 2: Configure the drag handle<br />
<br />
<pre class="brush:javascript">config: {
// Set the class to the name you passed in for the handleSelector
itemTpl: '<span class="gripper"></span>[html goes here]'
...
}
</pre>
<br />
The tag used for the list-sortablehandle is the object that will start the reorder process. This can be styled using whatever you like.<br />
<br />
Step 3: Listen for the finishing event<br />
<br />
<pre class="brush:javascript">config: {
listeners:[
event: 'dragsort',
// to is the new position in the list
// from is where the item used to be
fn: function(listObject, row, to, from)
]
...
}
</pre>
<br />
It was smooth sailing after this point.metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com3tag:blogger.com,1999:blog-1955739017412408985.post-15112775701664165712014-01-23T15:08:00.001-08:002014-01-26T12:27:25.311-08:00Javascript: Problems, trouble, issues parsing JSON data / Unexpected tokenI ran into an issue trying to parse a JSON string that made very little sense. Normally when you have a token in the JSON response that doesn't work the error will include that character. This time it gave me nothing.<br />
<br />
<pre class="brush:javascript">// This is all you have to do
JSON.parse(jsonObject);
</pre>
<br />
After 4 hours and much googling I had no answer. I though for some reason the server response had the wrong type of quotes on it, but turned out to be something very left field.<br />
<br />
I used JSON.stringify() on the server response and saw something really weird on the end of the string that wasn't showing up by looking at the response.<br />
<br />
<pre class="brush:javascript">// What is this?!
'"timeCreated\":1390518047098}\u0000\u0000\'
</pre>
<br />
The \u0000 character was choking the parser and wasn't showing up as a bad token. This is the unicode character for null. Not sure why it was on the response but it was causing the problem. Running this cleaned up the problem.<br />
<br />
<pre class="brush:javascript">// Take out the garbage
[server response] = [server response].replace(/\u0000/g, "")
</pre>
<br />
As a safety measure it's good to have a method you can use to clean your JSON strings before trying to parse them.metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com7tag:blogger.com,1999:blog-1955739017412408985.post-34642544236006416942014-01-10T14:02:00.002-08:002014-01-10T14:02:31.724-08:00Javascript: Quick Date timestamp I wanted to find a quick way to compare two dates. The easiest way is to use their unix timestamp. If the date exists as an object you can use .getTime() to retrieve the number of milliseconds that have passed since epoch time.<br />
<br />
You can retrieve that number even faster with the following bit of code<br />
<br />
<pre class="brush:javascript">+new Date
</pre>
<br />
I found the tip <a href="http://stackoverflow.com/a/5036460/122236" target="_blank">here</a> and wanted to surface it.metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com0tag:blogger.com,1999:blog-1955739017412408985.post-56834502200349025382013-12-14T00:08:00.002-08:002014-02-25T15:33:59.152-08:00Sencha Touch: Problems with Date Time PickerPart of a project I'm working on requires an form element that allows the user to select a date and time for the same field. Sencha Touch has a built in <a href="http://docs.sencha.com/touch/2.3.0/#!/api/Ext.field.DatePicker" target="_blank">form field for selecting a date</a> and it works really well. They don't have one that allows you to pick both the date and the time.<br />
<br />
I found a plugin on <a href="https://market.sencha.com/extensions/datetimepicker" target="_blank">Sencha's site</a> that seemed to be just what I was looking for. There were a few issues with it.<br />
<br />
#1 No install instructions.<br />
This is the first plugin I've used and I couldn't find anything on Sencha's site that was helpful. After some digging <a href="http://scriptogr.am/tkashiro/post/how-to-use-senchatouch-custom-components" target="_blank">I found instructions</a> for another plugin that pointed me in the right direction.<br />
<br />
<ol>
<li>Copy the <b>ux</b> folder to your app directory.</li>
<li>Open your <b>app.js</b> file and locate the <b>Ext.Loader</b> line. If there isn't a <b>setPath</b> method chained to <b>setConfig </b>add one. Add these key/value pairs to the object. They correspond to the Ext.define namespaces for <b>DateTime.js</b> and <b>DateTimePicker.js</b> located in the <b>ux</b> folder.</li>
<ol>
<li>'Ext.ux.field' : './ux'</li>
<li>'Ext.ux.picker': './ux'</li>
</ol>
</ol>
<div>
#2 Bugs</div>
<div>
The first problem I had was the cancel button destroyed the picker. One feature of the plugin allows you to destroy the picker to save memory. It's missing a check for the destroy option and nukes it on cancel.</div>
<div>
<br /></div>
<div>
The second problem is if you press OK to the default date it doesn't actually read it properly. Deep in DateTime.js the getValue method looks through the items on the picker and grabs the slots. It calls getValue on each slot but returns nothing. You need to pass true for it to read the proper value.</div>
<div>
<br /></div>
<div>
I was able to find the <a href="https://github.com/tomalex0/senchatouch-datetimepickerv2" target="_blank">original source on github</a>. <a href="https://github.com/metric152/senchatouch-datetimepickerv2" target="_blank"><b>I forked the repo</b></a> and fixed all the bugs I found. I submitted a pull request so hopefully I'll hear back from the guy soon so future users will have fewer problems.</div>
<br />
<b>UPDATE</b><br />
The <a href="https://github.com/tomalex0/senchatouch-datetimepickerv2" target="_blank">github</a> version of the plugin has integrated my pull request that fixes the issues I ran into.metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com2tag:blogger.com,1999:blog-1955739017412408985.post-24359716811668450632013-11-14T10:34:00.001-08:002013-11-14T10:34:35.946-08:00Sencha Touch: Submit the form with Go/EnterI'm in the process of refactoring some code from my first Sencha Touch project. I followed a really great tutorial from <a href="http://miamicoder.com/2012/adding-a-login-screen-to-a-sencha-touch-application/" target="_blank">Miami Coder</a> used to build a login page. There are a few things I wish it did better in terms of separating view and controller code, but you learn that stuff on the road.<br />
<br />
One thing I really wish it covered was submitting the form using the Go key on iPhone, or Enter key. It's reliant on pressing the Log In button and then letting the code grab the values and move on. I want to make two changes. I want to listen for the Go key and submit the form, and I want the code to exist in the Controller, not the View.<br />
<br />
First let's set up the View.<br />
<br />
<pre class="brush:javascript"> xtype: 'fieldset',
itemId: 'login-form',
name: 'login-form',
items: [
{
xtype: 'textfield',
placeHolder: 'Username',
itemId: 'user-name-text-field',
required: true,
autoComplete: false,
autoCorrect: false
},
{
xtype: 'passwordfield',
placeHolder: 'Password',
itemId: 'password-text-field',
required: true
}
]
},
{
xtype: 'button',
itemId: 'login-button',
action: 'login',
// This is just a color style
ui: 'action',
text: 'Log in',
cls: 'login-button'
}
</pre>
Now let's set up the Controller.
<br />
<pre class="brush:javascript">config: {
control:{
// Listen for the login button
'button[action=login]':{
tap: 'tryLogin'
},
// Listen for a field form submit
'fieldset[name=login-form]':{
action: 'tryLogin'
}
}
}
</pre>
I listen for events in the Controller instead of launching events through the Application from the View and listening for them elsewhere. The View is kept nice and clean and all the logic is in the Controller where it belongs. The Controller can grab a reference to the View and update whatever it needs.<br />
<br />
'control' is my new favorite property. It's great for event listening. Once I found out I could tie a function to a button without listening for a command I never looked back.metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com0tag:blogger.com,1999:blog-1955739017412408985.post-18929175934483788162013-11-11T09:25:00.001-08:002013-11-11T09:25:33.545-08:00Git : Tower on sale 50% off<a href="http://blog.152.org/2012/02/mac-os-x-git-clients-roundup.html">A while ago I wrote an article about my search for a good git client</a>. There are a lot out for OSX which is good because you have a choice, but not all of them are good.<br />
<br />
<br />
<div class="p1">
After playing with a few clients I've settled on <a href="http://www.git-tower.com/">Tower</a>. It's a really streamlined client that isn't cluttered with buttons. The one downside is that it wasn't cheap. It's normally $59. It's on sale today for $29.50. I highly recommend picking it up. Falls under getting what you pay for.</div>
metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com0tag:blogger.com,1999:blog-1955739017412408985.post-2760950001569740102013-08-26T13:51:00.001-07:002013-08-26T13:51:41.359-07:00PHP: Zend Studio 10 SaleZend Studio is a fantastic PHP dev tool. I've used it for years and they keep making it better. It's built on top of Eclipse so it can be used as a plugin. I have it set up this way so I can work on my PHP API and Android client in the same tool.<br />
<br />
<a href="http://shop.zend.com/ZendStudio_Faster_IDE">It's on sale now for a limited time</a>. Not sure when the sale ends, but it's totally worth picking up.metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com0tag:blogger.com,1999:blog-1955739017412408985.post-58614895951790449772013-08-02T16:14:00.000-07:002013-08-03T10:04:29.235-07:00Javascript / IE8 : file fields created by javascript allows text entryI ran into an issue in IE8 while creating file fields in javascript for a form. The newly created file field allowed text entry. It didn't matter if I used jQuery or created the field with createElement.<br />
<br />
<br />
<pre class="brush:xml"><form id="fields">
<input id="picker-1" type="file" />
</form>
</pre>
<pre class="brush:javascript">$
var fileField = $('<input />',{
'id': 'picker-2',
'type': 'file'});
$('#fields').append(fileField);
</pre>
<br />
When the field was placed on the screen it allowed users to enter text. This isn't a huge issue, but this shouldn't happen. It doesn't happen when you create the file field through HTML. <a href="http://files.152.org/ie-file-field-bad.html" target="_blank">You can see an example here</a>.<br />
<br />
The solution to this problem is cloning the newly created field before appending it to the DOM.<br />
<br />
<br />
<pre class="brush:javascript">var fileField = $('<input />',{
'id': 'picker-2',
'type': 'file'});
$('#fields').append(fileField.clone());
</pre>
<pre class="brush:javascript">
</pre>
<br />
This will make it behave like a normal file field. <a href="http://files.152.org/ie-file-field-good.html" target="_blank">You can see an example here</a>.metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com1tag:blogger.com,1999:blog-1955739017412408985.post-29216672548491665312013-07-18T14:20:00.001-07:002013-07-18T14:20:07.756-07:00Sencha Touch: Using the Action property of the Button elementI've been trying to wire up the buttons in my UI to handlers inside the view so I could have them fire an event to the controller and complete an action, but it required me to put a function in the config section and it looks messy and isn't portable.<br />
<br />
<a href="http://stackoverflow.com/questions/10037979/rendering-a-new-view-when-a-button-is-clicked" target="_blank">After much googling</a> I found a hidden property of Button called action. I can't find very good documentation on it and wanted to show an example of it because it will make your life so much easier.<br />
<br />
<br />
<pre class="brush:javascript">// Building a button inside of an items array
{
xtype: 'button',
action: 'warnOnLeave',
align: 'left',
iconCls: 'home',
ui: 'back',
}
// Handle the button click inside a controller
control: {
// Listen for the new button press
'button[action=warnOnLeave]':{
tap: 'onCreateNewContent'
}
}
</pre>
<br />
This saved me quite a few steps because all my button actions triggered something in the controller. This way I can skip using fireEvent and just tie the event to a handler method in the controller.metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com0tag:blogger.com,1999:blog-1955739017412408985.post-26516810036233907162013-07-18T13:56:00.004-07:002014-01-28T10:11:07.599-08:00Sencha Touch: Center elements in a tab panelBy default elements in <a href="http://docs.sencha.com/touch/2.2.1/#!/api/Ext.tab.Panel">Ext.tab.Panel</a> are aligned left. I wanted to center them so it's not so close to the back button in the Title Bar.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-3ySw5T-wFso/UehVKy0JfII/AAAAAAAACOw/yiM-dMD2K80/s1600/left.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-3ySw5T-wFso/UehVKy0JfII/AAAAAAAACOw/yiM-dMD2K80/s320/left.png" height="320" width="213" /></a></div>
<br />
I found the answer while digging around in the comments section of the <a href="http://docs.sencha.com/touch/2.2.1/#!/api/Ext.tab.Panel-cfg-tabBar" target="_blank">Sencha Touch documentation</a> and wanted to surface the answer so others could easily find it.<br />
<br />
<pre class="brush:javascript">Ext.define("Sample.view.ContentEditorContainer",{
extend: 'Ext.tab.Panel',
alias: 'widget.contenteditorcontainer',
config: {
// How to center tabs in a panel floating at the top
tabBar: {
layout: {
type: 'hbox',
align: 'center',
pack: 'center'
}
},
</pre>
<br />
This will center the elements.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-Jd7jLNM7INA/UehWAqYOM6I/AAAAAAAACO8/uvvtg6FpRRs/s1600/center.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-Jd7jLNM7INA/UehWAqYOM6I/AAAAAAAACO8/uvvtg6FpRRs/s320/center.png" height="320" width="213" /></a></div>
<br />
<a href="http://docs.sencha.com/touch/2.3.0/#!/guide/layouts-section-pack-and-align-%28hbox%29" target="_blank">Here is the documentation</a> for centering elements on a panel.metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com0tag:blogger.com,1999:blog-1955739017412408985.post-19139135508789069192013-07-17T10:14:00.001-07:002013-07-17T10:14:09.403-07:00Tep Wireless Sale: 50% offI used a tep internet hotspot on my last vacation and the it worked really well. I highly recommend it to anyone going on an overseas trip.<br />
<br />
They're having a 50% off sale right now. The coupon code is <a href="http://www.tepwireless.com/wifi/Europe?utm_source=Email_Campaign_72hrs50&utm_medium=Email&utm_campaign=Email_Campaign_72hrs50" target="_blank">“FireSale”</a>.metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com0tag:blogger.com,1999:blog-1955739017412408985.post-53130947153920997432013-07-12T10:44:00.000-07:002013-07-12T10:44:16.145-07:00Javascript / jQuery : Scroll to the top of a documentQuick way to scroll to the top of a page via jQuery<br />
<br />
<a href="http://api.jquery.com/scrollTop/" target="_blank">jQuery(window).scrollTop(0);</a>metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com1tag:blogger.com,1999:blog-1955739017412408985.post-43727627256681936492013-07-12T10:37:00.004-07:002013-07-12T10:37:36.626-07:00Objective C : Learning the syntaxI'm in the process of trying to learn Objective-C. In the beginning this can be really rough. There are so many brackets. <span style="font-size: xx-small;">So many brackets...</span><br />
<br />
This site has been pretty helpful in trying to make some sense out of the chaos:<br />
<a href="http://cocoadevcentral.com/d/learn_objectivec/">http://cocoadevcentral.com/d/learn_objectivec/</a><br />
<br />
This is the video course I'm learning from: <a href="https://itunes.apple.com/us/course/coding-together-developing/id593208016" target="_blank">Coding Together: Developing Apps for iPhone and iPad (Winter 2013)</a>. It's really good, better than most books I've read and it's free.<br />
<br />
<a href="http://shop.oreilly.com/product/0636920029717.do" target="_blank">Programming iOS 6</a> however has been a fantastic book and explains obj-c in great depth. You'll need at least a basic understanding of either C or C++. Other books have you blindly follow code examples without explaining anything. This book tells you exactly what's going on. I wish more books were written in this fashion.<br />
<br />
There's lot of other stuff obj-c does that seem auto-magical. Like the variables that are created from that are prefixed with an _. It's all about comments you guys.metric152http://www.blogger.com/profile/11587192756320730861noreply@blogger.com0