I'm currently teaching myself a few new languages to expand my knowledge base and development capabilities.
React JS: https://facebook.github.io/react/docs/tutorial.html
Python: http://learnpythonthehardway.org/book
Thursday, 12 November 2015
Wednesday, 7 October 2015
Tooltip styling is removed when used in ngRepeat
Problem: I have a tooltip that is styled using jQuery, but when it is used in an ngRepeat the styling is removed.
Examples:
Correct styling (no ngRepeat):
No styling (inside ngRepeat):
Process: I did a bit of research and it seemed like an ngRepeat scoping issue; where the ngRepeat was unable to access the correct styling as each repeat is the child of the repeater, not the parent and therefore loses some bindings.
I made a Stack Overflow post to try and see if anyone could confirm my theory and potentially provide a solution.
I created a new tooltip using css instead of jQuery to see if it was a scoping issue. After some fiddling around I got it working inside the repeater! However the width of the tooltip was very narrow:
I created this Stack Overflow thread to ask others ideas on how to fix it after trying a bunch of fixes myself. The only response was someone suggesting changing the position value from absolute to relative:

It seems that more work would have to be done because not only did the positioning have to be redone, the tooltip was not dynamic in that it was being cut off on browser resizing. So I went back to solving the ngRepeat issue with the jQuery tooltip as this is something I wanted to solve and a better option than having redundant versions of tooltips.
Reasoning: I learnt that on the page load event the jQuery binds the custom tooltip class to tooltip function. However, when it's used in the repeater the event is fired after the page load and there is no existing binding. Therefore it is necessary to bind newly created elements to the tooltip again.
Basically the jQuery is initialised and rendered, but the ngRepeat is on the client side. Each repeat is dynamically generated with the scope of the child, not the parent, so all original bindings are out of scope and need to be re-binded after the ngRepeat has been created.
Solution: Re-bind all dynamic elements to the ngRepeat after it has been initialised and rendered. Referenced this post for a solution.
Create new directive to broadcast when the ngRepeat has finished rendering:
In the controller create a listener for the broadcast that then updates the parent of the tooltip (which in turn updates the tooltip):
Add on-finish-render="ngRepeatFinished" to the ngRepeat in the ascx:
Result:
Examples:
Correct styling (no ngRepeat):
No styling (inside ngRepeat):
Process: I did a bit of research and it seemed like an ngRepeat scoping issue; where the ngRepeat was unable to access the correct styling as each repeat is the child of the repeater, not the parent and therefore loses some bindings.
I made a Stack Overflow post to try and see if anyone could confirm my theory and potentially provide a solution.
I created a new tooltip using css instead of jQuery to see if it was a scoping issue. After some fiddling around I got it working inside the repeater! However the width of the tooltip was very narrow:
I created this Stack Overflow thread to ask others ideas on how to fix it after trying a bunch of fixes myself. The only response was someone suggesting changing the position value from absolute to relative:
It seems that more work would have to be done because not only did the positioning have to be redone, the tooltip was not dynamic in that it was being cut off on browser resizing. So I went back to solving the ngRepeat issue with the jQuery tooltip as this is something I wanted to solve and a better option than having redundant versions of tooltips.
Reasoning: I learnt that on the page load event the jQuery binds the custom tooltip class to tooltip function. However, when it's used in the repeater the event is fired after the page load and there is no existing binding. Therefore it is necessary to bind newly created elements to the tooltip again.
Basically the jQuery is initialised and rendered, but the ngRepeat is on the client side. Each repeat is dynamically generated with the scope of the child, not the parent, so all original bindings are out of scope and need to be re-binded after the ngRepeat has been created.
Solution: Re-bind all dynamic elements to the ngRepeat after it has been initialised and rendered. Referenced this post for a solution.
Create new directive to broadcast when the ngRepeat has finished rendering:
In the controller create a listener for the broadcast that then updates the parent of the tooltip (which in turn updates the tooltip):
Add on-finish-render="ngRepeatFinished" to the ngRepeat in the ascx:
Result:
Tuesday, 29 September 2015
AngularJs modules corrected to support minification
Problem: All the dependency injections in the project I am working on currently do not support JavaScript minification. Minification is the process of removing all the white space and other unnecessary characters from the code, such as comments, new line characters and sometimes block delimiters. This compresses the code without removing any functionality, and because it isn't actually compressed it doesn't need to be uncompressed to be read (therefore both the minified source and the original can be interpreted immediately). - source
I am using Grunt to minify all code, which uses UglifyJS to minify the JavaScript specifically.
Solution: By adding a simple object (keyword) to map the parameter instead of injecting directly into the function. This means that if parameters naming changes it will still be injecting the correct value.
Current code:
Improved code:
All the controllers, directives and factories should be in this format.
I am using Grunt to minify all code, which uses UglifyJS to minify the JavaScript specifically.
Solution: By adding a simple object (keyword) to map the parameter instead of injecting directly into the function. This means that if parameters naming changes it will still be injecting the correct value.
Current code:
Improved code:
All the controllers, directives and factories should be in this format.
Tuesday, 22 September 2015
Chart.js tooltip cut off
Problem:
- Using Chart.js to display data but the tooltip has been cut off by the edge of the chart's container:
Apparently it is a bug (https://github.com/nnnick/Chart.js/issues/622).
A couple of options I thought of, including:
- Line break: "At this point in time, it's not possible to add line breaks to a tooltip or axis label." - http://stackoverflow.com/questions/29302392/chartjs-tooltip-line-breaks
- Text wrapping: Apparently the top solution is to hope a solution "magically" happens - https://github.com/nnnick/Chart.js/issues/608
- Adding width, margin, neither worked.
- Updating Chart.js to calculate and move the tooltips to prevent being cut off, however this is something I can't implement for what I'm working on - https://github.com/matt-bradley/Chart.js/commit/9fd40ce65fbcb7fb11f6af1d019001a4718c666e
Solution:
- Increase the size of the canvas using width and height (and also therefore adding margins for the center text). This was not the preferred option, but it works and was quick to implement. Because the size of the tooltip will never be larger than the example given, it's also therefore a robust solution:
Friday, 18 September 2015
How to open a new tab in AngularJs
I have a hyperlink that when clicked, opens a document:
To make the hyperlink open the document in a new tab add:
target="_blank":
To make the hyperlink open the document in a new tab add:
target="_blank":
Thursday, 17 September 2015
Datepicker year range examples
Examples of how to set the year range in AngularJs datepicker:
1900 to present
1900 to present
- yearrange="1900:+0"
Last 20 years
- yearrange="-20:+0"
1950 to 2000
- yearrange="1950:2000"
18 years or older (up to 115 years)
- yearrange="-115:-18"
5 years from the present
- yearrange="+0:+5"
Monday, 14 September 2015
Set the start date on a mobile native keyboard
Setting the minimum allowed date on a datepicker, but when testing for mobile, the iPhone keyboard still lets the user scroll all the way back to the year "1".
I did some research and from what I saw I was using the "min" attribute correctly. I then checked the AngularJs version I am using which is v1.3.2. This is an earlier version compared to most of the forum references I was looking at, and after some further research I realised this earlier version has a different naming attribute for minimum value for datepicker. I therefore changed the attibute from "min" to "min-date" and it now works.
I did some research and from what I saw I was using the "min" attribute correctly. I then checked the AngularJs version I am using which is v1.3.2. This is an earlier version compared to most of the forum references I was looking at, and after some further research I realised this earlier version has a different naming attribute for minimum value for datepicker. I therefore changed the attibute from "min" to "min-date" and it now works.
Sunday, 13 September 2015
View website in mobile view on your browser
To cover all bases when developing a website, development and testing needs to be included for mobile view.
To view your website without using a device follow these steps:
To view your website without using a device follow these steps:
- Open the website
- Press F12
- Press the mobile icon 2nd from left (in between search icon and "Elements" heading)
- Navigate to Cookies -> localhost
- Scroll down to the bottom and find "Name: sc_device, Value: Desktop"
- Delete that line
- On the webpage select your desired device
- Refresh the page
Thursday, 10 September 2015
Filtering data displayed in an AngularJs repeat
I recently had trouble when trying to display a list of products in a 2 column grid. I had a list of products and each product had the potential to hold a list of "flexi" products within those products.
The problem was that I only wanted to display the flexi products, and only had access to the parent product list. So, when trying to display them, I had to loop through the products to display the flexis, but I was unintentionally displaying a column for each product regardless of whether it had any flexis:
I tried a lot of different ways to try and configure the display; I started off with many ng-if/ng-show/ng-hide checks, but I couldn't figure out how to access the data in the scope of the child of the repeat (product in data.Products), only the parent (data.Products) while trying to refine how the parent is displayed. I then moved onto creating new refined lists on the AngularJS side to use instead of data.Products, but no matter what I tried I couldn't display it properly (loops in loops to access the flexi list seemed to be losing scope when displayed).
After some deliberation I thought the best way to do it would be on the .ascx side anyway, so after some research I found a fix:
This article helped solve the issue: http://stackoverflow.com/questions/18644412/angularjs-filter-not-null
Result:
The problem was that I only wanted to display the flexi products, and only had access to the parent product list. So, when trying to display them, I had to loop through the products to display the flexis, but I was unintentionally displaying a column for each product regardless of whether it had any flexis:
Code:
After some deliberation I thought the best way to do it would be on the .ascx side anyway, so after some research I found a fix:
This article helped solve the issue: http://stackoverflow.com/questions/18644412/angularjs-filter-not-null
Result:
Thursday, 3 September 2015
IQueryable collection modification returning null
Scenario: Creating a new IQueryable collection, looping through it and setting a certain value for each item looped through.
Issue: However, when using the collection straight after the loop, the value that had just been set was coming through as null.
Solution: IQueryable doesn't allocate memory as it's a copy - just used for querying against a specific data source. So if modification of properties is desired an object will need to be instantiated instead.
Note: This is a refactored snipped of code for the purpose of this blog only.
Issue: However, when using the collection straight after the loop, the value that had just been set was coming through as null.
Solution: IQueryable doesn't allocate memory as it's a copy - just used for querying against a specific data source. So if modification of properties is desired an object will need to be instantiated instead.
Note: This is a refactored snipped of code for the purpose of this blog only.
Friday, 28 August 2015
Delay between submitting and receiving data from Siebel
I am having a problem with a history table not displaying new data being submitted. The data appears in the table ~10 minutes after submission. Using Siebel for data management.
At first I thought there was a caching issue on my end; either not refreshing the cache after submitting new data, or refreshing faster than it was taking for the system to register there was new data.
Upon further testing (get history data, submit new request data, get history data again) and logs, identified that the cache was indeed being refreshed, however the data being returned from Siebel was not up to date with the new entry.
Options:
At first I thought there was a caching issue on my end; either not refreshing the cache after submitting new data, or refreshing faster than it was taking for the system to register there was new data.
Upon further testing (get history data, submit new request data, get history data again) and logs, identified that the cache was indeed being refreshed, however the data being returned from Siebel was not up to date with the new entry.
Options:
- Disable caching entirely on the history calls (bad performance)
- Set a static cache refresh for an amount of time that they expect the new request to be included in history (still need the user to refresh the page after that amount of time)
Neither options are good. Either the whole process is slowed on purpose by X seconds, or stays fast but without the newly submitted data.
I decided to test how long it is between submitting the data and retrieving the history with the new data using sleep(). I incrementally tested times, staring from 2000ms (2 seconds) to 300000ms (5 minutes). After 5 minutes Siebel was still returning the history list without the newly submitted data.
That means there is not much point disabling caching since it won't make a difference over that extended amount of time, where our caching refresh is 10 minutes.
Not sure why Siebel has such a long delay between receiving data and having it available, it's something I will have to look in to.
***
Upon further investigation it appears the newly created submission actually does appear in the history list. Apparently Siebel is only returning the most recent 25 entries, however I was calculating whether the data had been submitted based on count (assuming the max number would increase with a new entry). Because the full history list isn't returned, it is necessary to look for the specific entry instead of relying on count.
Therefore it looks to be a caching issue after all. Looking into the controller to see if a databind refresh is possible after submission of the new entry.
***
Solution:
Implemented cache expiry functionality to invalidate all previous search results after submitting a new entry.
Upon further investigation it appears the newly created submission actually does appear in the history list. Apparently Siebel is only returning the most recent 25 entries, however I was calculating whether the data had been submitted based on count (assuming the max number would increase with a new entry). Because the full history list isn't returned, it is necessary to look for the specific entry instead of relying on count.
Therefore it looks to be a caching issue after all. Looking into the controller to see if a databind refresh is possible after submission of the new entry.
***
Solution:
Implemented cache expiry functionality to invalidate all previous search results after submitting a new entry.
Tuesday, 25 August 2015
AngularJS ng-cloak flickering
I was having a problem when using ng-cloak/ng-show, where there were unwanted elements flickering on the page and then disappearing.
Example:
The error message was flickering briefly before disappearing when it shouldn't have been appearing at all. It is occurring between when the view is first loaded and before Angular has initialized.
Adding a rule to CSS can stop the flickering:
Example:
The error message was flickering briefly before disappearing when it shouldn't have been appearing at all. It is occurring between when the view is first loaded and before Angular has initialized.
Adding a rule to CSS can stop the flickering:
Monday, 24 August 2015
Restoring databases
To keep up to date on the project I am working on, I am required to manually update my local database to new versions.
Steps I take restore the database:
Steps I take restore the database:
- Copy new .bak file to accessible location
- Open Microsoft SQL Server Management Studio
- Connect
- Right click "Databases"
- Click "Restore Database..."
- Select "Device"
- Click "..."
- Select "Add" in the pop up box
- Locate and select new .bak file, click "OK"
- Make sure new backup is selected and click "OK"
If this error occurs: - Open IIS (Internet Information Services Manager)
- Under Actions->Manage Server click "Stop"
- Reselect new database backup in SQL and click "OK"
- Press "Start" in IIS to restart server
And then because I am using Sitecore, the updated master has to be published to web for me to be able to see the changes: - Open Sitecore instance
- Click "Publish" tab
- Click "Publish" drop down arrow
- Select "Publish Item"
- "Smart publish" and then "Publish >"
AngularJS $scope
I am learning AngularJS as part of the project I am working on.
One problem I was having was not binding my values to $scope, which is necessary otherwise Angular doesn't retain the information. Without the correct binding, my console logs were printing the correct value but the wrong data was being displayed on my .ascx.
Example:
This does not set the IsAuthorised bool such that it will retain the value. The correct way is:
One problem I was having was not binding my values to $scope, which is necessary otherwise Angular doesn't retain the information. Without the correct binding, my console logs were printing the correct value but the wrong data was being displayed on my .ascx.
Example:
This does not set the IsAuthorised bool such that it will retain the value. The correct way is:
Automated GulpJS file sync
Currently, to deploy front end files to the local website either Sublime has to be used to file sync, or manual Ctrl-A|Ctrl-C from Source to Website is another option.
Gulp can be used to automate file synchronisation. It monitors all front-end files (css, js, aspx, ascx, html) in the DEV directory, and synchronises the file into the (IIS) Websites directory on save of the file.
This means that upon editing these files in Visual Studio and saving (Ctrl-S), the file will automatically deploy to the local website.
Instructions:
Gulp can be used to automate file synchronisation. It monitors all front-end files (css, js, aspx, ascx, html) in the DEV directory, and synchronises the file into the (IIS) Websites directory on save of the file.
This means that upon editing these files in Visual Studio and saving (Ctrl-S), the file will automatically deploy to the local website.
Instructions:
- Create gulpfile.js to do the syncing in the project root directory
- Create install_gulp.bat in <root directory>/tools to install Gulp and all its dependencies
- Install Node.js (https://nodejs.org/)
- In an elevated command prompt, cd into the <project root>\tools directory
- Run install_gulp.bat
- cd.. to the root directory
- Enter gulp into the cmd prompt to run it
Gulp will need to be running (repeat step 7) to continue to monitor and sync files, This can be done by either creating a script or adding a task to the task scheduler.
Thursday, 16 July 2015
Creative loading effects
When deciding on how to personalise and add some real pizzazz to a website I'm working on, I came across a site that shows some really cool animated loading effects to use instead of spinners.
Check it out here.
Check it out here.
Sunday, 12 July 2015
Defining debugging
My senior web developer colleague just realised that debugging means "de - bugging.. Getting rid of the bugs". He had a light-bulb moment, and I witnessed it. I told him not to blog about it for his own reputation so instead I offered to tell the world to keep him anonymous.
Just goes to show, it doesn't matter how experienced you are there is always more to learn!
Just goes to show, it doesn't matter how experienced you are there is always more to learn!
Subscribe to:
Posts (Atom)