   fullClickableSelector = ->
     config.clickableSelectors.join(',')
 
-  isInstant = (linkOrDescendant) ->
-    element = e.closest(linkOrDescendant, fullInstantSelector())
-    # Allow users to configure up.link.config.instantSelectors.push('a')
-    # but opt out individual links with [up-instant=false].
-    return element && !e.matches(element, '[up-instant=false], [up-follow=false]')
+  isFollowDisabled = (link) ->
+    return e.matches(link, config.noFollowSelectors.join(','))
+
+  isPreloadDisabled = (link) ->
+    return e.matches(link, config.noPreloadSelectors.join(','))
+
+  isInstantDisabled = (link) ->
+    return e.matches(link, config.noInstantSelectors.join(','))
 
   ###**
   @property up.link.config

    link = up.fragment.get(link)
    return e.matches(link, fullFollowSelector()) && !isFollowDisabled(link)

  isFollowDisabled = (link) ->
    return e.matches(link, '[up-follow=false]')

  ###**
  Makes sure that the given link will be [followed](/up.follow)
  by Unpoly instead of making a full page load.

    betterTargetSelector = "a, [up-href], #{up.form.fieldSelector()}"
    betterTarget = e.closest(event.target, betterTargetSelector)
    return (!betterTarget || betterTarget == link) && !isFollowDisabled(link)

  isInstant = (linkOrDescendant) ->
    element = e.closest(linkOrDescendant, fullInstantSelector())
    # Allow users to configure up.link.config.instantSelectors.push('a')
    # but opt out individual links with [up-instant=false].
    return element && !isInstantDisabled(element)

  ###**
  Provide an `up:click` event that improves on standard click
