Aaron

Pinterest is an image based link sharing website that’s become fairly popular lately. It has a “Pin It” button that can normally be dragged to the bookmark bar and added as a link in your browser to make it easy to “pin” things. Of course, you can’t drag a link on the iPad! There is an iPad App for Pinterest, and from what I’ve heard it leaves something to be desired. So here’s how to get a Pin It button on the iPad, iPad2, or anything else that supports running JavaScript in a bookmark but doesn’t allow you to drag and drop a link.

The “Pin It” button is just a link with some JavaScript in it, so we will create a custom bookmark on the iPad with the correct JavaScript and it will work as expected.

  • Find the custom JavaScript.
  1. You can try copying and pasting the JavaScript from here, but it may change in the future. If it doesn’t work, then continue on to the next step in this section. Do include the “javascript:” at the beginning – it’s absolutely necessary.
    1. javascript:void((function(){var%20e=document.createElement('script');e.setAttribute('type','text/javascript');e.setAttribute('charset','UTF-8');e.setAttribute('src','http://assets.pinterest.com/js/pinmarklet.js?r='+Math.random()*99999999);document.body.appendChild(e)})());
  2. Open Safari on an actual computer (you may need to install it on Windows). Or just install one of those User Agent Switchers and tell Pinterest that you’re using Safari, if you know what you’re doing…
  3. Log in to Pinterest and get the “Pin It” button from the “About” menu, and drag it to your bookmarks.
  4. Edit the bookmark and copy the address of the bookmark, which should start with “javascript:”
  • Get the bookmark text on to your iPad. Probably the easiest way to do this is by emailing it somewhere and setting up that email on the iPad.
  • Copy the entire text of the bookmark, including the “javascript:”
  • Create a bookmark on the iPad (for anything, it is changed in the next step).
  • Edit the bookmark you created, name it “Pin It!”, paste the javascript:… text into the location/address part of the bookmark.
  • Click the “Pin It!” bookmark on any page with an image to get the popup window where you choose which photo to use. This look slightly different on the iPad but has the same functionality.
  • Rejoice in Pinterest goodness.

Some people have had issues importing various movie formats into iPhoto. Even .MOV QuickTime movies sometimes don’t play correctly in iMovie. .MTS files from Sony cameras simply will not work – they need to be converted. If you have the choice of a conversion format, use the H.264 format which may have an extension of .mp4. This works fine and may be the very format that iPhoto itself uses.

You can see the format that iPhoto uses by choosing a video that has already been imported (and plays correctly). Then click File -> Reveal in Finder -> Original File. Then right-click and choose Get Info. Under “More Info” there is a Codecs listing which shows the codec of the video.

A good converter is Xilisoft HD Video Converter.

The following are things that I think could be improved upon in JSF2.

1) There is no colspan (or rowspan) attribute for panelGrid.

Something like this would be useful, for example if you want full control of the tables JSF creates for you for specific formatting. There are a couple of ways to get around this. One method is to not use a panelGrid and just use a plain old html table. Of course, if you use a plain html then you’ll have to wrap it something (like a panelGrid for instance) if you’d like the table to be rerendered with some AJAX.

The other way around this is knowing that the panelGrid does offer headers and footers for the table it creates for you. This may be acceptable for your design.

<f:facet name="header">
    <h:outputText value="I am header text and I take up many columns."/>
</f:facet>

and

<f:facet name="footer">
    <h:outputText value="I am footer text and I take up many columns."/>
</f:facet>

2) A Boolean value on a bean is set to false instead of being left as null when the form is submitted.

There isn’t much to say about this. It’s “Boolean” not “boolean,” so don’t touch it if it’s null! This may have to do with the javax.faces.VALIDATE_EMPTY_FIELDS setting, but in my mind the two should be unrelated. Storing null instead of “false” is useful when saving form data to a database and capturing whether the user actually chose false or was defaulted into false. The default should be null if there is a “no option” default. The only way around this I’m aware of at the time of this writing is making the backing bean use a String, giving the “no option” option a value of “null,” and then turning that “null” String into an actual null value before inserting into the database (what a pain).

3) selectMany check boxes can only be displayed vertically or horizontally.

What about 2 by 2? 3 by 2? etc. This is another control issue.. The way around this that I found is to create extra methods on the backing bean – one that returns the first half of the check boxes and one that returns the second half of the check boxes. That way the two methods can be used for two separate columns, thus creating a list of checkboxes that are two-by-two. The annoying thing about doing it this way is that returning a simple

list.sublist(0, list.size() / 2);

doesn’t really work. Since JSF wants to set data on the list instead of just looking at it, you may need to actually truly have two lists on the backing bean. Then dealing with it as one list requires some additional workarounds. That’s what I had to do…

Here’s how to kick people off of the server in case they leave for the day (or for lunch) and leave their RDC (Remote Desktop Client) open.

*open a command prompt to \windows\system32\dllcache

*type the following…: query session /server:etltst01

*type the following….: reset session X /server:etltst01
where X is the ID of the person to boot.

from http://www.howtogeek.com/howto/windows/command-line-hack-for-terminal-server-has-exceeded-the-maximum-number-of-allowed-connections/.

What’s that? You’ve never heard of the ConcurrentHashSet before? It didn’t work out with the compiler? You may have typed it wrong. Try typing

Set<Object> processors = Collections.newSetFromMap(
    new ConcurrentHashMap<Object, Boolean>());

From http://dhruba.name/2009/08/05/concurrent-set-implementations-in-java-6/ 

Sometimes it’s desirable to set focus to the the invalid component instead of only displaying a message about the invalid component. This is especially true when tabs are used and the invalid component may not be visible to the user at all, leaving the submit button apparently unresponsive when it’s actually displaying the message on a different tab. The code works as follows and depends on the following.

…sets focus to invalid input components (empty and required or when an invalid date is entered, for example). It depends on the following things:

 

  1. the component must have an ID.
  2. The h:message component must have an ID exactly the same as the invalid component except with the additional suffix of “Message”.
  3. The h:message component must have the “errorMessage” css class specified as one of it’s classes.

This works in the following way.

  1. look for components with the “errorMessage” class.
  2. removes the “Message” suffix from the ID of the component.
  3. find the component with the new ID.
  4. set focus there.

On the submit button use the “onevent” attribute to trigger javascript.

<h:commandButton value="Submit Claim"
     action="#{controller.storeClaim}" id="saveReport">
      <f:ajax event="action" execute="@form"
     render="allErrorMessages tc1 tc2 tc3 tc4 tc5"
           onevent="setFocusToRequiredOrInvalid" />
</h:commandButton>

In an included javascript file define the “setFocusToRequiredOrInvalid” function as the following.

/** Returns true if the passed in string ends with the passed in suffix. */
function endsWith(str, suffix) {
   return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
 
// set focus to the first required field that is empty.
function setFocusToRequiredOrInvalid(e) {
     var setFocusItem = null;
     var tabIndexForFocus = null;
     
     /* The following sets focus to invalid input components (empty and required or when an invalid date
       * is entered, for example). It depends on the following things:
       * 1) the component must have an ID.
       * 2) The h:message component must have an ID exactly the same as the invalid component except with
       * the additional suffix of "Message".
       * 3) The h:message component must have the "errorMessage" css class specified as one of it's classes.
       * This works in the following way:
       * 1) look for components with the "errorMessage" class.
       * 2) removes the "Message" suffix from the ID of the component.
       * 3) find the component with the new ID
       * 4) set focus there */

     
      // look for error message components
      jQuery.each($(".errorMessage"), function(i, val) {
           var componentID = val.id; // get the component's ID
           
           // if the ID ends in "Message" then we named the ID to correspond with an input component
           if (endsWith(componentID, "Message")) {
                 // get the ID of the component for which this error message refers.
                 var errorredComponentID = componentID.substring(0, componentID.length - "Message".length);
                 
                 // select the errored component
                 var errorredComponent = document.getElementById(errorredComponentID);
                 if ((errorredComponent != null) &&
                              (errorredComponent != undefined) &&
                              (errorredComponent != "")) {
                       
                       // set the focus to this component
                        setFocusItem = errorredComponent;
                  }
                 
                 // figure out which tab to switch to
                 if (setFocusItem != null) {
                       // get the list of classes for the element. copied from
                       // stackoverflow.com/questions/1227286/get-class-list-for-element-with-jquery
                       var classList =$(setFocusItem).attr('class').split(/\s+/);
                       // look at each class
                       for(var i = 0; i < classList.length; i++) {
                             var value = classList[i];
                             // if the length is correct and it starts with "tab-" then
                             // extract the tab number
                             if ((value.length >= "tab-0".length) && (value.substr(0,4) == "tab-")) {
                                    tabIndexForFocus = value.substr(4);
                              }
                        }
                       
                       return false; // this means "break;" to jquery
                  }
            }
      });
     
     // look for invalid components by looking for requiredEmpty components.
     // these components are required to be empty
      jQuery.each($(".requiredEmpty"), function(i, val) {
           // get the first child's node value...
           if (val.firstChild != null) {
                  value = val.firstChild.nodeValue;
            }
           
           if ((setFocusItem == null) &&
                  (!
                  ((value == undefined) || (value == null) || (value == ""))
                  )
                  ) {
                 // find the previousSibling which is an input type for setting focus
                 do {
                        value = val.previousSibling;
                       
                       if (value == null) {
                             break;
                        }
                       if ((value.nodeName == "INPUT") && (value.getAttribute('type') != "hidden")) {
                              setFocusItem = value;
                             break;
                        }
                  } while (true);
            }
      });
     
     // switch to the appropriate tab if we should
     if (tabIndexForFocus != null) {
           var $tabs = $('#tabs').tabs(); // first tab selected
            $tabs.tabs('select', parseInt(tabIndexForFocus)); // switch to tab
           //$tabs.tabs('select', 1); // switch to tab
      }
     
     // if we found an empty required item then set the focus there
     if (setFocusItem != null) {
            setFocusItem.focus();
      }
}
| Terms of Use