Skip to content

Commit

Permalink
switch from Prototype to Zepto.js + CoffeeScript
Browse files Browse the repository at this point in the history
  • Loading branch information
mislav committed Sep 1, 2011
1 parent 05b1600 commit d4c6e7f
Show file tree
Hide file tree
Showing 8 changed files with 1,478 additions and 6,284 deletions.
23 changes: 23 additions & 0 deletions app/assets/javascripts/actions.coffee
@@ -0,0 +1,23 @@
$(document).delegate '.actions input[type=submit].watched', 'click', ->
$(this).closest('.actions').addClass('asking')
false

$(document).delegate '.actions input[type=submit].watched', 'ajax:before', ->
false

$(document).delegate '.actions .question a[href="#cancel"]', 'click', ->
$(this).blur().closest('.actions').removeClass('asking')
false

$(document).delegate '.actions .button_to', 'ajax:success', (e, html) ->
replaceActions $(this).closest('.actions'), html

$(document).delegate 'a.revert', 'ajax:success', (e, html) ->
replaceActions $(this).closest('.actions'), html

# preserve the ".other-info" element while replacing ".actions"
replaceActions = (element, content) ->
parent = element.parent()
element.replaceWith(content)
preserve = element.find('.js-preserve')
parent.find('.actions').eq(0).prepend preserve
205 changes: 3 additions & 202 deletions app/assets/javascripts/application.js
@@ -1,202 +1,3 @@
//= require prototype
//= require rails
//*= require_tree .

if ('createTouch' in document) {
try {
$A(document.styleSheets).each(function(stylesheet){
var ignore = /:hover\b/, idxs = []
$A(stylesheet.cssRules).each(function(rule, idx) {
if (rule.type == CSSRule.STYLE_RULE && ignore.test(rule.selectorText)) {
idxs.push(idx)
}
})
idxs.reverse().each(function(idx) { stylesheet.deleteRule(idx) })
})
} catch (e) {}
}

document.on('click', '.actions input[type=submit].watched', function(e, button) {
e.stop()
button.up('.actions').addClassNameTransition('asking')
})
document.on('ajax:before', '.actions input[type=submit].watched', function(e) { e.stop() })

document.on('click', '.actions .question a[href="#cancel"]', function(e, link) {
e.stop()
link.blur()
link.up('.actions').removeClassNameTransition('asking')
})

document.on('ajax:success', '.actions .button_to', function(e, form) {
if (useTransitions && !Prototype.Browser.Opera) {
form.select('input[type=submit][data-disable-with]').invoke('removeAttribute', 'data-disable-with')

form.up('.actions').addClassName('fadeout').transitionEnd(function() {
var parent = this.up()
this.replaceActions(e.memo.responseText)
var actions = parent.down('.actions')
actions.addClassName('hidden')
;(function() { actions.removeClassName('hidden').addClassName('fadein') }).defer()
})
} else {
form.up('.actions').replaceActions(e.memo.responseText)
}
})

document.on('ajax:success', 'a.revert', function(e, link) {
link.up('.actions').replaceActions(e.memo.responseText)
})

Element.addMethods({
getText: function(element) {
element = $(element)
return element.textContent || element.innerHTML.stripTags()
},
once: function(element, event, selector, fn) {
element = $(element)
if (!fn) { fn = selector, selector = null }

var handler, executed = false, wrapper = function() {
if (!executed) {
fn.apply(this, arguments)
executed = true
handler.stop()
}
}
if (selector) handler = element.on(event, selector, wrapper)
else handler = element.on(event, wrapper)

return handler
},
// preserve the ".other-info" element while replacing ".actions"
replaceActions: function(element, content) {
element = $(element)
var parent = element.up()
element.replace(content)
parent.down('.actions').insert({ top: element.down('.js-preserve') })
return element
}
})

var useTransitions = Modernizr.csstransitions,
transitionEvent = Prototype.Browser.WebKit ? 'webkitTransitionEnd' :
Prototype.Browser.Opera ? 'oTransitionEnd' : 'transitionend'

if (useTransitions) {
Element.addMethods({
addClassNameTransition: function(element, name) {
element = $(element)
tmpName = name + '-transition'
element.addClassName(tmpName).transitionEnd(function() {
element.removeClassName(tmpName).addClassName(name)
})
return element
},
removeClassNameTransition: function(element, name) {
element = $(element)
tmpName = name + '-transition-back'
element.removeClassName(name).addClassName(tmpName).transitionEnd(function() {
element.removeClassName(tmpName)
})
return element
},
transitionEnd: function(element, handler) {
element = $(element)
element.once(transitionEvent, handler)
return element
}
})
} else {
Element.addMethods({
addClassNameTransition: Element.addClassName,
removeClassNameTransition: Element.removeClassName
})
}

Function.prototype.throttle = function(t) {
var timeout, scope, args, fn = this, tick = function() {
fn.apply(scope, args)
timeout = null
}
return function() {
scope = this
args = arguments
if (!timeout) timeout = setTimeout(tick, t)
}
}

var pagination = $$('.pagination').first()

if (pagination) {
var page = parseInt(pagination.down('em').getText()),
lastPage = parseInt(pagination.select('a:not(.next_page)').last().getText()),
url = window.location.toString(),
container = $$('ol.movies').first(),
loading = false

var scrollHandler = Element.on(Prototype.Browser.WebKit ? document : window, 'scroll', function() {
if (loading) return
var viewportHeight = document.viewport.getHeight()

if (pagination.viewportOffset().top - viewportHeight < viewportHeight/2) {
loading = true
new Ajax.Request(url, {
method: 'get', parameters: {page: ++page},
onSuccess: function(r) {
container.insert(r.responseText)
if (page == lastPage) {
scrollHandler.stop()
pagination.hide()
}
loading = false
}
})
}
})
}

// Emulates HTML5 "placeholder" and "autofocus" attributes.
// from https://github.com/teambox/teambox/blob/master/app/javascripts/html5.js
document.on('dom:loaded', function() {
if (!window.Modernizr) return

if (!Modernizr.input.placeholder) {
var selector = 'input[placeholder], textarea[placeholder]'

function emulatePlaceholder(input) {
var val = input.getValue(), text = input.readAttribute('placeholder')
if (val.empty() || val === text)
input.setValue(text).addClassName('placeholder')
}

document.on('focusin', selector, function(e, input) {
if (input.getValue() === input.readAttribute('placeholder'))
input.setValue('').removeClassName('placeholder')
})

document.on('focusout', selector, function(e, input) {
emulatePlaceholder(input)
})

// setup existing fields
$$(selector).each(emulatePlaceholder)

// observe form submits and clear emulated placeholder values
$(document.body).on('submit', 'form:has(' + selector + ')', function(e, form) {
form.select(selector).each(function(field) {
if (field.getValue() == field.readAttribute('placeholder')) field.setValue('')
})
})

// observe new forms inserted into document and setup fields inside
document.on('DOMNodeInserted', 'form', function(e) {
if (e.element().match('form')) e.element().select(selector).each(emulatePlaceholder)
})
}

if (!Modernizr.input.autofocus) {
var input = $(document.body).down('input[autofocus]')
if (input) input.activate()
}
})
//= require zepto
//= require ujs
//= require_tree .
43 changes: 43 additions & 0 deletions app/assets/javascripts/html5.coffee
@@ -0,0 +1,43 @@
# Emulates HTML5 "placeholder" and "autofocus" attributes.
# from https://github.com/teambox/teambox/blob/master/app/javascripts/html5.js
$ ->
return unless window.Modernizr

unless Modernizr.input.placeholder
inputs = $('input[placeholder], textarea[placeholder]')

emulatePlaceholder = (input) ->
val = input.val()
text = input.attr('placeholder')
if not val or val is text
input.val(text).addClass 'placeholder'

inputs.live 'focusin', ->
input = $(this)
if input.val() is input.attr('placeholder')
input.val('').removeClass 'placeholder'

inputs.live 'focusout', ->
emulatePlaceholder $(this)

# setup existing fields
inputs.each ->
emulatePlaceholder $(this)

$(document).delegate "form:has(#{inputs.selector})", 'submit', ->
$(this).find(inputs.selector).each ->
input = $(this)
input.val('') if input.val() is field.attr('placeholder')

# observe new forms inserted into document and setup fields inside
$(document).delegate 'form', 'DOMNodeInserted', (e) ->
el = $(this)
if el.is('form')
el.find(inputs.selector).each ->
emulatePlaceholder $(this)

unless Modernizr.input.autofocus
input = $('input[autofocus]').eq(0)
if input.size()
input.focus()
input.get(0).select()
30 changes: 30 additions & 0 deletions app/assets/javascripts/pagination.coffee
@@ -0,0 +1,30 @@
pagination = $('.pagination').eq(0)

viewportOffset = (el) ->
el.offset().top - document.body.scrollTop

if pagination.size()
page = parseInt(pagination.find('.current').text())
lastPage = parseInt(pagination.find('a:not(.next_page)').eq(-1).text())
url = window.location.toString()
container = $('ol.movies').eq(0)
loading = false
scrollElement = if Zepto.browser.webkit then document else window

$(scrollElement).bind 'scroll', ->
return if loading
viewportHeight = document.documentElement.clientHeight
paginationOffset = viewportOffset(pagination) - viewportHeight

if paginationOffset < viewportHeight/2
loading = true
$.ajax
method: 'get'
data:
page: ++page
success: (data) ->
container.append data
if page is lastPage
$(scrollElement).unbind 'scroll'
pagination.hide()
loading = false
12 changes: 12 additions & 0 deletions app/assets/javascripts/touch_nohover.coffee
@@ -0,0 +1,12 @@
if 'createTouch' of document
ignore = /:hover\b/
try
for stylesheet in document.styleSheets
idxs = []
# detect hover rules
for rule, idx in stylesheet.cssRules
if rule.type is CSSRule.STYLE_RULE and ignore.test(rule.selectorText)
idxs.unshift idx

# delete hover rules
stylesheet.deleteRule idx for idx in idxs

0 comments on commit d4c6e7f

Please sign in to comment.