Commit 0a537623 authored by Randall Leeds's avatar Randall Leeds

Merge branch '198-angularjs' into develop

Fix #198

Conflicts:
	h/js/src/controllers.coffee
parents 61308b52 788fa8c1
This diff is collapsed.
angular.module 'h', [
'deform'
'h.controllers'
'h.directives'
'h.services'
]
......@@ -16,10 +16,23 @@ class Hypothesis extends Annotator
showViewPermissionsCheckbox: false,
userString: (user) -> user.replace(/^acct:(.+)@(.+)$/, '$1 on $2')
constructor: (element, options) ->
this.$inject = ['$rootElement', '$scope', '$compile', '$http']
constructor: (@element, @scope, @compile, @http) ->
super @element, @options
# Load plugins
for own name, opts of @options
if not @plugins[name] and name of Annotator.Plugin
this.addPlugin(name, opts)
# Export public, bound functions on the scope
for own key of this
if typeof this[key] == 'function' and not key.match('^_')
@scope[key] = this[key]
# Establish cross-domain communication to the widget host
@provider = new easyXDM.Rpc
swf: options.swf
swf: @options.swf
onReady: this._initialize
,
local:
......@@ -41,8 +54,8 @@ class Hypothesis extends Annotator
if @plugins.Permissions.user?
this.showEditor annotation
else
showAuth true
@editor.hide()
this.showAuth true
this.show()
# This guy does stuff when you "back out" of the interface.
# (Currently triggered by a click on the source page.)
......@@ -77,12 +90,48 @@ class Hypothesis extends Annotator
@renderer.hooks.chain "postConversion", (text) ->
text.replace /<a href=/, "<a target=\"_blank\" href="
super
@scope.$watch 'personas', (newValue, oldValue) =>
if newValue?.length
@element.find('#persona')
.off('change').on('change', -> $(this).submit())
.off('click')
this.showAuth(false)
else
@scope.persona = null
@scope.token = null
@element.find('#persona').off('click').on('click', => this.showAuth())
@scope.$watch 'persona', (newValue, oldValue) =>
if oldValue? and not newValue?
@http.post 'logout', '',
withCredentials: true
.success (data) => @scope.reset()
@scope.$watch 'token', (newValue, oldValue) =>
if @plugins.Auth?
@plugins.Auth.token = newValue
@plugins.Auth.updateHeaders()
if newValue?
if not @plugins.Auth?
this.addPlugin 'Auth',
tokenUrl: @scope.tokenUrl
token: newValue
else
@plugins.Auth.setToken(newValue)
@plugins.Auth.withToken @plugins.Permissions._setAuthFromToken
else
@plugins.Permissions.setUser(null)
delete @plugins.Auth
# Load plugins
for own name, opts of @options
if not @plugins[name] and name of Annotator.Plugin
this.addPlugin(name, opts)
# Fetch the initial model from the server
@http.get 'model'
withCredentials: true
.success (data) =>
angular.extend @scope, data
this.reset()
this.showAuth false
this
......@@ -94,8 +143,8 @@ class Hypothesis extends Annotator
@viewer.show()
@provider.getMaxBottom (max) =>
$('#toolbar').css("top", "#{max}px")
$('#gutter').css("padding-top", "#{max}px")
@element.find('#toolbar').css("top", "#{max}px")
@element.find('#gutter').css("padding-top", "#{max}px")
@heatmap.BUCKET_THRESHOLD_PAD = (
max + @heatmap.constructor.prototype.BUCKET_THRESHOLD_PAD
)
......@@ -108,7 +157,7 @@ class Hypothesis extends Annotator
this.publish 'hostUpdated'
_setupWrapper: ->
@wrapper = $('#wrapper')
@wrapper = @element.find('#wrapper')
.on 'mousewheel', (event, delta) ->
# prevent overscroll from scrolling host frame
# http://stackoverflow.com/questions/5802467
......@@ -121,7 +170,7 @@ class Hypothesis extends Annotator
this
_setupDocumentEvents: ->
$('#toolbar .tri').click =>
@element.find('#toolbar .tri').click =>
if @visible
this.hide()
else
......@@ -272,8 +321,8 @@ class Hypothesis extends Annotator
# Returns itself for chaining.
_setupEditor: ->
@editor = this._createEditor()
.on('hide', @provider.onEditorHide)
.on('save', @provider.onEditorSubmit)
.on('hide', => @provider.onEditorHide)
.on('save', => @provider.onEditorSubmit)
this
_createEditor: ->
......@@ -485,7 +534,7 @@ class Hypothesis extends Annotator
animate parent.classed('collapsed', !collapsed)
when '#reply'
unless @plugins.Permissions?.user
showAuth true
this.showAuth true
break
d3.event.preventDefault()
parent = d3.select(event.currentTarget)
......@@ -561,7 +610,7 @@ class Hypothesis extends Annotator
if @lastWidth > 0 then @provider.setFrameWidth(@lastWidth)
@provider.setActiveHighlights annotations
@provider.showFrame()
$("#toolbar").addClass "shown"
@element.find("#toolbar").addClass "shown"
document.getElementsByClassName('tri')[0].draggable = true
hide: =>
......@@ -570,7 +619,7 @@ class Hypothesis extends Annotator
@provider.setActiveHighlights []
@provider.resetFrameWidth()
@provider.hideFrame()
$("#toolbar").removeClass "shown"
@element.find("#toolbar").removeClass "shown"
document.getElementsByClassName('tri')[0].draggable = false
threadId: (annotation) ->
......@@ -579,4 +628,49 @@ class Hypothesis extends Annotator
else
annotation.id
window.Hypothesis = Hypothesis
showAuth: (show=true) =>
$header = @element.find('header')
visible = !$header.hasClass('collapsed')
if (visible != show)
if (show)
$header.removeClass('collapsed')
else
$header.addClass('collapsed')
$header.one 'webkitTransitionEnd transitionend OTransitionEnd', =>
$header.find('.nav-tabs > li.active > a').trigger('shown')
submit: =>
controls = @element.find('.sheet .active form').formSerialize()
@http.post '', controls,
headers:
'Content-Type': 'application/x-www-form-urlencoded'
withCredentials: true
.success (data) =>
# Extend the scope with updated model data
angular.extend(@scope, data.model)
# Replace any forms which were re-rendered in this response
for oid of data.form
target = '#' + oid
$form = $(data.form[oid])
$form.replaceAll(target)
link = @compile $form
link @scope
deform.focusFirstInput target
reset: =>
angular.extend @scope,
username: null
password: null
email: null
code: null
personas: []
persona: null
token: null
angular.module('h.controllers', [])
.controller('Hypothesis', Hypothesis)
# Extend deform to allow targeting focusing of input when multiple forms
# are on the same page. See https://github.com/Pylons/deform/pull/128
angular.extend deform,
focusFirstInput: (el) ->
el = el || document.body
input = $(el).find(':input')
.filter('[id ^= deformField]')
.filter('[type != hidden]')
.first()
raw = input?.get(0)
if raw?.type in ['text', 'file', 'password', 'textarea']
if raw.className != "hasDatepicker" then input.focus()
# AngularJS directive that creates data bindings for named controls on forms
# with the 'deform' class and triggers deform callbacks during linking.
deformDirective = ->
compile: (tElement, tAttrs, transclude) ->
# Capture the initial values from the server-side render and set a model
# binding for all the named controls.
initValues = {}
$controls = tElement.find('input,select,textarea').filter('[name]')
.filter ->
# Ignore private members (like __formid__) and hidden fields
# (angular does not data-bind hidden fields)
not (this.name.match '^_' or this.type is hidden)
.each ->
initValues[this.name] =
if this.tagName == 'select'
options = []
selected = null
$(this)
.attr(
'data-ng-options',
"value for value in #{this.name}.values"
)
.find('option').filter('[value!=""]')
.each (i) ->
if this.selected then selected = i
options.push
label: this.label or this.innerText
value: this.value
.remove()
options: options
selected: selected
else
this.value
$(this).attr 'data-ng-model', "#{this.name}"
# Link function
(scope, iElement, iAttrs, controller) ->
deform.processCallbacks()
restrict: 'C'
require: 'form'
scope: false
angular.module('deform', []).config [
'$provide', '$compileProvider', '$filterProvider',
($provide, $compileProvider, $filterProvider) ->
# Process any pending callbacks from the initial load
deform.processCallbacks()
# Register the deform service and directive
$provide.value 'deform', deform
$compileProvider.directive 'deform', deformDirective
]
navTabsDirective = (deform) ->
link: (scope, iElement, iAttrs, controller) ->
iElement.find('a')
# Focus the first form element when showing a tab pane
.on 'shown', (e) ->
target = $(e.target).data('target')
deform.focusFirstInput(target)
# Always show the first pane to start
.first().tab('show')
restrict: 'C'
navTabsDirective.$inject = ['deform']
angular.module('h.directives', ['deform'])
.directive('navTabs', navTabsDirective)
angular.module('h.services', [])
......@@ -24,13 +24,13 @@ svg { -webkit-tap-highlight-color: rgba(255, 255, 255, 0); }
//HIDDEN TABS////////////////////////////////
.nav a[data-target="#password-tab"],
.nav a[data-target="#reset-tab"] {
.nav a[data-target="#activate-tab"],
.nav a[data-target="#forgot-tab"] {
display: none;
}
.nav .active a[data-target="#password-tab"],
.nav .active a[data-target="#reset-tab"] {
.nav .active a[data-target="#activate-tab"],
.nav .active a[data-target="#forgot-tab"] {
display: initial;
}
......@@ -268,7 +268,7 @@ svg { -webkit-tap-highlight-color: rgba(255, 255, 255, 0); }
}
}
&.open .provider {
.dropdown.open .provider {
display: inline;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment