Friday, March 31, 2017

Nikon D3300 focus problem and fix

They are on clearance in Walmart stores and I'm lucky enough to grab one at $299. Right out of box, photos are blurry, very. After some tests I confirmed front-focus problem with both lenses (18-55 and 55-200):



As both lenses do the same front-focus thing, it must be the camera body. So I enabled sensor clean procedure to lift up the mirror, turned the auto focus screw counterclockwise a little bit (about 10 degree or so), as instructed here.

Now both lenses focused at the center perfectly:



I used to be against to DSLR, because they were big, heavy and expensive. Things have changed in recent years, they have been getting smaller, lighter and inexpensive, under the competition from mirrorless and smartphones. Their lenses are more and relative cheap.

Sunday, March 26, 2017

Tweaks for ZTE Trek 2 K88 HD Tablet

[update] How to solve the touch issue

For only $60, you get a very fast and smooth 8" tablet that you'll love to use it to do serious work or play for fun:

  • 2GB RAM and 16GB storage that can be expanded via MicroSD.
  • 1280x800 bright and clear screen, non reflective, not the stupid 16:9.
  • 5M front and rear cameras.
  • Two front facing speakers, loud and clear.
  • Unlock code provided, use it on T-Mobile and in other countries including China.
  • FM radio, clean and good reception, timer off, but mono.
  • Large battery that last for a day of heavy use and idle forever.
  • Good GPS for offline or online navigation.
No root

Fortunately not many garbages, and half of them can be easily disabled. For annoying notifications: press and hold on it, then click on the info icon and block it.



If Google stuff is a problem (such as in China), use noroot firewall to block them.

Hotspot

This function is hidden, but you can use it with WiFi Hotspot Pro.


Calls

It cannot do calls and texts in the way of normal smartphones do. The built-in dialer and SMS apps are modified, the NumberSync craps that are VoIP based. They are no different than Hangouts, except the CID is spoofed to that of an AT&T postpaid #.

You do can install the Android Messages and Dialer by Google. Then SMS will work like is on an ordinary phone. For the dialer, however, not much you can. You can only install the old RC8 versions because RC9 and newer cannot install on non-Google phones. For newer versions, you can find some hacked ones on XDA.

You still cannot make phone calls though, because some necessary libraries are crippled, like all other tablets sold in monopoly USA. You do can dial some secret codes, such as *#*#4636#*#*, then turn radio off to save battery:


Browser

Use Yandex, please, don't bother with all others! A truly full browser, plus the MS RDP, are what make a tablet a productive tool to leave your computer home.



If you don't use Google Play Store and Drive, disable their app links. Then Play Store and Drive links will be opened in Yandex.


Few photos

Low light, normal light and front camera:




This article is written on this tablet. The built-in Gallery app is very handy for cropping and doodling photos.

No battery drain during idle under WiFi. Very little drain when LTE signal is poor:


Friday, March 17, 2017

Philips SHP9500S

For $50, these headphones are extremely comfortable and sound great - very detailed and flat. Their impedance is 30 ohm, easy to drive by phones and media players. Because they are open-back, healthy for ears, but don't use them in a noisy environment though.


They beat Grado 60 on each and every aspects, as the entry to good sound. As these are extremely comfortable, you don't suffer while enjoying great tunes like you do with Grado 60. And they sound better, much better. My HD518 do not offer the veil-less sound from these.

The only issue I have with them is too weak clamping force - they move and even drop whenever I look for something on the ground. This also causes a stress after a while, because my head tends not to move due to the fear of dropping the headphones.

Fortunately, there is an easy workaround. Now I can wear them even while doing some labor work. They have thus replaced officially my daily-wearing headphones - Koss KSC35/75.


As you see, I use Samsung HS3000 to make them wireless (with large battery to last at least a whole day), thanking to the standard 3.5 mm jack. Comfortable and convenient, cannot ask for more.

If you need headphones in a noisy environment, check the Phillips SHB9850NC. The 9850 and 9500S are pretty much the only headphones I use these days.

Friday, March 10, 2017

KoT's Dynamic Content Blocker

My two scripts, Block GIF and AD Block, worked so well, so I combined them into one. I also added another transparent button for iFrame block. Being able to block or unlock on the fly and to save the preference to a site or sub-site, this method is perfect. Can be easily modified, improved, extended and expanded as well.

I am not against to ads, but I hate dynamic contents - too annoying and distractive, killing battery, slowing devices down and running them hot. Because all contents are blocked not removed, the original page format is retained and there is no up-down or left-right shifting.

See how well it works:



I also use The Great Suspender to unload tabs after 5 minutes. Now, there is no CPU consumption, how great is this!



The following script has been (on 5/22/2017) and will be updated. If you want to unblock an item, please let me know so I can find out the iframe for you and add it to the NOT_TO_REMOVE list.

You need to install Greasemonkey (Firefox) or Violentmonkey (Chrome, Opera and Yandex), add a new script and copy and paste the following lines.

// ==UserScript==
// @name         KoT's Content Blocker
// @namespace    http://www.kots.us
// @grant        none
// @exclude      https://xfinity.nnu.com/xfinitywifi/main
// @exclude      https://www.blogger.com/*
// @exclude      https://groups.google.com/forum/*
// @exclude      https://productforums.google.com/forum/*
// @exclude      https://postage.ebay.com/ws/eBayISAPI.dll*
// @exclude      https://ibdswebp41-ext.pb.com/images/USPS/HTMLFolders/HTML14/*
// ==/UserScript==

/* add your items not to be blocked */

var NOT_TO_REMOVE = 
    ':not([src*=\'youtu\'])' +
    ':not([src*=\'dailymotion\'])' +
    ':not([src*=\'youku\'])' +
    ':not([src*=\'tudou\'])' +
    ':not([src*=\'powermv\'])' +
    ':not([src*=\'dramafever\'])' +
    ':not([src*=\'vimeo\'])' +
    ':not([src*=\'liveguidestationplayer\'])' +
    ':not([src*=\'RoutePositionET\'])' +
    ':not([src*=\'blogger.com\'])' +
    ':not([src*=\'chase.com\'])' +
    ':not([src*=\'/tob/live/usp-core\'])' +
    ':not([src*=\'vi.vipr.ebaydesc.com\'])' +
    ':not([src*=\'signin.ebay.com/ws/\'])' +
    ':not([iframe-src*=\'mail.com\'])' +
    ':not([src*=\'captcha\'])'
;

/* add your items to be blocked */

var TO_REMOVE = 'div[id^=\'carousel\']' +
    ',div[id^=\'Carousel\']' +
    ',iframe[src^=\'/news/index.php?act=getiframe\']' +
    ',iframe[src^=\'javascript\']' +
    ',div[class^=\'eis_slide\']'
;

/* add special items to be blocked */

function blockSpecialItems() {
  var m = document.getElementById('scrollWrap');
  if (m !== null) {
    m.id = 'scrollWrap_';
    m = document.getElementById('scrollMsg');
    if (m !== null) {
      m.parentNode.removeChild(m);
    }
  }
}

/* no need to change below */

function getCookie(w){
cName = "";
pCOOKIES = new Array();
pCOOKIES = document.cookie.split('; ');
for(bb = 0; bb < pCOOKIES.length; bb++){
NmeVal  = new Array();
NmeVal  = pCOOKIES[bb].split('=');
if(NmeVal[0] == w){
cName = unescape(NmeVal[1]);
}
}
return cName;
}

function setCookie(name, value, expires, path, domain, secure){
cookieStr = name + "=" + escape(value) + "; ";

if(expires){
expires = setExpiration(expires);
cookieStr += "expires=" + expires + "; ";
}
if(path){
cookieStr += "path=" + path + "; ";
}
if(domain){
cookieStr += "domain=" + domain + "; ";
}
if(secure){
cookieStr += "secure; ";
}

document.cookie = cookieStr;
}

function setExpiration(cookieLife){
    var today = new Date();
    var expr = new Date(today.getTime() + 
                        cookieLife * 24 * 60 * 60 * 1000);
    return  expr.toGMTString();
}

function is_gif_image(i) {
  return /^(?!data:).*\.gif/i.test(i.src);
}

function freeze_gif(i) {

  hasGIF = true;
  
  var c = document.createElement('canvas');
  var w = c.width = i.width;
  var h = c.height = i.height;
  c.getContext('2d').drawImage(i, 0, 0, w, h);
  try {
    // if possible, retain all css aspects
    i.src = c.toDataURL("image/gif");
  } catch(e) {
    // cross-domain -- mimic original with all its tag attribs
    for (var j = 0, a; a = i.attributes[j]; j++)
      c.setAttribute(a.name, a.value);
    i.parentNode.replaceChild(c, i);
  }
}

function blockMarquee() {
  var m = document.getElementsByTagName('marquee');
  while( m.length > 0) {
    var p = document.createElement('div');
    p.innerHTML = m[0].innerHTML;
    var wth = (m[0].style.width == "") ? "350" : m[0].style.width;
    var stl = "clear: both; white-space: nowrap; overflow: hidden;" +
        "text-overflow: ellipsis; width:" + wth + ";";
    p.setAttribute('style', stl);
    m[0].parentNode.insertBefore(p, m[0]);
    m[0].parentNode.removeChild(m[0]);
  }
}

function blockContents(elements) {
  for (var i = 0; i < elements.length; i++) {
    hasIframe = true;
    var frm = document.createElement("iframe");
    frm.width = elements[i].width;
    frm.height = elements[i].height;
    frm.style.border = "none";
    frm.style.float = elements[i].style.float;
    frm.style.position = elements[i].style.position;
    frm.style.display = elements[i].style.display;
    frm.style.margin = elements[i].style.margin;
    elements[i].parentNode.replaceChild(frm, elements[i]);
  } 
}

function createButton(label) {
  if(label == 'GiF') {
    var rt = '7%';
    var ck = 'blockGIF';
    var hs = hasGIF;
  }
  else {
    rt = '1%';
    ck = 'blockIframe';
    hs = hasIframe;
  }
  var btn = document.createElement( 'input' );
  with( btn ) {
    onclick = function() {
      if (getCookie(ck) !== 'No') {
        setCookie(ck, 'No', 3650);
      }
      else { 
        setCookie(ck, '', -1); 
        setCookie(ck, '', -1, '/'); 
      }  
      location.reload();
    };
    setAttribute( 'value', label );
    setAttribute( 'type', 'button' );
    var stl = "font-size: 18px; position: fixed;bottom: 1%;" +
        "background-color: Transparent; background-repeat:" + 
        "no-repeat; cursor: pointer; overflow: hidden;" + 
        "right:" + rt + ";" + "color:";
    if (getCookie(ck) !== "No")
      if (hs)
        stl += "red;";
      else
        stl += "gray;";
    else
      stl += "green;";
   setAttribute( 'style', stl );
  }
  document.body.appendChild(btn);  
}

function doBlock() {

  if (getCookie('blockIframe') !== 'No') {
    blockContents(document.querySelectorAll(NOT_TO_REMOVE));
    blockContents(document.querySelectorAll(TO_REMOVE)); 
  }
  
  //Firefox has a good addon: Toggle aninated GIFs
  if (typeof InstallTrigger == 'undefined') {
    if (getCookie('blockGIF') !== 'No')
      [].slice.apply(document.images).filter(is_gif_image)
        .map(freeze_gif);
  }
  
  if (window.top !== window.self)
    return;
  
  if (typeof InstallTrigger == 'undefined')
    createButton ('GiF');
  createButton ('FrM'); 
  
}

NOT_TO_REMOVE = 'iframe:not([src])' + NOT_TO_REMOVE + 
  ',iframe[src^=\'http\']' + NOT_TO_REMOVE;

doBlock();

if (window.top !== window.self)
  return;

var hasGIF = false;
var hasIframe = false;

blockSpecialItems();
blockMarquee();
  
//some items are delayed to show up
window.addEventListener ('load', function(){ 
  doBlock();
  window.setTimeout(doBlock, 4000);
}, false);

Wednesday, March 8, 2017

My script for blocking GIF

I cannot find a good animation block extension for Opera and Yandex which are my current favorite browsers for Windows and Android, respectively. GIF Jam jams loading of a page while jamming GIF. So is GIF Blocker, although faster. Stop Animations does not block GIF by default; so you have to press ESC key all the time - quite a hassle and no ESC key on a phone.

Therefore I had to make one. I found a script that does what is similar to Stop Animations. I changed it to block GIF by default. I also added a transparent "GIF" button to unblock (or block) GIF on the fly and save the option to the site via cookie (Opera does not support GM_setValue, code is from here).


This button is located at the bottom right corner. On the phone, this button might be a little hard to find if you zoom the page. The button label is gray if blocking is enabled (default) and, if one or more GIF images got blocked, it becomes red, or green if disabled (not blocking). So you'll know if you are missing something. This script does not add obvious slowdown and other side effects.

Related article: KoT's Dynamic Content BlockerMy ad-block script

This script has been (on 03/09/2017) and will be updated without notice

// ==UserScript==
// @name         KoT's Content Blocker
// @namespace    http://www.kots.us
// @grant        none
// @exclude      https://xfinity.nnu.com/xfinitywifi/main
// @exclude      https://www.blogger.com/*
// @exclude      https://groups.google.com/forum/*
// ==/UserScript==

/* add your items not to be blocked */

var NOT_TO_REMOVE = 
    ':not([src*=\'youtu\'])' +
    ':not([src*=\'dailymotion\'])' +
    ':not([src*=\'youku\'])' +
    ':not([src*=\'tudou\'])' +
    ':not([src*=\'powermv\'])' +
    ':not([src*=\'dramafever\'])' +
    ':not([src*=\'vimeo\'])' +
    ':not([src*=\'liveguidestationplayer\'])' +
    ':not([src*=\'RoutePositionET\'])' +
    ':not([src*=\'blogger.com\'])' +
    ':not([src*=\'chase.com\'])' +
    ':not([src*=\'/tob/live/usp-core\'])'   
;

/* add your items to be blocked */

var TO_REMOVE = 'div[id*=\'carousel\']' +
    ',div[id*=\'Carousel\']' +
    ',iframe[src^=\'/news/index.php?act=getiframe\']' +
    ',iframe[src^=\'javascript\']'
;

/* add special items to be blocked */

function blockSpecialItems() {
  var m = document.getElementById('scrollWrap');
  if (m !== null) {
    m.id = 'scrollWrap_';
    m = document.getElementById('scrollMsg');
    if (m !== null) {
      m.parentNode.removeChild(m);
    }
  }
}

/* no need to change below */

function getCookie(w){
cName = "";
pCOOKIES = new Array();
pCOOKIES = document.cookie.split('; ');
for(bb = 0; bb < pCOOKIES.length; bb++){
NmeVal  = new Array();
NmeVal  = pCOOKIES[bb].split('=');
if(NmeVal[0] == w){
cName = unescape(NmeVal[1]);
}
}
return cName;
}

function setCookie(name, value, expires, path, domain, secure){
cookieStr = name + "=" + escape(value) + "; ";

if(expires){
expires = setExpiration(expires);
cookieStr += "expires=" + expires + "; ";
}
if(path){
cookieStr += "path=" + path + "; ";
}
if(domain){
cookieStr += "domain=" + domain + "; ";
}
if(secure){
cookieStr += "secure; ";
}

document.cookie = cookieStr;
}

function setExpiration(cookieLife){
    var today = new Date();
    var expr = new Date(today.getTime() + 
                        cookieLife * 24 * 60 * 60 * 1000);
    return  expr.toGMTString();
}

function is_gif_image(i) {
  return /^(?!data:).*\.gif/i.test(i.src);
}

function freeze_gif(i) {

  hasGIF = true;
  
  var c = document.createElement('canvas');
  var w = c.width = i.width;
  var h = c.height = i.height;
  c.getContext('2d').drawImage(i, 0, 0, w, h);
  try {
    // if possible, retain all css aspects
    i.src = c.toDataURL("image/gif");
  } catch(e) {
    // cross-domain -- mimic original with all its tag attribs
    for (var j = 0, a; a = i.attributes[j]; j++)
      c.setAttribute(a.name, a.value);
    i.parentNode.replaceChild(c, i);
  }
}

function blockMarquee() {
  var m = document.getElementsByTagName('marquee');
  while( m.length > 0) {
    var p = document.createElement('div');
    p.innerHTML = m[0].innerHTML;
    var wth = (m[0].style.width == "") ? "350" : m[0].style.width;
    var stl = "clear: both; white-space: nowrap; overflow: hidden;" +
        "text-overflow: ellipsis; width:" + wth + ";";
    p.setAttribute('style', stl);
    m[0].parentNode.insertBefore(p, m[0]);
    m[0].parentNode.removeChild(m[0]);
  }
}

function blockContents(elements) {
  for (var i = 0; i < elements.length; i++) {
    hasIframe = true;
    var frm = document.createElement("iframe");
    frm.width = elements[i].width;
    frm.height = elements[i].height;
    frm.style.border = "none";
    frm.style.float = elements[i].style.float;
    frm.style.position = elements[i].style.position;
    elements[i].parentNode.replaceChild(frm, elements[i]);
  } 
}

function createButton(label) {
  if(label == 'GiF') {
    var rt = '1%';
    var ck = 'blockGIF';
    var hs = hasGIF;
  }
  else {
    rt = '7%';
    ck = 'blockIframe';
    hs = hasIframe;
  }
  var btn = document.createElement( 'input' );
  with( btn ) {
    onclick = function() {
      if (getCookie(ck) !== 'No') {
        setCookie(ck, 'No', 3650);
      }
      else { 
        setCookie(ck, '', -1); 
        setCookie(ck, '', -1, '/'); 
      }  
      location.reload();
    };
    setAttribute( 'value', label );
    setAttribute( 'type', 'button' );
    var stl = "font-size: 18px; position: fixed;bottom: 1%;" +
        "background-color: Transparent; background-repeat:" + 
        "no-repeat; cursor: pointer; overflow: hidden;" + 
        "right:" + rt + ";" + "color:";
    if (getCookie(ck) !== "No")
      if (hs)
        stl += "red;";
      else
        stl += "gray;";
    else
      stl += "green;";
   setAttribute( 'style', stl );
  }
  document.body.appendChild(btn);  
}

function doBlock() {

  if (getCookie('blockIframe') !== 'No') {
    blockContents(document.querySelectorAll(NOT_TO_REMOVE));
    blockContents(document.querySelectorAll(TO_REMOVE)); 
  }
  
  if (getCookie('blockGIF') !== 'No')
    [].slice.apply(document.images).filter(is_gif_image)
      .map(freeze_gif);
  
  createButton ('GiF');
  createButton ('FrM'); 
  
}

//for main frame only:
if (window.top !== window.self)
  return;

var hasGIF = false;
var hasIframe = false;

NOT_TO_REMOVE = 'iframe:not([src])' + NOT_TO_REMOVE + 
  ',iframe[src^=\'http\']' + NOT_TO_REMOVE;

blockSpecialItems();
blockMarquee();

doBlock();
  
//some items are delayed to show up
window.addEventListener ('load', function(){ 
  doBlock();
  window.setTimeout(doBlock, 4000);

}, false);

Thursday, March 2, 2017

My ad-block script

Why not using an add-on/extension like adblock etc.? Because many sites now block them! And they tend to block some wanted content while leave some unwanted unblocked.

You'll need to install the Greasemonkey (Firefox) or Violent Monkey (Chrome, Yandex and Opera). Then add a new script and copy & paste. All dynamic contents are removed; so be sure to add to the "NOT_TO_REMOVE" list the iframe src's that you do want to see! Or you may add exceptional line(s) like this within metadata block:

// @exclude     http://www.example.com/foo/baz

Now your browsers should be totally quiet without any unwanted moving stuff. Timers are removed too!

Related article: KoT's Dynamic Content BlockerMy script for blocking GIF

This script has been (on 03/09/2017) and will be updated without notice

// ==UserScript==
// @name         Block Marquee
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @include      http*://*/*
// @exclude      https://xfinity.nnu.com/xfinitywifi/main
// @exclude      https://www.blogger.com/*
// @exclude      https://groups.google.com/forum/*
// @grant        none
// ==/UserScript==
    
/* add your items to be not blocked */

var NOT_TO_REMOVE = 'iframe' +
':not([src*=\'youtu\'])' +
':not([src*=\'dailymotion\'])' +
':not([src*=\'youku\'])' +
':not([src*=\'tudou\'])' +
':not([src*=\'powermv\'])' +
':not([src*=\'dramafever\'])' +
':not([src*=\'vimeo\'])' +
':not([src*=\'liveguidestationplayer\'])' +
':not([src*=\'RoutePositionET\'])' +
':not([src*=\'blogger.com\'])' +
':not([src*=\'chase.com\'])' +
':not([src*=\'/tob/live/usp-core\'])'
;

/* add your items to be blocked */

var TO_REMOVE = 'div[id*=\'carousel\']' +
',div[id*=\'Carousel\']' 
;

function doRemove() {

  var m, i;
  
  if (window.top == window.self) {
      m = document.querySelectorAll(NOT_TO_REMOVE);
      for (var i = 0; i < m.length; i++) {
        m[i].parentNode.removeChild(m[i]);
      }
  }
  
  m = document.querySelectorAll(TO_REMOVE);
  for (i = 0; i < m.length; i++) {
    m[i].parentNode.removeChild(m[i]);
  }
  
  // Thanks to http://stackoverflow.com/a/8345837
  // Set a fake timeout to get the highest timeout id
  var highestTimeoutId = setTimeout(";");
  for (i = 0 ; i < highestTimeoutId ; i++) {
      clearTimeout(i); 
  }

}

var m, i;

/* block Special items */

m = document.getElementById('scrollWrap');
if (m !== null) {
  m.id = 'scrollWrap_';
  m = document.getElementById('scrollMsg');
  if (m !== null) {
    m.parentNode.removeChild(m);
  }
}

/* block common items */

m = document.getElementsByTagName('marquee');
for (i = 0; i < m.length; i++) {
  var p = document.createElement('div');
  p.innerHTML = m[0].innerHTML;
  p.setAttribute('style', 'width: 100%; clear: both;');
  m[0].parentNode.insertBefore(p, m[0]);
  m[0].parentNode.removeChild(m[0]);
}

//Don't run on frames or iframes
if (window.top !== window.self) 
    return;

doRemove(); window.addEventListener('load', doRemove, false);

Wednesday, March 1, 2017

The only acceptable browser for Android: Yandex

Since I upgraded my Nexus 6 to the latest OS 7.1.1, I have been searching for a browser that does these two simple things:

1) Text wrapping (text-reflow, auto-fit)
2) Remember passwords

Without text wrapping, I don't know how anybody could read anything on the phone's small screen. As for password-remember, it is virtually impossible for anyone to type in passwords over and over again on the phone's tiny keyboard.


Yandex and Opera are the only two can do these two simple things, believe it or not. I didn't try FireFox and Chrome though, because they suck, they use too much resources and run phone hot. I pick Yandex over Opera, because it is quite a hassle to use tabs with Opera and it sometimes drains battery while phone is idling.


Yandex has some very thoughtful features too. For example, address bar is at the bottom, as you see in above first photo. It is auto-hidden, and, the best part, I only need to move the page down just a little bit to let it appear. Because it is based on the same source code of Chrome, so all Chrome and Opera extensions work with Yandex! I use the Autofill extension to remember the few passwords that Yandex won't. Yes, all, I mean ALL, passwords can be remembered! So this Yandex really works for everything you do on a desktop computer! You can even block Youtube ads with one of such extensions!


I cannot say enough how great Yandex is. I do have one complaint: cannot disable the stupid preview mode; so have to double touch for each and every site. Apple invented two great things that ruined user experience on every smartphone: one is swipe to answer a call and the other is this preview mode.

The followings are the ones I tried but could not do at least one of the above two simple things:

Boat
Dolphin
Next
Naked
Via
UC (text is often messily formatted)
Maxthon
Flynx
Ghostery
Lightning

There might be even more, but I can no longer remember.

PS: There are few sites that Autofill cannot automatically add their username and password. "reg.usps.com" is one of them, but can be easily added manually: