Skip to content

Commit

Permalink
Merge branch 'master' into gh-pages
Browse files Browse the repository at this point in the history
Conflicts:
	client/src/main.coffee
  • Loading branch information
tantaman committed Jul 3, 2012
2 parents 935694a + 9ad714c commit 536ba48
Show file tree
Hide file tree
Showing 28 changed files with 404 additions and 112 deletions.
2 changes: 0 additions & 2 deletions README.md
@@ -1,5 +1,3 @@
**Firefox support is currently busted... 6/19/12**

Strut
=======

Expand Down
31 changes: 31 additions & 0 deletions client/src/common/FileUtils.coffee
@@ -0,0 +1,31 @@
define(->
FileUtils =
baseName: (path, extension) ->
if (path[path.length - 1] is "/")
path = path.substring(0, path.length - 1)

idx = path.lastIndexOf("/")
if idx isnt -1 and idx + 1 < path.length
path = path.substring(idx+1, path.length)

if extension?
idx = path.lastIndexOf(extension)
if idx + extension.length is path.length
path = path.substring(0, idx)

path

# TODO: make a generic type that returns the mime type
imageType: (uri) ->
if (uri.indexOf("data:") is 0)
idx = uri.indexOf(";")
uri.substring(11, idx).toUpperCase()
else
idx = uri.lastIndexOf(".")
if idx isnt -1 and idx+1 < uri.length
extension = uri.substring(idx+1, uri.length)
idx = extension.lastIndexOf("?")
if idx isnt -1
extension = extension.substring(0, idx)
extension.toUpperCase()
)
16 changes: 13 additions & 3 deletions client/src/main.coffee
Expand Up @@ -38,8 +38,9 @@ if window.location.href.indexOf("preview=true") isnt -1
else
continuation = () ->
requirejs(["ui/editor/Editor",
"model/presentation/Deck"],
(Editor, Deck) ->
"model/presentation/Deck",
"storage/FileStorage"],
(Editor, Deck, FileStorage) ->
deck = new Deck()
editor = new Editor({model: deck})

Expand All @@ -49,8 +50,17 @@ else
++@z

$("body").append(editor.render())
deck.newSlide()

lastPres = localStorage.getItem("StrutLastPres")
if lastPres?
pres = FileStorage.open(lastPres)
if pres?
deck.import(pres)

if not lastPres?
deck.newSlide()
)

requirejs(["vendor/amd/backbone",
"state/DefaultState"],
(Backbone, DefaultState) ->
Expand Down
13 changes: 12 additions & 1 deletion client/src/model/common_application/AutoSaver.coffee
Expand Up @@ -6,6 +6,7 @@ define(["storage/FileStorage"],
(FileStorage) ->
defaults =
interval: 10
onUnload: true

###*
* Auto saves a given model on a specified interval.
Expand All @@ -22,6 +23,11 @@ define(["storage/FileStorage"],
@options or (@options = {})
_.defaults(@options, defaults)

if @options.onUnload
$(window).unload(() =>
@_save()
)

###*
* Starts the auto save task if not already started
* @method start
Expand All @@ -44,12 +50,17 @@ define(["storage/FileStorage"],
_save: ->
fileName = @model.get("fileName")
if not fileName?
return
fileName = "presentation-1"
@model.set("fileName", fileName)
#if @lastAutoSave?
# FileStorage.remove(@lastAutoSave)
#date = new Date()
#fileName =
# "AUTOSAVE-#{date.getDate()}/#{date.getMonth()+1} #{date.getHours()}:#{date.getMinutes()}:#{date.getSeconds()}"
#@lastAutoSave = fileName
if fileName isnt @_lastName
@_lastName = fileName
localStorage.setItem("StrutLastPres", fileName)

FileStorage.save(fileName, @model.toJSON(false, true))
)
82 changes: 68 additions & 14 deletions client/src/model/presentation/Archiver.coffee
@@ -1,28 +1,48 @@
define(["vendor/amd/jszip"],
(JSZip) ->
define(["vendor/amd/jszip",
"./Deck",
# egh... Someone is in the wrong spot. Either impress renderer or archiver.
"ui/impress_renderer/ImpressRenderer",
"common/FileUtils"],
(JSZip, Deck, ImpressRenderer, FileUtils) ->
defaults =
includeImages: false
includeImages: true
includeFonts: true

Archiver =
createArchive: (presentation, options) ->
options or (options = {})
_.defaults(options, defaults)
class Archiver
constructor: (@presentation, @options) ->
@options or (@options = {})
@canvas = $("<canvas></canvas>")[0]
@_archivedImages = {}
@_imageIdx = 0
_.defaults(@options, defaults)

create: () ->
@archive = new JSZip()
@previewExportDir = @archive.folder("preview_export")

@imagesDir = @previewExportDir.folder("images")
@scriptsDir = @previewExportDir.folder("scripts")
@fontsDir = @previewExportDir.folder("fonts")
@cssDir = @previewExportDir.folder("css")

archive = new JSZip()
presentationCopy = new Deck()

# hmm.. we should update the impress renderer
# to just function on the raw object
# so we don't have to re-import
presentationCopy.import(presentation.toJSON(false, true))
presentationCopy.import(@presentation.toJSON(false, true))

presentationCopy.get("slides").each((slide) =>
@processComponents(slide.get("components"), archive, options)
@processComponents(slide.get("components"))
)

showStr = "<!doctype html><html>" \
+ ImpressRenderer.render(@model.attributes) + "</html>"
+ ImpressRenderer.render(presentationCopy.attributes) + "</html>"

@_archiveIndexHtml(showStr)
@_archiveScripts()
@_archiveFonts()
@_archiveCss()

# Clone presentation
# via toJSON, new Deck(), deck.import(json)
Expand All @@ -37,13 +57,47 @@ define(["vendor/amd/jszip"],
# put js in zip
# put fonts in zip
# return "download ready" link
@_archivedImages = {}
@archive.generate();

processComponents: (components, archive, options) ->
processComponents: (components) ->
components.forEach((component) =>
@processComponent(component, archive, options)
@processComponent(component)
)

processComponent: (component, archive, options) ->
processComponent: (component) ->
if component.get("type") is "ImageModel"
if @options.includeImages
@_archiveImage(component)

_archiveIndexHtml: (str) ->
@archive.file("index.html", str);

# use the !text plugin to load these?
_archiveScripts: () ->

# how could we archive fonts though...?
_archiveFonts: () ->

_archiveCss: () ->

_archiveImage: (component) ->
# TODO: check the origin on the image
# if cross origin then just link it?
if not @_archivedImages[component.get("src")]
@_archivedImages[component.get("src")] = true

img = component.cachedImage
@canvas.width = img.naturalWidth
@canvas.height = img.naturalHeight

@canvas.getContext("2d").drawImage(img, 0, 0)

fileName = @_imageIdx + FileUtils.baseName(component.get("src"))
@imagesDir.file(fileName,
@canvas.toDataURL().replace(/^data:image\/(png|jpg);base64,/, ""),
base64: true)
component.set("src", "preview_export/images/" + fileName)


###
Expand Down
13 changes: 3 additions & 10 deletions client/src/model/presentation/components/Image.coffee
@@ -1,8 +1,8 @@
###
@author Tantaman
###
define(["./Component"],
(Component) ->
define(["./Component", "common/FileUtils"],
(Component, FileUtils) ->
Component.extend(
initialize: () ->
Component.prototype.initialize.apply(this, arguments)
Expand All @@ -11,14 +11,7 @@ define(["./Component"],
# We could do an HTTP request and get the content type
# that'd be more foolproof.
src = @get("src")
idx = src.lastIndexOf(".")
if idx isnt -1 and idx+1 < src.length
extension = src.substring(idx+1, src.length)
idx = extension.lastIndexOf("?")
if idx isnt -1
extension = extension.substring(0, idx)

@set("imageType", extension.toUpperCase())
@set("imageType", FileUtils.imageType(src))
@on("change:src", @_updateCache, @)
@cachedImage = new Image()
@_updateCache()
Expand Down
9 changes: 8 additions & 1 deletion client/src/storage/FileStorage.coffee
Expand Up @@ -24,7 +24,14 @@ define([],
@storageImpl.setItem(prefix + fileName, JSON.stringify(contents))

open: (fileName) ->
JSON.parse(@storageImpl.getItem(prefix + fileName))
item = @storageImpl.getItem(prefix + fileName)
if item?
try
JSON.parse(item)
catch e
return null
else
null

# FileStorage should not be a singleton...
new FileStorage()
Expand Down
29 changes: 25 additions & 4 deletions client/src/ui/editor/Editor.coffee
Expand Up @@ -11,20 +11,35 @@ define(["vendor/amd/backbone",
"ui/widgets/SaveAsDialog",
"storage/FileStorage",
"ui/widgets/BackgroundPicker",
"model/common_application/AutoSaver"
"model/common_application/AutoSaver",
"model/presentation/Archiver",
"css!./res/css/Editor.css"],
(Backbone, SlideEditor, TransitionEditor, Templates, ImpressRenderer, RawTextModal, OpenDialog, SaveAsDialog, \
FileStorage, BackgroundPicker, AutoSaver, empty) ->
FileStorage, BackgroundPicker, AutoSaver, Archiver, empty) ->
editorId = 0

menuOptions =
new: (e) ->
num = localStorage.getItem("StrutNewNum")
if not num?
num = 2
else
num = parseInt(num)

localStorage.setItem("StrutNewNum", num+1)

@model.import(
fileName: "presentation-" + num
slides: []
)
@model.newSlide()
open: (e) ->
@openDialog.show((fileName) =>
console.log "Attempting to open #{fileName}"
data = FileStorage.open(fileName)
if data?
@model.import(data)
localStorage.setItem("StrutLastPres", fileName)
)
openRecent: (e) ->
save: (e) ->
Expand Down Expand Up @@ -81,6 +96,11 @@ FileStorage, BackgroundPicker, AutoSaver, empty) ->
@model.set("background", bgState)
)

exportZIP: (e) ->
archiver = new Archiver(@model)
archive = archiver.create()
window.location.href="data:application/zip;base64,"+archive;

Backbone.View.extend(
className: "editor"
events:
Expand Down Expand Up @@ -151,8 +171,9 @@ FileStorage, BackgroundPicker, AutoSaver, empty) ->

_backgroundChanged: (model, value) ->
# tell our perspectives about the bg update...
for key,persp of @perspectives
persp.backgroundChanged(value)
if value?
for key,persp of @perspectives
persp.backgroundChanged(value)

menuItemSelected: (e) ->
$target = $(e.currentTarget)
Expand Down
4 changes: 3 additions & 1 deletion client/src/ui/editor/SlideSnapshot.coffee
Expand Up @@ -57,7 +57,9 @@ define(["vendor/amd/backbone",
@$el.html(Templates.SlideSnapshot(@model.attributes))
g2d = @$el.find("canvas")[0].getContext("2d")
@slideDrawer = new SlideDrawer(@model, g2d)
@slideDrawer.repaint()
setTimeout(=>
@slideDrawer.repaint()
, 0)

if @model.get("active")
@$el.addClass("active")
Expand Down
8 changes: 4 additions & 4 deletions client/src/ui/editor/raster/ImageModelDrawer.coffee
Expand Up @@ -8,10 +8,10 @@ define(["./AbstractDrawer"],

_imageLoaded: (image, imageModel) ->
bbox =
x: imageModel.get("x") * @scale
y: imageModel.get("y") * @scale
width: image.naturalWidth * @scale
height: image.naturalHeight * @scale
x: imageModel.get("x") * @scale.x
y: imageModel.get("y") * @scale.y
width: image.naturalWidth * @scale.x
height: image.naturalHeight * @scale.y

@applyTransforms(imageModel, bbox)

Expand Down
4 changes: 3 additions & 1 deletion client/src/ui/editor/raster/SlideDrawer.coffee
Expand Up @@ -12,7 +12,9 @@ define(["common/Throttler",
width: @g2d.canvas.width
height: @g2d.canvas.height
@throttler = new Throttler(600, @)
@scale = @size.width / slideConfig.size.width
@scale =
x: @size.width / slideConfig.size.width
y: @size.height / slideConfig.size.height

@drawers =
TextBox: new TextBoxDrawer(@g2d)
Expand Down

0 comments on commit 536ba48

Please sign in to comment.