Thursday 30 October 2014

WTF Cnet? Put HREF attributes in those anchor tags! A link tag without a link is pretty stupid.


When is a an <a> anchor tag not really an anchor tag... when it doesn't have a href attribute. 

WTF Cnet. 


I was reading this article on Cnet and I started going through the list on the right of the page - "This Week's Must Reads" (see image)



Now normally, when I want to read articles, I open them in separate tabs so I can look at them after I finish the current tab. Now in this case the "Open In New Tab" option wasn't opening up in Chrome. So I call on "Inspect Element" option and I get this:

<a class="title" data-goto="5657a735-cbf6-40b4-8453-94cb94630900" data-url="/news/for-gorilla-glass-testers-life-is-a-daily-grind-and-scratch-and-drop/" data-s-object-id="TOC.2">

                            <div class="col-1">
                                <div class="progress">2</div>
                            </div>

                            <div class="col-3">
                                <div class="hed">For Gorilla Glass testers, life is a daily grind (and scratch and drop...)</div>

                                                                                                    <span class="topic">Phones</span>
                                                            </div>
                        </a>


The link probably only works after a click event. But what's the purpose of this? 

Now admittedly, I've been guilty of doing something similar last year, for SEO purposes. There were links on the website of my company that they wanted to de-prioritise as they wanted the main content links getting crawled first. So I did exactly the same technique - put the URL in a data attribute. I event reversed it, so that crawlers woudln't recognise the attribute as a URL and try to crawl it. But the links I did that on were only links to FAQ and generic help. People wouldn't normally go to them anyway. But this.. 

A list of most read articles on a news site is arguably on the same level of importance as the main article, as it leads people to consume more content on the site. So why would they make things a little more difficult for us tab-users by removing the href attribute?


Wednesday 24 September 2014

PuTTY default colours suck, so replace it with a better colour scheme like zenburn

PuTTY defaults to horrible combinations like using black background, with blue text for directories. WTH, after all these years?

Replace that with a better colour scheme. I came across Zenburn for PuTTY.


Step 1:

Go to


Step 2:

Save this as a .reg file. Make sure you're saving the content, and not ending up with the HTML of the github page.

Step 3:

Right click, and then select "Merge"

You'll know if it worked as you'll get a message

In PuTTY, a "Zenburn" session will be created. This has your new, better colours.

Step 4: (do this for all your existing entries)

NOTE: this assumes that 
a. your session only has the hostname as its contents, because that's all you'll be copying.
b. your hostname is the same as your putty session name

Load the existing entry you want to change.
Copy the hostname to clipboard
Load the Zenburn session.
Paste the hostname into the session name
Paste the hostname into the host details
Click on Save

Test it by opening this session. Colours shoud be better now.

Repeat for all your PuTTY session entries.


Tuesday 23 September 2014

Given a list of values, recursively go through subdirectories and find the matching files of a specific filename

Unix grep example:

fgrep -R -f sorted_untrusted_values_to_find.txt --include=".thisfile"

1. Given a list of values, contained in the file "sorted_unstrusted_values_to_find.txt", where each row has one value

-f sorted_untrusted_values_to_find.txt 

2. recursively traverse the subdirectories under our current location

 -R 

3. looking at the files named ".thisfile"

--include=".thisfile"

3. return the files that have a match



Wednesday 30 July 2014

Moving your Git working directory from Linux to Windows? There are two issues that you're probably going to get

The simpler solution would be to just check out the repository, but in
some cases you probably have some branches and stashes in your local
repository that you don't want to lose. So if you want to keep your
current local repo, you'll definitely have to deal with these two
issues. Here's how to solve them.

A. The line endings issue. You want to make sure that you're not
inadvertently checking in CRLF line endings.

Make sure you set this:

git config --global core.autocrlf true

This tells Git to use the system's default line ending (CRLF) when
checking out and LF when checking in.

B. File permissions being changed by Cygwin

The executable bit on Git repository files will get changed, and you
will have permissions "changes" in your git respository immediately
after checkout. Fix this by turning git's core.filemode config to
false. Refer to this post:
https://groups.google.com/a/chromium.org/forum/?fromgroups=#!topic/chromium-dev/0EdNev3NNsw

1. Turn it for globally: git config --global core.filemode false
2. Turn it off for each repo: git config core.filemode false
3. Turn it off for all the submodules of each repo: git submodule
foreach --recursive git config core.filemode false

If you don't change do (B), then when you do 'git status' you'll find it listing a lot of files that have been changed. Then when you do a 'git diff' on one of them, you'll see that the only change was in the executable bit in the permissions, ie

$ git diff scripts/e2e-test.sh
diff --git a/scripts/e2e-test.sh b/scripts/e2e-test.sh
old mode 100755
new mode 100644


Tuesday 1 April 2014

Mockito - don't use @InjectMocks if your constructor will be calling methods on your injected mocks

I had this:

@Mock
MessageSource mockMessageSource;

@InjectMocks
PhoneNumberUtil phoneNumberUtil;


@Before
public void setup() {

    MockitoAnnotations.initMocks(this);


    when(mockMessageSource.getMessage(eq("first.key"), (Object[]) eq(null), anyString(),eq(Locale.getDefault()))).thenReturn("This is a default message");
    when(mockMessageSource.getMessage(eq("second.key"), (Object[]) eq(null), anyString(),eq(Locale.getDefault()))).thenReturn("second Value");


}


Where


public PhoneNumberUtil(MessageSource messageSource) {
    this.firstValue = messageSource.getMessage("first.key"), null, FIRST_DEFAULT_VALUE, Locale.getDefault());
    this.secondValue = messageSource.getMessage("second.key"), null, SECOND_DEFAULT_VALUE, Locale.getDefault());
}



I was running my unit test but wondering why the fields "firstValue" and "secondValue" were still coming out as null.

I already mocked the messageSource.getMessage() calls. Why weren't my mocks getting called??

Then I realised: the when().thenReturn() calls weren't getting called until AFTER PhoneNumberUtil was already initialized!


I was using @InjectMocks and once the line

MockitoAnnotations.initMocks(this);

was called, phoneNumberUtil would already get initialised with mockMessageSource. But at that point, mockMessageSource isn't setup to do anything yet.

So the fix was to do this in my setup()



@Mock
MessageSource mockMessageSource;

PhoneNumberUtil phoneNumberUtil;

@Before
public void setup() {

    MockitoAnnotations.initMocks(this);


    when(mockMessageSource.getMessage(eq("first.key"), (Object[]) eq(null), anyString(),eq(Locale.getDefault()))).thenReturn("This is a default message");
    when(mockMessageSource.getMessage(eq("second.key"), (Object[]) eq(null), anyString(),eq(Locale.getDefault()))).thenReturn("second Value");

    phoneNumberUtil = new PhoneNumberUtil(mockMessageSource);

}


If you need to make a call on a mocked dependency in the constructor of the class you're testing, then you can't use the @InjectMocks pattern.

You need to create the class you are testing using code, not annotations, using constructor injection to pass in the mocked dependencies, and you need to create it after you've mocked the methods being called in the constructor.


Friday 14 March 2014

Prevent Googlebot from crawling some links, but still have them useable by the user

WHAT:

Prevent Googlebot from crawling some links, so that other more
important links on our page are given priority and indexed faster


HOW:

1. remove the link, replace with "#" so it's still a valid HREF
2. Put the value as data attribute, ie, data-goto
3. Reverse the value because if we had data-goto="/productlist.html",
Googlebot would still crawl it.
Instead we have data-goto="lmth.tsiltcudorp/"
4. On loading the page, run a javascript to go through all the links
that have this attribute, reverse the string and place it in the
"href" attribute. Googlebot can't run javascript so it never sees the
HREF values in there.

RETURNED BY SERVER

<a class="unseen-link" href="#" data-goto="lmth.tsiltcudorp/">Product List</a>


SEEN BY USER

<a class="unseen-link" href="/productlist.html"
data-goto="lmth.tsiltcudorp/">Product List</a>



function prepareMissingLinks() {
var stringReverse = function(string) {
return string.split('').reverse().join('');
};
var $hiddenLink = $('.unseen-link');

$hiddenLink.each(function() {
$(this).attr("href", stringReverse($(this).data('goto')));
});
}



I had an earlier implementation of this using the hover event but that
doesn't work for touchscreen devices. This works on desktop and
mobile, and is also simpler.

Wednesday 26 February 2014

How to change extension of multiple files in Linux?

When files are in same folder:

rename 's/.abc$/.edefg/' *.abc


Recursively rename files:

# Bash
# Also requires GNU or BSD find(1)
# Recursively change all *.foo files to *.bar

find . -type f -name '*.foo' -print0 | while IFS= read -r -d '' f; do
mv -- "$f" "${f%.foo}.bar"
done



From:
http://askubuntu.com/questions/35922/how-to-change-extension-of-multiple-files-from-command-line

Also see:

http://mywiki.wooledge.org/BashFAQ/030

Wednesday 12 February 2014

@RetryOnFailure annotation using Aspect from JCABI library

Use this annotation to make repeated calls on failure for an idempotent method

http://www.jcabi.com/jcabi-aspects/annotation-retryonfailure.html

Validate user-inputted URLs using Google Safe Browsing API

Use this API to get a database of URLs from Google and verify them
locally. They also have an earlier version of the API but you need to
make a remote call. This is better as the client is the only one that
knows about the URLs it is verifying.

https://developers.google.com/safe-browsing/developers_guide_v2

Thursday 6 February 2014

Notes: Example of image data embedded in HTML

This is a div that appears on the Onion above an article when you've
reached 5 articles already, asking you to subscribe. The image
information is embedded in base64 on the div itself.


<div style="background-image:
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RDhCQzBDREZCQ0ZGMTFFMEIxQkFCQ0MxOEQzMzc5NTEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RDhCQzBDRTBCQ0ZGMTFFMEIxQkFCQ0MxOEQzMzc5NTEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpEOEJDMENEREJDRkYxMUUwQjFCQUJDQzE4RDMzNzk1MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpEOEJDMENERUJDRkYxMUUwQjFCQUJDQzE4RDMzNzk1MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PoOauxEAAAALSURBVAgdYzA+AwABNQEAGVbmvQAAAABJRU5ErkJggg%3D%3D);
z-index: 99998; position: absolute; top: 0px; left: 0px; width: 100%;
height: 3198px;"></div>

Tuesday 4 February 2014

Java: (Spring) Getting subset of a list for paged display

PagedListHolder - one of those Spring classes that you wish you've
been using for the past 10 years

Given a
1. list of items
2. page number and
3. number of items per page

Return the part of the list to be displayed on the page


PagedListHolder<PopularSearch> pagedListHolder = new
PagedListHolder<PopularSearch>(sourceList);
pagedListHolder.setPage(pageNumber);
pagedListHolder.setPageSize(itemCountPerPage);

List<PopularSearch> tmp = pagedListHolder.getPageList();

Friday 31 January 2014

Doubleclick for Publishers reference material

From: https://productforums.google.com/forum/#!category-topic/dfp/getting-started/208IT9kC6Xo

For Premium

DFP Premium Help Center
https://support.google.com/dfp_premium/

Please remember that are two main ways to contact DFP. There is a
Contact Us link on all DFP Premium support page (near the upper right
hand part of the page). There is also a Report a Bug link in your DFP
account (also in the upper right hand corner of your page).

Getting Started Guide (high level overview)
https://support.google.com/dfp_premium/answer/184981

Training
https://support.google.com/dfp_premium/answer/3419426

Partner Directory
https://support.google.com/dfp_premium/answer/2616938

DFP Training Videos:
http://www.youtube.com/dfp

Release Notes
https://support.google.com/dfp_premium/answer/179039


Other Resources

Google also provides additional tools to webmasters to help you track
traffic and improve your search rankings. If you have not signed up
already, you might want to at least take a quick look at them.

Google Analytics
http://www.google.com/analytics/

Google Webmaster Tools
http://www.google.com/webmasters/


Webinars

Google has been releasing quite a few webinars that people maybe
interested in. While not always specific to DFP, many of them are
helpful for webmasters and advertising in general.

You can register for Google Webinars here:
http://www.google.com/ads/experienced/webinars.html

Or use their Calendar to see upcoming Webinars
https://www.google.com/calendar/embed?src=google.com_fqpk56cl9ck36np1ip263m2hks%40group.calendar.google.com

Javascript: Finding the viewport width,

Useful for responsive design, determining same max-width used in @media queries

var windowWidth = window.innerWidth ||
document.documentElement.clientWidth || document.body.clientWidth;

Based on: http://andylangton.co.uk/blog/development/get-viewport-size-width-and-height-javascript


"The responsive viewport breakpoint "staircase" in my opinion becomes:

320px, 480px, 603px, 768px, 966px, 1024px"

See: http://www.hardweb.com.au/nexus7viewportportrait603x797landscape966x444.html

Also read:

http://alistapart.com/article/vexing-viewports


Been working recently on Google DFP tag code, so keeping these references:

http://exisweb.net/how-to-use-google-adsense-on-a-responsive-website

https://productforums.google.com/forum/#!msg/dfp/gxHN91Z7PoI/yC14WsR0KoMJ

http://stackoverflow.com/questions/15423189/changing-ad-size-based-on-browser-width-in-dfp

http://stackoverflow.com/questions/15452905/adding-a-browser-width-component-to-ad-slots




<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title> - jsFiddle demo</title>
<script type='text/javascript'
src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js'></script>
<link rel="stylesheet" type="text/css" href="/css/result-light.css">
<style type='text/css'>
</style>


<script type='text/javascript'>//<![CDATA[
$(window).load(function(){
$("#showValue").click(function () {
var windowWidth = window.innerWidth ||
document.documentElement.clientWidth || document.body.clientWidth;

$("#widthLabel").text(windowWidth);
$("#windowinnerWidth").text(window.innerWidth);
$("#documentdocumentElementclientWidth").text(document.documentElement.clientWidth);
$("#documentbodyclientWidth").text(document.body.clientWidth);
$("#viewportHeight").text($(window).height());

});
});//]]>

</script>


</head>
<body>
<p>Width: <span id="widthLabel"></span>

<br/>window.innerWidth: <span id="windowinnerWidth"></span>

<br/>document.documentElement.clientWidth: <span
id="documentdocumentElementclientWidth"></span>

<br/>document.body.clientWidth: <span id="documentbodyclientWidth"></span>

<br/>$(window).height(): <span id="viewportHeight"></span>
</p>
<input id="showValue" type="button" value="Show Width" />
</body>


</html>

Wednesday 15 January 2014

TIL: Hibernate JPA NamedNativeQuery declaration requires a "resultClass" even for update/delete operations

I was writing some JPA code (Hibernate implementation) that used
NamedNativeQuery

and kept getting this when I ran the webapp in Tomcat:

nested exception is org.hibernate.cfg.NotYetImplementedException: Pure
native scalar queries are not yet supported

The exception was from an unrelated class but I suspected that this
was caused by changes I made.

According to this:

http://jdevelopment.nl/hibernates-pure-native-scalar-queries-supported/

resultClass is required for all NamedNativeQuery, even the ones that
don't return them, because of a longstanding BUG in Hibernate.
Apparently the bug was fixed as of Hibernate 4.2 but we're still on
3.6 so upgrading is not really an option.