Jquery validation message placement by field

In a previous post, I showed how to declare an error label container for jquery validation messages. http://javaninja.net/2010/12/change-where-jquery-validation-messages-are-displayed/.

Today, we had a problem where the markup of the page required us to need to specify for this particular field, display the messages here. The default behavior of showing the messages by the fields was still desired, but the mark-up was preventing this. Checker was being added by Jquery Uniform dynamically. It was restricted to width=”25″ and height=”25″ to force the checkbox to a certain size. The problem is that the regular Jquery Validation error messages defaults to placing the error message after the target element. Unfortunately, this places it within the div that is limiting its size.

<div class="x2-top row">
    <div class="col-md-9  uniformed">
        <div id="acceptedTermsDiv checker">
            <input type="checkbox" 
                   name="acceptedTerms" 
                   id="acceptedTerms" 
                   style="width:20px;" 
                   value="true" 
                   tabindex="6"/>
            <span class="tooltip_text" 
                  data-toggle="tooltip" 
                  data-placement="bottom" 
                  title="You must accept the Terms and Conditions." 
                  data-container="#acceptedTermsDiv">
                <label for="acceptedTerms">I Accept The <a href="#" class="inline" id="termsLink">Terms &amp; Conditions</a></label>
            </span>                                                                                   
        </div>
    </div>
</div>

One way to solve this is to use a custom errorPlacement to force the messages to a custom location.

<div class="x2-top row">
    <div class="col-md-9  uniformed">
        <div id="acceptedTermsDiv checker">
            <input type="checkbox" 
                   name="acceptedTerms" 
                   id="acceptedTerms" 
                   style="width:20px;" 
                   value="true" 
                   tabindex="6"/>
            <span class="tooltip_text" 
                  data-toggle="tooltip" 
                  data-placement="bottom" 
                  title="You must accept the Terms and Conditions." 
                  data-container="#acceptedTermsDiv">
                <label for="acceptedTerms">I Accept The <a href="#" class="inline" id="termsLink">Terms &amp; Conditions</a></label>
            </span>                                                                                   
        </div>
    </div>
</div>

The custom errorPlacement will look like this:

errorPlacement: function(error, element) {
    if (element.attr("type") == "checkbox") {
        error.insertAfter($(element).closest(".checker").closest('div'));
    } else {
        error.insertAfter(element);
    }
}

Jquery validation of passwords with multiple validations

The previous article regex validation with jquery validation plugin laid the foundation for creating custom validation methods.

One thing I ran into was the case where multiple validations were created for a password, but they only test for the existence of one character that matches the regex. Meaning, does the password contain a lower-case letter? The advantage of using multiple validations, is that the user can be told which types of characters they need to make their password validate correctly.

I needed to validate that a password contains at least one lower-case letter, at least one upper-case letter, at least one number, and at least one symbol. First, I created the custom validations.


/**
 * Custom validator for contains at least one lower-case letter
 */
$.validator.addMethod("atLeastOneLowercaseLetter", function (value, element) {
    return this.optional(element) || /[a-z]+/.test(value);
}, "Must have at least one lowercase letter");

/**
 * Custom validator for contains at least one upper-case letter.
 */
$.validator.addMethod("atLeastOneUppercaseLetter", function (value, element) {
    return this.optional(element) || /[A-Z]+/.test(value);
}, "Must have at least one uppercase letter");

/**
 * Custom validator for contains at least one number.
 */
$.validator.addMethod("atLeastOneNumber", function (value, element) {
    return this.optional(element) || /[0-9]+/.test(value);
}, "Must have at least one number");

/**
 * Custom validator for contains at least one symbol.
 */
$.validator.addMethod("atLeastOneSymbol", function (value, element) {
    return this.optional(element) || /[!@#$%^&*()]+/.test(value);
}, "Must have at least one symbol");

Once the validators were created, now it was time to use them.

<script>
    $(function () {
        $("#change-password").validate({
            rules: {
                password: {
                    required: true,
                    atLeastOneLowercaseLetter: true,
                    atLeastOneUppercaseLetter: true,
                    atLeastOneNumber: true,
                    atLeastOneSymbol: true,
                    minlength: 8,
                    maxlength: 40
                }
            }
        });
    });
</script>

An alternative way to specify the rules is

$("#password").rules("add", {
    required: true,
    minlength: 8,
    maxlength:40,
    atLeastOneLowercaseLetter: true,
    atLeastOneUppercaseLetter: true,
    atLeastOneNumber: true,
    atLeastOneSymbol: true
});

Bootstrap 3 tooltips

Bootstrap 3 tooltips are fairly easy to use. They also offer excellent cross-browser support while also being responsive.

If you are already using Bootstrap 3, then it is fairly easy to start using the tooltips. The first step is to add the HTML markup.

<a href="#"
     data-toggle="tooltip"
     title="My tooltip text">Tooltip target</a>

That is fairly straight forward. The title contains the text that will be displayed in the tooltip. data-toggle is a custom attribute and is used by the required javascript to trigger the markup as a tooltip.

The required javascript is

<script>
    $(function () {
        $('[data-toggle="tooltip"]').tooltip();
    });
</script>

That’s all it takes for a basic tooltip. Sometimes you need to customize the functionality. The default behavior is to trigger the tooltip on click. Sometimes you need other triggers, hover for example. This can be accomplished by adding data-trigger.

<a href="#"
     data-toggle="tooltip"
     data-trigger="hover click"
     title="My tooltip text">Tooltip target</a>

If you want to style the text, all you need to do is add normal class attribute. In my case, I made a css style especially for this purpose.

<a href="#"
     class="tooltip_text"
     data-toggle="tooltip"
     title="My tooltip text">Tooltip target</a>

By default, HTML markup is not displayed as HTML when it is included as part of the tooltip text. This can be enabled by adding data-html.

<a href="#"
     data-html="true"
     data-toggle="tooltip"
     title="My tooltip text">Tooltip target</a>

We did encounter a problem with using an <a> as the HTML element. The page will attempt to scroll to the anchor when clicked. We overcame this by using a tag.

<span data-toggle="tooltip"
      title="My tooltip text">
  Tooltip target
</span>

The default placement for the tooltips is above the trigger. Use data-placement to specify left, right or bottom.

<a href="#"
     data-placement="bottom"
     data-toggle="tooltip"
     title="My tooltip text">Tooltip target</a>

Grunt

Grunt, grunt, grunt. This is my first gruntfile. Once you get in the groove, it’s pretty easy to write them quickly.

module.exports = function (grunt) {

    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        clean: ['build'],
        less: {
            current: {
                files: [
                    {
                        expand: true,
                        cwd: "current/styles",
                        src: [
                            'global/**/*.less',  // need to process the global css separately from the rest
                            'modules/**/*.less'
                        ],
                        dest: 'build/temp/css',
                        ext: '.css'
                    }
                ]
            },
            working: {
                files: [
                    {
                        expand: true,
                        cwd: "working/styles",
                        src: [
                            'global/**/*.less', // need to process the global css separately from the rest
                            'modules/**/*.less'
                        ],
                        dest: 'build/temp/css-working',
                        ext: '-working.css'
                    }
                ]
            }
        },
        concat: {
                css: {
                    options: {
                        sourceMap: true
                    },
                    files: {
                        'build/compiled/css/<%= pkg.name %>.css': [
                            'bootstrap-3.3.4/dist/css/bootstrap.css',
                            'build/temp/css/global/igaming.css',
                            'build/temp/css/modules/**/*.css'],  // note would be better to use files created in less task via something like'<%= less.working.files.dest %>'
                        'build/compiled/css/<%= pkg.name %>-working.css' : [
                            'bootstrap-3.3.4/dist/css/bootstrap.css',
                            'build/temp/css-working/global/igaming.css',
                            'build/temp/css-working/modules/**/*.css'  // note would be better to use files created in less task via something like'<%= less.working.files.dest %>'
                        ]
                    }
                },
                js: {
                    options: {
                        separator: ';',
                        sourceMap: true
                    },
                    files: {
                        'build/compiled/js/<%= pkg.name %>.js': [
                            // load jquery, bootstrap, then the rest
                            'current/scripts/jquery/*.js',
                            'bootstrap-3.3.4/dist/js/bootstrap.js',
                            'current/scripts/libs/*.js',
                            'current/scripts/js/*.js',
                            'current/scripts/igaming/*.js'
                        ],
                        'build/compiled/js/<%= pkg.name %>-working.js': [
                            // load jquery, bootstrap, then the rest
                            'working/scripts/jquery/*.js',
                            'bootstrap-3.3.4/dist/js/bootstrap.js',
                            'working/scripts/libs/*.js',
                            'working/scripts/js/*.js',
                            'working/scripts/igaming/*.js'
                        ]
                    }
                }
        },
        uglify: {
            current: {
                options: {
                    sourceMap: true,
                    sourceMapIncludeSources: true,
                    sourceMapIn: 'build/compiled/js/<%= pkg.name %>.js.map'
                },
                files: {
                    'build/compiled/js/<%= pkg.name %>.min.js': 'build/compiled/js/<%= pkg.name %>.js' // wouldn't use '<%= concat.js.dest %>', for some reason
                }
            },
            working: {
                options: {
                    sourceMap: true,
                    sourceMapIncludeSources: true,
                    sourceMapIn: 'build/compiled/js/<%= pkg.name %>-working.js.map'
                },
                files: {
                    'build/compiled/js/<%= pkg.name %>-working.min.js': 'build/compiled/js/<%= pkg.name %>-working.js' // wouldn't use '<%= concat.js_working.dest %>', for some reason
                }
            }
        },
        cssmin: {
            options: {
                sourceMap: true
            },
            target: {
                files: {
                    'build/compiled/css/<%= pkg.name %>.min.css': ['build/compiled/css/<%= pkg.name %>.css'],
                    'build/compiled/css/<%= pkg.name %>-working.min.css': ['build/compiled/css/<%= pkg.name %>-working.css']
                }

            }
        },
        copy: {
            // builds the /assets webapp by copying the /webapp directory,
            // then copying the compiled css and js resources
            webapp: {
                files: [
                    {
                        expand: true,
                        cwd: 'webapp',
                        src: '**',
                        dest: 'build/assets'
                    }
                ]
            },
            compiled: {
                files: [
                    {
                        expand: true,
                        cwd: 'build/compiled',
                        src: '**',
                        dest: 'build/assets/compiled'
                    }
                ]
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-cssmin');
    grunt.loadNpmTasks('grunt-contrib-copy');


    // Default task(s).
    grunt.registerTask('default', ['clean', 'less', 'concat', 'uglify', 'cssmin', 'copy']);




    //grunt.registerTask("concat-css", "Concatenates the CSS files into a CSS file per section", function () {
    //
    //    // read all subdirectories from your modules folder
    //    grunt.file.expand("build/css").forEach(function (topDir) {
    //        console.log('topDir=' + topDir);
    //
    //        //grunt.file.setBase(topDir);
    //        // read all subdirectories from your modules folder
    //        grunt.file.expand("build/css").forEach(function (dir) {
    //            console.log('dir=' + dir);
    //
    //            console.log("cssFiles=" + cssFiles);
    //
    //            // get the current concat config
    //            var concat = grunt.config.get('concat') || {};
    //
    //            // set the config for this modulename-directory
    //            concat[cssFiles] = {
    //                //cwd: topDir,
    //                src: dir + '**/*.css',
    //                dest: dir + '.css'
    //            };
    //            // save the new concat configuration
    //            grunt.config.set('concat', concat);
    //        });
    //        // set the base to where it is supposed to be so that Grunt works as expected
    //        //grunt.file.setBase('../..');
    //    });
    //    // when finished run the concatenations
    //    grunt.task.run('concat');
    //});


};

CXF generated SOAP client

Creating a SOAP client for a SOAP web service is very straight forward when using CXF. Given a WSDL url or a WSDL file, create a project with a pom.xml containing the following:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.rightnow.ws</groupId>
    <artifactId>rightnow</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-codegen-plugin</artifactId>
                <version>3.0.4</version>
                <executions>
                    <execution>
                        <id>generate-sources</id>
                        <phase>generate-sources</phase>
                        <configuration>
                            <wsdlOptions>
                                <wsdlOption>
                                    <wsdl>https://twinspires--tst.custhelp.com/cgi-bin/twinspires.cfg/services/soap?wsdl</wsdl>
                                </wsdlOption>
                            </wsdlOptions>
                        </configuration>
                        <goals>
                            <goal>wsdl2java</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

When you run mvn compile, it will generate classes in the generated-sources/cxf directory.

The next step is to use the service client. The normal usage pattern is below. The service is instantiated, then the port is retrieved.

package com.rightnow.ws.wsdl.v1_2;

import com.rightnow.ws.metadata.v1_2.MetaDataClass;
import org.junit.Test;

import javax.xml.datatype.XMLGregorianCalendar;
import java.util.List;

import static org.junit.Assert.assertNotNull;

/**
 * @author norris.shelton
 */
public class TestRightNowSyncService {

    @Test
    public void testName() throws Exception {
        RightNowSyncService rightNowSyncService = new RightNowSyncService();
        RightNowSyncPort rightNowSyncPort = rightNowSyncService.getRightNowSyncPort();

        XMLGregorianCalendar metaDataLastChangeTime = rightNowSyncPort.getMetaDataLastChangeTime();
        assertNotNull(metaDataLastChangeTime);

        List<MetaDataClass> metaDataClasses = rightNowSyncPort.getMetaData();
        assertNotNull(metaDataClasses);

    }
}

How to get the first entry from a LinkedHashMap

I had an array of Strings. I needed to be able to quickly locate each item, so I fed it into a LinkedHashSet.

                Map<String, Boolean> newTableNames = new LinkedHashMap<>(pokerTableNames.length);
                for (String pokerTableName : pokerTableNames) {
                    newTableNames.put(pokerTableName, false);
                }

Later in the code, I needed to grab an item out of the list. My first cut was involved a for-loop. I got the first KeyValueSet, then called remove witht the value.

An easier way seems to be…

String candidateTableName  = newTableNames.entrySet().iterator().next().getKey();

UnsupportedOperationException when trying to iterate over Hazelcast replicatedMap

I needed to iterate over the values contained in a replicatedMap. I thought it would be as simple as:

hz.<Long, GameInfo>replicatedMap(DO.DESK_MAP, DO.DESK_MAP).values();

It would show that there were 2006 entries, but I couldn’t touch them.

I later stumbled upon the following:

hz.mapValues(DO.DESK_MAP);

This gave me a Collection of the values that I could iterate over.

Getting dotCMS JSON API to return more than 10 rows

The dotCMS JSON API is pretty easy to use. It even tells you the query for the content that you are looking for. That makes it super easy to use. What I didn’t know was that the results default to a limit of 10 records.

Here was my original query.

http://youbet.com/api/content/render/false/query/+structureName:PokerTableNameAdjectives%20+(conhost:915f2552-793a-4f17-96d0-f0955fcc698f%20conhost:SYSTEM_HOST)%20+languageId:1*%20+deleted:false%20%20+working:true/orderby/modDate%20desc/limit/30

That was easy enough, but how to you specify more? You specify the optional limit. It’s pretty easy, once you know what you are looking for.

/api/content/limit/<integer-limit>

That was easy enough. Here is what the final query looks like.

http://youbet.com/api/content/render/false/query/+structureName:PokerTableNameAdjectives%20+(conhost:915f2552-793a-4f17-96d0-f0955fcc698f%20conhost:SYSTEM_HOST)%20+languageId:1*%20+deleted:false%20%20+working:true/orderby/modDate%20desc/api/content/limit/1000

Getting a list of objects via RestTemplate

Usually we get back an object. Sometimes the object will contain a list. What needs to happen when you need to get back a list of Strings? RestTemplate accepts a parameter that tells it what the data it receives will be put in. I used a String array. It converts the JSON object into a String[] and away I go.

                    String[] pokerTableNames =
                        restTemplate.getForObject(pokerSettingsService.getValueByName(PokerSettings.IGP_ADAPTER_URL) + "/poker/tableNames",
                            String[].class);

Things I learned in the pursuit of code

LinkedIn Auto Publish Powered By : XYZScripts.com