Tuesday, June 23, 2015

Fancy tabs using pure CSS and AngularJS

I'll start this post with demonstration of what I mean by "fancy"
One way to do that, would be using a predefined image for each tab for each state. 
As you can see from the pictures above, it would be 4 separate images cut to fit specific dimensions. 
Downsides of this approach would be:
  1. Resizing of these tabs won't be possible,  if you try to do so, you will definitely change the triangular part angle 
  2. Downloading pretty big images might be noticeable
  3. Adding effects on tab swap will look clunky
On the positive side, I would put only the ease of implementation.

After playing a while with CSS options and adding some AngularJS wiring  (my application is using AngularJS so it was necessary), I came up with following solution:

This code snippet shows how to create two tabs control with triangular inner side of the tab. The tab swapping powered by AngularJS, of course it can be done using JQuery or any other JS library.
Note:
A proper way to do that would be creating a directive, that will support multiple tabs, but currently I'm a bit short of time. 
This solutions seems to be working for me, I've removed most of the unnecessary content to keep the code clean.

Thursday, June 11, 2015

Very nice site http://www.cssmatic.com/. It allows you to visually define some of the CSS features and copy the resulting stylesheet.
I've used it to define an appropriate shadow for a tab control I've had to develope for my company. 

Monday, March 23, 2015

Some time ago I've stumbled upon very clean design concepts defined by Google, named Material design.
Today I've had to create a dashboard where one of the components would be a Table displaying some cost related information.
Since I'm working with AngularJS I've looked into Angular Material project for inspiration (I haven't migrated my projects  to work with this framework yet). I was surprised to find out that simple table\grid has nor design guidelines neither implementation. After some googling   I've found this solution . It's very clean and professional looking table design. All I had to do was just to take whole css content from attached codepan and apply i to my table. IMHO it looks great.
I've forked it to a GIST , feel free to borrow and use.

Thursday, November 27, 2014

File input control don't have to be ugly    

The caption is a bit of a lie, it has to be ugly, since native browser implementation is pretty ugly and there is no straight forward way to change it's L&F.

So what do you do when your have a nice bootstrap  L&F in the whole system?

This fiddle suggesting a nice solution that was inspired by this guy.

I've used it together with AngularJS file uploader directive and it looks and works pretty nice good together.

In general the solution is :

  1. To make the sure you file input tag is transparent 
  2. To increase it's z-index so it will be above
  3. To locate it on the same spot a nice looking control is located
  4. To make sure z-index of nice looking control is lower than the file input tag

Actually that all the story, if anyone familiar with better techniques to prettify file input tag, please leave a comment bellow.



Tuesday, August 5, 2014

AngularJS directive to wrap Chart.js charting library

Just forked a directive used to wrap Chart.js charting library.
I've made a single change to original code published by earlonrails, which already worked fine.
My directive sensitive to both changing the whole chart object or just data  attribute.
Here is the link for forked version. 

Wednesday, July 2, 2014

Create an extensible set of commands using: Spring,Annotations and simple interface

Lately I've found myself using the same technique more than once in order to create some easily extensible mechanism, using: Spring, Annotations and simple predefined interface

I think the best way to picture the usage would be an example:
Let's say you need some kind of email editor in your application which will allow your user to use predefined set of keywords that will be evaluated during the email sending.

For example: 
If the user wrote following text in email body :  Hi today is ${system.Date} and I'm ...
Then  the recipient will get following content  :  Hi today is 2/7/2014 and I'm ...

In case your task is a bit more complicated than that and you need more comprehensive set of keywords, that will be extended during the time or even you would like to allow 3rd party developers to extend it, following technique might be handy.

I'll skip the part when you find  ${prefix.keyword} pattern in the code and start from the point you have extracted the keyword already.
 

   
 //.......
    for(/*... do the iteration*/){
        // get your keyword from text
        String keywordValue =  getKeywordValue(foundKeyword);
        // replace your ${foundKeyword} with keywordValue
    } 

//......
    // call the Helper class to get the correct executor
    private String getKeywordValue(String key) {
        KeywordExecutor keywordExecutor = KeywordExecutorsHelper.getKeywordExecutor(key);
        if(keywordExecutor != null){
            return  keywordExecutor.execute(context);
        }
        // if we couldn't find suitable executor just return the keyword as is 
        return key;
    }

Now let's have a look on how KeywordExecutor implemented, for sake of our example let's assume we have 2 keywords to implement: system.Date and system.Time

 // the interface
 public interface KeywordExecutor {

    // you can pass any parameters if you need them for your business case
    String execute();
 }

 // annotation that will hold the required keyword 
 @Target(ElementType.TYPE)
 @Retention(RetentionPolicy.RUNTIME)
 public @interface Keyword {

    String value();
 }


 @Component // Spring Component annotation 
 @Keyword("system.Time") // here goes our annotation with the the keyword 
 public class TimeKeyword implements KeywordExecutor {


    // the implementation itself 
    @Override
    public String execute() {
        Date now = new Date();
        // using Spring SimpleDateFormat here 
        SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
        return format.format(now);
    }
 }


// same as above with slight format change
 @Component
 @Keyword("system.Date")
 public class DateKeyword implements KeywordExecutor {


    @Override
    public String execute() {
        Date now = new Date();
        SimpleDateFormat format = new SimpleDateFormat("dd-MMM-yyyy");
        return format.format(now);
    }
 }

You can see that execute method can be as complex as we need and the rest of the code won't be affected.

The last thing that we need is our KeywordExecutorsHelper implementation:

 
 // in this sample I just reading all the classes every time getKeywordExecutor method called, you can optimize this by
 // saving the Map a static variable and lazy initializing it during the first getKeywordExecutor call 
 public class KeywordExecutorsHelper {
    public static KeywordExecutor getKeywordExecutor(String keyword) {

        // getting all the beans annotated with Keyword annotation 
        Map keywordExecutors = SpringUtils.getBeanWithAnnotation(Keyword.class);
        // the bean name used as a key in retrieved Map
        for (String beanName : keywordExecutors.keySet()) {
            // since all the beans implementing the same interface, I can safely cast each bean to KeywordExecutor 
            KeywordExecutor keywordExecutor = (KeywordExecutor) keywordExecutors.get(beanName);
            // getting the specific annotation instance from current bean using simple java reflection
            Keyword keywordAnnotation = keywordExecutor.getClass().getAnnotation(Keyword.class);

            // reading the value attribute and comparing with received keyword
            if (keyword.equalsIgnoreCase(keywordAnnotation.value())) {
                return keywordExecutor;
            }

        }
        // no implementation found for requested keyword
        return null;
    }

}

So, lets summarize what have we done and why you might need it:
  • What
    • Defined an interface that will help us to encapsulate bean implementation (execute in the case above)
    • Define an annotation that will help us to find all the annotated classes using Spring and will be used as a placeholder for required attributes  (Keyword in the case described above)
    • Define a Helper class that will retrieve all the possible implementations from Spring context and will  return a specific one by demand
    • Finally use the  Helper class to get the specific implementation 
  • Why
    • In case you need an extensible set of commands that can be summoned using keyword only this implementation can  be very handy
    • In case you want to outsource the implementation and will receive some kind of 3rd jar, you'll have to define only the interface and the annotation
Hope it was helpful.

Saturday, June 28, 2014

Stream a file using Spring MVC Controller

Did you ever need a way to stream a file directly to the browser as a result of calling a specific URI?

I did, more than once. Every time it requires some time to recall what is the correct way to do that.
This post will be a reminder for me and might become useful for anyone who reads this.

Why would I want to do that?

I needed that in following scenarios:

  1. I've just generated a pdf file and I'm required to return it to web based client, so the pdf file would be opened or downloaded automatically by the browser.
  2. There is a bunch of  image files located in some custom (preferably predefined) location that is not exposed  via direct URL, a.k.a it's not located in any subfolder under WEB-INF directory. This configuration is useful when I need to allow a customer put some custom icons without giving him an access to my web application resources or implementing file upload.
  3. In general: any time I need to return to web browser any downloadable type of file or file type that browsers are able to open.

How to do that?


Let's define a simple Spring MVC controller. In order access to application context I'll implement ApplicationContextAware interface.

@Controller
@RequestMapping("/customIcons")
public class CustomIconsController  implements ApplicationContextAware {
    private ApplicationContext applicationContext;
       
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

}

In this specific implementation I needed a way to enlist all the images under specific location. Once a caller UI gets them, it will have to show a dialog with all the available icons and will allow the user to pick one of the presented icons.


    // will contain all the found resources in order to return the stream as soon as the request arrives
    private Map foundResources = new HashMap<>(); 

    @RequestMapping("/all")
    @ResponseBody
    public Collection getAllCustomIcons() {

        Collection retVal = new ArrayList<>();
        Resource[] resources = null;

        try {
            // getting all the .png files from predefined location 
            resources= applicationContext.getResources("file:c:/customIconsPath/*.png");
        } catch (IOException e) {
            // any fallback solution can come here, for example: try to load images from your classpath instead 
            throw new ConfigurationException("No custom icons directory available");
        }

        extractFileNames(retVal, resources);

        return retVal;

    }
    private void extractFileNames(Collection retVal, Resource[] resources) {
        if (resources != null) {
            for (Resource resource : resources) {
                String finalName = resource.getFilename().replace(".png", "");// just removing the extention
                if (!"".equals(finalName)) {
                    retVal.add(finalName);
                    foundResources.put(resource.getFilename(), resource);
                }
            }
        }
    }

So far so good, I've got the list of all my .png files and now I want to show them in html using img tag Using AngularJS I would write something like this:

<img ng-repeat="customIconName in customIconNames"  ng-src="'customIcons/icon/' + customIconName"/>    

 You can use any other JS technique to get the resulting file name from the list returned by previous call.

 And that's the way method returning the requested image will look:


    @RequestMapping("/icon/{fileName}")
    // pay attention to second parameter, Spring MVC can pass HTTP response and request besides the path variable parameters
    public void getCustomIcon(@PathVariable("fileName") final String fileName, HttpServletResponse response) {

        try {
            // we've returned the filename without extension, so we put the extension back
            // alternatively we could save the Map key without the extension.    
            InputStream inputStream = foundResources.get(fileName + ".png").getInputStream();
            // the browser should know what kind of data are we streaming so setting a mime type is essential  
            response.setContentType("image/png");
            // copy the file input stream to response output stream (see the function bellow)
            writeStream(inputStream, response.getOutputStream());
            // flushing the response
            response.flushBuffer();

        } catch (FileNotFoundException e) {
            // just logging the errors
            logger.error(e);
        } catch (IOException e) {
            logger.error(e);
        }
   }

   public static void writeStream(InputStream inputStream, OutputStream outputStream) throws IOException {
        int buf_size = 8192;
        byte[] buf = new byte[buf_size];
        int len;
        while ((len = inputStream.read(buf, 0, buf_size)) != -1) {
            outputStream.write(buf, 0, len);
        }
    }

The getCustomIcon method, which is the whole reason for this post, is very simple  and requires to follow several steps:

  1. HttpServletResponse should be one of the parameters your void method receives
  2. Read the required file from the disk (in the example above it was already read in previous call)
  3. Copy  the input stream from of your file to response output stream (I've just used the fact that Resource can return an input stream right away)
  4. Call response.flushBuffer() to  complete the streaming
Hope it helps.