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 3/20/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.

// ==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/*
// ==/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:

Sunday, February 26, 2017

How to extract Wechat voice messages

1) The voice messages are stored under /sdccard/tencent/MicroMsg/[akskjdkdkdjdkdkdajhueiieuiuowpq]/voice2. Each voice message has its own folder and is an amr file. Copy these *.amr files from your phone to your PC.

2) Download "wechat_silk" utility from here and extract the "wechat_silk.exe" file onto your computer. Drag the amr files and drop them onto "wechat_silk.exe". You'll get *.wav files on your desktop.

Now you can play these messages on your PC.

Optionally, you may convert and combine the wav files into a single MP3 file:

3) Go to a wav-to-mp3 site such as this to convert wav files to MP3 files.

4) Go to a MP3-combine site such as this and you'll finally have all your wechat voice messages in one MP3 file.

Sunday, February 19, 2017

A must do for Chinese apps

Yesterday I was in CostCo and my Nexus 6 ran quite warmly. It was the Moli TV doing something in the ground. I opened the Swiss knife - Tasker, added the following profile and task to kill it whenever it is in the background.

New profile, Application, 魔力视频,  link to it a new task:

Code, run shell, am force-stop com.molitv.android.v2, use root.

Now go back to the profile, add to it an exit task, link it to this new task as well and unlink the enter task.



From now on, I can still open this app and use it normally to watch TV, it just won't have a chance to run in the back ground.

I did the same for TV Plus. Those are pretty much the only two Chinese apps I use that have no reason to run in the background.