let Rx = require('rxjs/Rx')

let mousedowns = Rx.Observable.fromEvent(document, 'mousedown')
  , mousemoves = Rx.Observable.fromEvent(document, 'mousemove')
  , mouseups = Rx.Observable.fromEvent(document, 'mouseup')

let mousedrags = mousedowns.flatMap(x => {
  return mousemoves.map(y => {
    return {
      left: Math.min(x.pageX, y.pageX),
      top: Math.min(x.pageY, y.pageY),
      width: Math.abs(y.pageX - x.pageX),
      height: Math.abs(y.pageY - x.pageY)
    }
  }).takeUntil(mouseups)
})

// create and append rectangle
mousedowns.subscribe(_ => {
  let el = document.createElement('div')
  el.id = "rect"
  el.style.position = "absolute"
  el.style.border = "1px dotted lightblue"
  el.style.zIndex = "9999"
  document.body.appendChild(el)
})

// move rectangle
mousedrags.subscribe(e => {
  let el = document.querySelector("#rect")
  el.style.left = e.left + "px"
  el.style.top = e.top + "px"
  el.style.width = e.width + "px"
  el.style.height = e.height + "px"
})

// remove rectangle
mouseups.subscribe(_ => {
  let el = document.querySelector("#rect")
  if (!el) return
  el.remove()
})

let overlaps = (el1, el2) => {
  let rect1 = el1.getBoundingClientRect()
    , rect2 = el2.getBoundingClientRect()
    , left = Math.max(rect1.left, rect2.left)
    , right = Math.min(rect1.right, rect2.right)
    , top = Math.max(rect1.top, rect2.top)
    , bottom = Math.min(rect1.bottom, rect2.bottom)

    return left < right && top < bottom
}

// merging mousedowns as click without drag should also refresh the links
let overlappedLinks = mousedrags.merge(mousedowns).concatMap(e => {
  let el = document.querySelector("#rect")
  let as = el ? [...document.querySelectorAll('a')].filter(a => overlaps(el, a)) : []
  return Rx.Observable.of(as)
})

// remember the last overlappedLinks
let overlappedLinksPairs = overlappedLinks.scan((acc, cur, _, __) => {
  let prev = acc.cur
  return {prev, cur}
}, {prev:[], cur:[]})

overlappedLinksPairs.subscribe(e => {
  let {prev, cur} = e
  prev.forEach(el => el.style.border = "")
  cur.forEach(el => el.style.border = "2px solid red")
})

mouseups.withLatestFrom(overlappedLinks, (_, as) => as)
  .mergeAll()
  .map(a => a.href)
  .distinct() // using distinct here will prevent same url being opened twice throughout
  .subscribe(url => window.open(url))

console.log("loaded");

@@ -1760,201 +1760,34 @@
 %7D)%0A%0A
-// remember the last overlappedLinks%0Alet overlappedLinksPairs = overlappedLinks.scan((acc, cur, _, __) =%3E %7B%0A  let prev = acc.cur%0A  return %7Bprev, cur%7D%0A%7D, %7Bprev:%5B%5D, cur:%5B%5D%7D)%0A%0AoverlappedLinksPairs
+overlappedLinks.pairwise()
 .sub
@@ -1806,17 +1806,17 @@
 %7B%0A  let 
-%7B
+%5B
 prev, cu
@@ -1816,17 +1816,17 @@
 rev, cur
-%7D
+%5D
  = e%0A  p

Use pairwise() on overlappedLinks instead of scan()