Skip to content

Commit

Permalink
Merge pull request #52 from jh3y/develop
Browse files Browse the repository at this point in the history
Merge in multiple changes
  • Loading branch information
jh3y committed Oct 17, 2015
2 parents 8e275f3 + 9279e7d commit d9893ce
Show file tree
Hide file tree
Showing 22 changed files with 394 additions and 52 deletions.
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tyto",
"version": "2.1.2",
"version": "2.2.2",
"homepage": "https://github.com/jh3y/tyto",
"authors": [
"jh3y <[email protected]>"
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tyto",
"version": "2.1.2",
"version": "2.2.2",
"description": "tyto - manage and organise",
"engines": {
"node": "0.10",
Expand Down Expand Up @@ -47,7 +47,7 @@
"gulp-util": "^3.0.4",
"gulp-wrap": "^0.11.0",
"mocha": "^2.2.5",
"mocha-phantomjs": "^3.5.3",
"mocha-phantomjs": "^4.0.1",
"vinyl-buffer": "^1.0.0",
"vinyl-source-stream": "^1.1.0"
}
Expand Down
6 changes: 4 additions & 2 deletions src/coffee/app.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ Tyto.TemplateStore = require './templates/templates'
TytoCtrl = require './controllers/tyto'
TytoViews = require './views/tyto'
TytoModels = require './models/tyto'
Utils = require './utils/tyto'
TytoUtils = require './utils/utils'
TytoSuggestions = require './utils/suggestions'


# Create Modules
Tyto.module 'Models' , TytoModels
Tyto.module 'Ctrl' , TytoCtrl
Tyto.module 'Views' , TytoViews
Tyto.module 'Utils' , Utils
Tyto.module 'Utils' , TytoUtils
Tyto.module 'Suggestions' , TytoSuggestions


# Instantiate and cache collections.
Expand Down
166 changes: 166 additions & 0 deletions src/coffee/utils/suggestions.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
Suggestions = (Suggestions, App, Backbone, Marionette) ->
Suggestions.proto = [
'filterItems'
'selectSuggestion'
'renderSuggestions'
'hideSuggestions'
]
Suggestions.props =
ACTIVE_CLASS : 'is--active'
SUGGESTIONS_ITEM: '.tyto-suggestions__item'

Suggestions.bootstrapView = (view) ->
###
Bootstraps the given view with module functions.
This is purely for a quick DRY fix. There is most definitely
a better way to do this I am sure.
###
for idx, func of Suggestions.proto
view[func] = Suggestions[func]

Suggestions.renderSuggestions = (filterString) ->
filterByTerm = (entity) ->
return entity.attributes.title.toLowerCase().indexOf(filterString.toLowerCase()) isnt -1
view = this
edit = view.ui.editDescription
props = view.domAttributes
suggestions = view.ui.suggestions
collection = Tyto.Boards.models.concat Tyto.Tasks.models
collection = if filterString then collection.filter(filterByTerm) else collection
markup = Tyto.TemplateStore.filterList
models: collection.slice(0, 4)
$body = $ 'body'
$column = $ '.tyto-column__tasks'
end = edit[0].selectionEnd
start = view.__EDIT_START + 1
val = edit[0].value

handleBlurring = (e) ->
el = e.target
if el.nodeName isnt 'LI' and el.nodeName isnt 'TEXTAREA'
view.hideSuggestions()
view.delegateEvents()
edit.blur()
$body.off 'click', handleBlurring
else if el.nodeName is 'TEXTAREA'
if end < start or val.substring(start, end).indexOf(' ') isnt -1
view.hideSuggestions()

scrollOff = (e) ->
view.delegateEvents()
edit.focus()
$body.off 'click' , handleBlurring
$column.off 'scroll', scrollOff
edit.off 'scroll', scrollOff
view.hideSuggestions()

view.$el.off 'blur' , '.' + edit[0].className
$body.on 'click' , handleBlurring
$column.on 'scroll', scrollOff
edit.on 'scroll', scrollOff

if !view.__EDIT_MODE
view.__EDIT_MODE = true
view.__EDIT_START = edit[0].selectionStart
coords = Tyto.Utils.getCaretPosition edit[0]
suggestions.html(markup)
.css({
left: coords.LEFT,
top : coords.TOP
})
.removeClass props.HIDDEN_UTIL_CLASS
else
suggestions.html markup

Suggestions.hideSuggestions = ->
view = this
props = view.domAttributes
view.__EDIT_MODE = false
view.__ACTIVE_SUGGESTION = null
view.__EDIT_MODE_IN_SELECTION = false
suggestions = view.ui.suggestions
suggestions.addClass props.HIDDEN_UTIL_CLASS

Suggestions.filterItems = (e) ->
view = this
suggestions = view.ui.suggestions
props = view.domAttributes
edit = view.ui.editDescription
key = e.which
start = edit[0].selectionStart
end = edit[0].selectionEnd
val = edit[0].value
# ONLY TRIGGERING IF 35 or in VIEW.__EDIT_MODE
if key is 35 and !view.__EDIT_MODE
before = val.charAt(start - 1).trim()
after = val.charAt(start).trim()
if before is '' and after is ''
view.renderSuggestions()
else if view.__EDIT_MODE
switch key
# HASH, SPACE
when 35, 32
view.hideSuggestions()
# ENTER
when 13
if view.__EDIT_MODE_IN_SELECTION and view.__ACTIVE_SUGGESTION isnt null
e.preventDefault()
view.__ACTIVE_SUGGESTION.click()
else
view.hideSuggestions()
# BACKSPACE
when 8
if end is view.__EDIT_START
view.hideSuggestions()
else
view.renderSuggestions val.substring(view.__EDIT_START + 1, end)
# UP/DOWN
when 38, 40
if e.type is 'keydown'
e.preventDefault()
dir = if key is 38 then 'prev' else 'next'
reset = if key is 38 then 'last' else 'first'
if view.__EDIT_MODE_IN_SELECTION
if view.__ACTIVE_SUGGESTION[dir]().length is 0
view.__ACTIVE_SUGGESTION.removeClass Suggestions.props.ACTIVE_CLASS
view.__ACTIVE_SUGGESTION = suggestions.find(Suggestions.props.SUGGESTIONS_ITEM)[reset]().addClass Suggestions.props.ACTIVE_CLASS
else
view.__ACTIVE_SUGGESTION = view.__ACTIVE_SUGGESTION.removeClass(Suggestions.props.ACTIVE_CLASS)[dir]()
.addClass(Suggestions.props.ACTIVE_CLASS)
else
view.__EDIT_MODE_IN_SELECTION = true
view.__ACTIVE_SUGGESTION = suggestions.find(Suggestions.props.SUGGESTIONS_ITEM)[reset]().addClass Suggestions.props.ACTIVE_CLASS
# LEFT/RIGHT
when 37, 39
# Need to check for left/right arrow press and being within the work so to speak.
if e.type is 'keyup'
if end < (view.__EDIT_START + 1) or val.substring(view.__EDIT_START, end).length isnt val.substring(view.__EDIT_START, end).trim().length
view.hideSuggestions()
else
# Render filtered suggestions using filterString
if e.type is 'keyup'
view.renderSuggestions val.substring(view.__EDIT_START + 1, end)

Suggestions.selectSuggestion = (e) ->
view = this
edit = view.ui.editDescription
entityType = e.target.getAttribute 'data-type'
entityId = e.target.getAttribute 'data-model-id'
if entityType
entity = Tyto[entityType].get entityId
if entity.attributes.boardId
boardId = Tyto.Tasks.get(entityId).attributes.boardId
url = '#board/' + boardId + '/task/' + entityId
else
url = '#board/' + entityId
url = '[' + entity.attributes.title + '](' + url + ')'
start = edit[0].value.slice 0, view.__EDIT_START
end = edit[0].value.slice edit[0].selectionEnd, edit[0].value.length
edit[0].value = start + ' ' + url + ' ' + end

$('body').off 'click'
view.ui.editDescription.focus()
view.hideSuggestions()
view.delegateEvents()

module.exports = Suggestions
32 changes: 32 additions & 0 deletions src/coffee/utils/tyto.coffee → src/coffee/utils/utils.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,38 @@ Utils = (Utils, App, Backbone, Marionette) ->
if model
model.save
ordinal: idx + 1
Utils.autoSize = (el) ->
sizeUp = ->
el.style.height = 'auto'
el.style.height = el.scrollHeight + 'px'
el.addEventListener 'keydown', sizeUp
el.addEventListener 'input' , sizeUp
el.addEventListener 'focus' , sizeUp
sizeUp()

Utils.getCaretPosition = (el) ->
carPos = el.selectionEnd
div = document.createElement 'div'
span = document.createElement 'span'
copyStyle = getComputedStyle el
coords = {}
bounds = el.getBoundingClientRect()
[].forEach.call copyStyle, (prop) ->
div.style[prop] = copyStyle[prop]
div.style.position = 'absolute';
div.textContent = el.value.substr(0, carPos);
span.textContent = el.value.substr(carPos) || '.';
div.appendChild(span);
document.body.appendChild(div);
fontSize = parseFloat(copyStyle.fontSize.replace('px', ''), 10)
top = el.offsetTop - el.scrollTop + span.offsetTop + fontSize
top = if (top) > el.offsetHeight then el.offsetHeight else top
left = el.offsetLeft - el.scrollLeft + span.offsetLeft
coords =
TOP : top + bounds.top + 'px'
LEFT: left + bounds.left + 'px'
document.body.removeChild(div);
coords

Utils.processQueryString = (params) ->
qS = {}
Expand Down
3 changes: 2 additions & 1 deletion src/coffee/views/board.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,13 @@ module.exports = Backbone.Marionette.CompositeView.extend
view = this
board = view.model
columns = view.collection
view.$el.addClass view.domAttributes.ADDING_COLUMN_CLASS

columns.add Tyto.Columns.create
boardId: board.id
ordinal: columns.length + 1

view.$el.addClass view.domAttributes.ADDING_COLUMN_CLASS

saveBoardName: ->
this.model.save
title: this.ui.boardName.text().trim()
Expand Down
2 changes: 1 addition & 1 deletion src/coffee/views/column.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,11 @@ module.exports = Backbone.Marionette.CompositeView.extend
addTask: ->
view = this
attr = view.domAttributes
view.$el.addClass attr.TASK_ADD_CLASS
this.collection.add Tyto.Tasks.create
columnId: view.model.id
boardId : view.options.board.id
ordinal : view.collection.length + 1
view.$el.addClass attr.TASK_ADD_CLASS

deleteColumn: ->
if this.collection.length is 0 or confirm Tyto.CONFIRM_MESSAGE
Expand Down
52 changes: 41 additions & 11 deletions src/coffee/views/edit.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@ EditView = Backbone.Marionette.ItemView.extend
isNew : this.options.isNew
colors : Tyto.TASK_COLORS

initialize: ->
view = this
Tyto.RootView.el.classList.add 'bg--' + view.model.get('color')
Tyto.RootView.el.classList.remove view.domAttributes.BLOOM_SHOW_CLASS

domAttributes:
VIEW_CLASS : 'tyto-edit'
BLOOM_SHOW_CLASS : 'is--showing-bloom'
Expand All @@ -32,6 +27,8 @@ EditView = Backbone.Marionette.ItemView.extend
save : '.tyto-edit__save'
color : '.tyto-edit__color-select__menu-option'
taskDescription: '.tyto-edit__task-description'
editDescription: '.tyto-edit__edit-description'
suggestions : '.tyto-task__suggestions'
taskTitle : '.tyto-edit__task-title'
column : '.tyto-edit__column-select__menu-option'
colorMenu : '.tyto-edit__color-select__menu'
Expand All @@ -43,13 +40,27 @@ EditView = Backbone.Marionette.ItemView.extend
minutes : '.tyto-edit__task-time__minutes'

events:
'click @ui.save' : 'saveTask'
'click @ui.color' : 'changeColor'
'click @ui.column' : 'changeColumn'
'click @ui.track' : 'trackTime'
'blur @ui.taskDescription': 'updateTask'
'blur @ui.taskTitle' : 'updateTask'
'click @ui.save' : 'saveTask'
'click @ui.color' : 'changeColor'
'click @ui.column' : 'changeColumn'
'click @ui.track' : 'trackTime'
'click @ui.taskDescription': 'showEditMode'
'blur @ui.editDescription' : 'updateTask'
'blur @ui.taskTitle' : 'updateTask'
###
NOTE:: These are functions that are bootstrapped in from
the 'Suggestions' module.
###
'keypress @ui.editDescription': 'filterItems'
'keydown @ui.editDescription' : 'filterItems'
'keyup @ui.editDescription' : 'filterItems'
'click @ui.suggestions' : 'selectSuggestion'

initialize: ->
view = this
Tyto.Suggestions.bootstrapView view
Tyto.RootView.el.classList.add 'bg--' + view.model.get('color')
Tyto.RootView.el.classList.remove view.domAttributes.BLOOM_SHOW_CLASS

getMDLMap: ->
view = this
Expand All @@ -67,17 +78,36 @@ EditView = Backbone.Marionette.ItemView.extend
el = e.target
val = if el.nodeName is 'TEXTAREA' then el.value else el.innerHTML
view.model.set el.getAttribute(attr.MODEL_PROP_ATTR), val
if el.nodeName is 'TEXTAREA'
desc = view.ui.taskDescription
edit = view.ui.editDescription
desc.html marked(edit.val())
edit.addClass attr.HIDDEN_UTIL_CLASS
desc.removeClass attr.HIDDEN_UTIL_CLASS

onShow: ->
Tyto.Utils.upgradeMDL this.getMDLMap()

onRender: ->
view = this
view.ui.taskDescription.html marked(view.model.get('description'))
# Sets up auto resizing for text area up to a CSS defined max height.
Tyto.Utils.autoSize view.ui.editDescription[0]
Tyto.Utils.renderTime view

trackTime: ->
Tyto.Utils.showTimeModal this.model, this

showEditMode: ->
domAttributes = this.domAttributes
model = this.model
desc = this.ui.taskDescription
edit = this.ui.editDescription
desc.addClass domAttributes.HIDDEN_UTIL_CLASS
edit.removeClass(domAttributes.HIDDEN_UTIL_CLASS)
.val(model.get('description'))
.focus()

###
This is a function for handling fresh tasks and saving them on 'DONE'
###
Expand Down
Loading

0 comments on commit d9893ce

Please sign in to comment.