diff options
Diffstat (limited to 'public/assets/javascripts/ui/lib')
| -rw-r--r-- | public/assets/javascripts/ui/lib/AlertModal.js | 38 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/lib/AnimatedView.js | 31 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/lib/ConfirmModal.js | 46 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/lib/ErrorModal.js | 38 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/lib/FormView.js | 227 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/lib/LabColorPicker.js | 180 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/lib/ModalView.js | 79 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/lib/Parser.js | 118 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/lib/Router.js | 1 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/lib/ToggleableView.js | 19 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/lib/Toolbar.js | 22 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/lib/UploadView.js | 152 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/lib/View.js | 231 |
13 files changed, 787 insertions, 395 deletions
diff --git a/public/assets/javascripts/ui/lib/AlertModal.js b/public/assets/javascripts/ui/lib/AlertModal.js index 1b0f40f..a4bf241 100644 --- a/public/assets/javascripts/ui/lib/AlertModal.js +++ b/public/assets/javascripts/ui/lib/AlertModal.js @@ -1,25 +1,25 @@ var AlertModal = new( ModalFormView.extend({ - el: ".mediaDrawer.alert", + el: ".mediaDrawer.alert", - events: { - "click .ok": "advance", - "click .close": "advance", - }, - - alert: function(message, callback){ - this.$(".message").empty().append(message) - this.callback = callback - this.show() - this.$(".ok").focus() - }, - - advance: function(e){ - e && e.preventDefault() - this.hide() - this.callback && this.callback() - this.callback = null - } + events: { + "click .ok": "advance", + "click .close": "advance", + }, + + alert: function(message, callback){ + this.$(".message").empty().append(message) + this.callback = callback + this.show() + this.$(".ok").focus() + }, + + advance: function(e){ + e && e.preventDefault() + this.hide() + this.callback && this.callback() + this.callback = null + } })) diff --git a/public/assets/javascripts/ui/lib/AnimatedView.js b/public/assets/javascripts/ui/lib/AnimatedView.js new file mode 100644 index 0000000..3c50b0a --- /dev/null +++ b/public/assets/javascripts/ui/lib/AnimatedView.js @@ -0,0 +1,31 @@ +var AnimatedView = View.extend({ + + _animating: false, + last_t: 0, + + startAnimating: function(){ + if (this._animating) return + this._animating = true + this._animate() + }, + + stopAnimating: function(){ + this._animating = false + }, + + _animate: function(t){ + if (! this._animating) return + + requestAnimationFrame(this._animate.bind(this)) + + var dt = t - this.last_t + this.last_t = t + + if (! t) return + + this.animate(t, dt) + }, + + animate: function(t, dt){}, + +})
\ No newline at end of file diff --git a/public/assets/javascripts/ui/lib/ConfirmModal.js b/public/assets/javascripts/ui/lib/ConfirmModal.js index 01720bb..7d9da67 100644 --- a/public/assets/javascripts/ui/lib/ConfirmModal.js +++ b/public/assets/javascripts/ui/lib/ConfirmModal.js @@ -1,24 +1,34 @@ var ConfirmModal = new( ModalFormView.extend({ - el: ".mediaDrawer.confirm", + el: ".mediaDrawer.confirm", - events: { - "click .yes": "advance", - "click .no": "hide", - }, - - confirm: function(question, callback){ - this.$(".question").empty().append(question) - this.callback = callback - this.show() - }, - - advance: function(e){ - e && e.preventDefault() - this.hide() - this.callback && this.callback() - this.callback = null - } + events: { + "click .yes": "agree", + "click .no": "cancel", + }, + + confirm: function(question, agreeCallback, cancelCallback){ + this.$(".question").empty().append(question) + this.agreeCallback = agreeCallback + this.cancelCallback = cancelCallback + this.show() + }, + + agree: function(e){ + e && e.preventDefault() + this.hide() + this.agreeCallback && this.agreeCallback() + this.agreeCallback = null + this.cancelCallback = null + }, + + cancel: function(e){ + e && e.preventDefault() + this.hide() + this.cancelCallback && this.cancelCallback() + this.agreeCallback = null + this.cancelCallback = null + } }) )
\ No newline at end of file diff --git a/public/assets/javascripts/ui/lib/ErrorModal.js b/public/assets/javascripts/ui/lib/ErrorModal.js index 8b01077..cfc2e6d 100644 --- a/public/assets/javascripts/ui/lib/ErrorModal.js +++ b/public/assets/javascripts/ui/lib/ErrorModal.js @@ -1,26 +1,26 @@ var ErrorModal = new( ModalFormView.extend({ - el: ".mediaDrawer.error", + el: ".mediaDrawer.error", - events: { - "click .ok": "advance", - "click .close": "advance", - }, - - alert: function(message, callback){ - this.$(".errorList").empty().append(message) - this.callback = callback - this.show() - this.$(".ok").focus() - }, - - advance: function(e){ - e && e.preventDefault() - this.hide() - this.callback && this.callback() - this.callback = null - } + events: { + "click .ok": "advance", + "click .close": "advance", + }, + + alert: function(message, callback){ + this.$(".errorList").empty().append(message) + this.callback = callback + this.show() + this.$(".ok").focus() + }, + + advance: function(e){ + e && e.preventDefault() + this.hide() + this.callback && this.callback() + this.callback = null + } })) diff --git a/public/assets/javascripts/ui/lib/FormView.js b/public/assets/javascripts/ui/lib/FormView.js index 17b748a..a952ecb 100644 --- a/public/assets/javascripts/ui/lib/FormView.js +++ b/public/assets/javascripts/ui/lib/FormView.js @@ -1,127 +1,138 @@ var FormView = View.extend({ - method: "post", + method: "post", + useMinotaur: false, - events: { - "submit form": "save" - }, + events: { + "submit form": "save" + }, - initialize: function(opt){ - if (opt && opt.parent) { - this.parent = opt.parent - } - this.$form = this.$("form") - this.$errors = this.$(".errors") - this.$errorList = this.$(".errorList") - }, + initialize: function(opt){ + if (opt && opt.parent) { + this.parent = opt.parent + } + this.$form = this.$("form") + this.$errors = this.$(".errors") + this.$errorList = this.$(".errorList") + }, - reset: function(){ - this.$("input,textarea").not("[type='submit']").not("[type='hidden']").val("") - }, - - showErrors: function(errors){ - if (errors && errors.length) { - this.$errorList.empty(); - for (var i in errors) { - this.$errorList.append('<div>' + errors[i] + '</div>'); - } - this.$errors.css("opacity", 1.0); - setTimeout(function(){ - this.$errors.show().css("opacity", 1.0); - }.bind(this), 200) - } - }, - - serialize: function(){ - var fd = new FormData(), hasCSRF = false - - this.$("input[name], select[name], textarea[name]").each( function(){ - if (this.type == "file") { - if (this.files.length > 0) { - fd.append(this.name, this.files[0]); - } - } - else if (this.type == "password") { - if (this.value.length > 0) { - fd.append(this.name, SHA1.hex('lol$' + this.value + '$vvalls')) - } - } - else { - fd.append(this.name, this.value); - hasCSRF = hasCSRF || this.name == "_csrf" - } - }); - - if (! hasCSRF) { + reset: function(){ + this.$("input,textarea").not("[type='submit']").not("[type='hidden']").val("") + }, + + showErrors: function(errors){ + if (errors && errors.length) { + this.$errorList.empty(); + for (var i in errors) { + this.$errorList.append('<div>' + errors[i] + '</div>'); + } + this.$errors.css("opacity", 1.0); + setTimeout(function(){ + this.$errors.show().css("opacity", 1.0); + }.bind(this), 200) + } + }, + + serialize: function(){ + var fd = new FormData(), hasCSRF = false + + this.$("input[name], select[name], textarea[name]").each( function(){ + if (this.type == "file") { + if (this.files.length > 0) { + fd.append(this.name, this.files[0]); + } + } + else if (this.type == "password") { + if (this.value.length > 0) { + fd.append(this.name, SHA1.hex('lol$' + this.value + '$vvalls')) + } + } + else { + fd.append(this.name, this.value); + hasCSRF = hasCSRF || this.name == "_csrf" + } + }); + + if (! hasCSRF) { fd.append("_csrf", $("[name=_csrf]").val()) } - - return fd - }, - - save: function(e, successCallback, errorCallback){ - e && e.preventDefault() + + return fd + }, + + save: function(e, successCallback, errorCallback){ + e && e.preventDefault() - this.$errors.hide().css("opacity", 0.0); - - if (this.validate) { - var errors = this.validate() - if (errors && errors.length) { - if (errorCallback) { - errorCallback(errors) - } - else { + this.$errors && this.$errors.hide().css("opacity", 0.0); + + if (this.validate) { + var errors = this.validate() + if (errors && errors.length) { + if (errorCallback) { + setTimeout(function(){ + errorCallback(errors) + }) + } + else { this.showErrors(errors) - } - return - } - } - - var action = typeof this.action == "function" ? this.action() : this.action - if (! action) return + } + return + } + } + var action = typeof this.action == "function" ? this.action() : this.action + if (! action) return - var request = $.ajax({ - url: action, - type: this.method, - data: this.serialize(), - dataType: "json", - processData: false, - contentType: false, - }) - - request.done($.proxy(function (response) { - if (response.error) { - var errors = [] - for (var key in response.error.errors) { - errors.push(response.error.errors[key].message); - } - if (errorCallback) { - errorCallback(errors) - } - else { + var request = $.ajax({ + url: action, + type: this.method, + data: this.serialize(), + dataType: "json", + processData: false, + contentType: false, + }) + + if (this.useMinotaur) { + Minotaur.show() + } + + request.done($.proxy(function (response) { + if (this.useMinotaur) { + Minotaur.hide() + } + if (response.error) { + var errors = [] + for (var key in response.error.errors) { + errors.push(response.error.errors[key].message); + } + if (errorCallback) { + errorCallback(errors) + } + else { this.showErrors(errors) - } - return - } - else { - if (successCallback) { - successCallback(response) - } - if (this.success) { - this.success(response) - } - } - }, this)); - } + } + return + } + else { + console.log("ok") + if (successCallback) { + console.log("use cb") + successCallback(response) + } + if (this.success) { + this.success(response) + } + } + }, this)); + } }) var ModalFormView = ModalView.extend(FormView.prototype).extend({ - load: function(){ - this.reset() - this.show() - } + load: function(){ + this.reset() + this.show() + } }) diff --git a/public/assets/javascripts/ui/lib/LabColorPicker.js b/public/assets/javascripts/ui/lib/LabColorPicker.js new file mode 100644 index 0000000..2c8fb90 --- /dev/null +++ b/public/assets/javascripts/ui/lib/LabColorPicker.js @@ -0,0 +1,180 @@ +var LabColorPicker = function (parent, w, h) { + var base = this + var canvas = this.canvas = document.createElement('canvas') + canvas.width = w + canvas.height = h + var ctx = this.ctx = canvas.getContext('2d-lodpi') +// canvas.className = "colorPicker" +// var imageData = ctx.createImageData(w, h) +// var data = imageData.data + + var cursor = this.cursor = document.createElement("div") + cursor.className = "colorPickerCursor" + + var brightnessControl = this.brightness = document.createElement("input") + var $brightnessControl = $(brightnessControl) + brightnessControl.setAttribute("type", "range") + brightnessControl.setAttribute("min", "0") + brightnessControl.setAttribute("max", "110") + brightnessControl.setAttribute("value", "0") + + var ww = w-1 + var hh = h-1 + + var L_range = [0, 110] + var a_range = [-86.185, 98.254] + var b_range = [-107.863, 94.482] + + var rgb = [0,0,0] + + var val = 80 + + this.mouse = new mouse({ + el: canvas, + down: function(e, cursor){ + parent.begin() + cursor.x.a = -cursor.x.a + base.pick(cursor.x.a, cursor.y.a) + }, + drag: function(e, cursor){ + cursor.x.b = -cursor.x.b + base.pick(cursor.x.b, cursor.y.b) + }, + up: function(){ + parent.finalize() + } + }) + + $brightnessControl.on({ + "mousedown": function(){ base.beginBrightness() }, + "input": function(){ base.updateBrightness() }, + }) + + this.setLab = function(Lab) { + val = Lab[0] + this.paint() + var rgb = xyz2rgb(hunterlab2xyz(Lab[0], Lab[1], Lab[2])).map(Math.round) + return rgb + } + this.pick = function(i, j){ + i = clamp(i, 0, w) + j = clamp(j, 0, h) + var x = mix( i/ww, a_range[0], a_range[1] ) + var y = mix( j/hh, b_range[0], b_range[1] ) + var rgb = xyz2rgb(hunterlab2xyz(val, x, y)).map(Math.round) + this.moveCursor(i, j) + parent.pickColor( rgb, [val,x,y] ) + } + this.load = function(rgba){ + var Lab = xyz2hunterlab(rgb2xyz(rgba)) + var val = clamp( Lab[0], L_range[0], L_range[1] ) + var x = mix( norm(Lab[1], a_range[0], a_range[1]), 0, ww ) + var y = mix( norm(Lab[2], b_range[0], b_range[1]), 0, hh ) + + this.moveCursor(x,y) + this.setLab(Lab) + this.setBrightness(Lab) + + return Lab + } + this.moveCursor = function(x,y){ + cursor.style.left = x + "px" + cursor.style.top = y + "px" + } + this.paint = function() { + val = clamp(val, L_range[0], L_range[1]) + var imageData = ctx.createImageData(canvas.width, canvas.height) + var data = imageData.data + var x, y, t, cw = imageData.width, ch = imageData.height + var cww = cw-1, chh = ch-1 + for (var i = 0; i < cw; i++) { + for (var j = 0; j < ch; j++) { + x = mix( i/cww, a_range[0], a_range[1] ) + y = mix( j/chh, b_range[0], b_range[1] ) + t = (j*w + i) * 4 + rgb = xyz2rgb(hunterlab2xyz(val, x, y)) + data[t] = Math.round( rgb[0] ) + data[t+1] = Math.round( rgb[1] ) + data[t+2] = Math.round( rgb[2] ) + data[t+3] = 255 + } + } + ctx.putImageData(imageData,0,0) + } + + this.beginBrightness = function(){ + parent.begin() + $(window).one("mouseup", parent.finalize.bind(parent)) + } + this.updateBrightness = function(){ + parent.labColor[0] = parseFloat( $brightnessControl.val() ) + var rgb = base.setLab( parent.labColor ) + parent.pickColor(rgb, parent.labColor) + } + this.setBrightness = function(Lab){ + $brightnessControl.val(Lab[0]) + } + + function hunterlab2xyz (L,a,b) { + var_Y = L / 10 + var_X = a / 17.5 * L / 10 + var_Z = b / 7 * L / 10 + + Y = Math.pow(var_Y, 2) + X = ( var_X + Y ) / 1.02 + Z = -( var_Z - Y ) / 0.847 + xyz = [X,Y,Z] + } + function xyz2rgb(){ + var var_X = xyz[0] / 100 //X from 0 to 95.047 (Observer = 2°, Illuminant = D65) + var var_Y = xyz[1] / 100 //Y from 0 to 100.000 + var var_Z = xyz[2] / 100 //Z from 0 to 108.883 + + var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986 + var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415 + var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570 + + if ( var_R > 0.0031308 ) var_R = 1.055 * Math.pow( var_R, 1 / 2.4 ) - 0.055 + else var_R = 12.92 * var_R + if ( var_G > 0.0031308 ) var_G = 1.055 * Math.pow( var_G, 1 / 2.4 ) - 0.055 + else var_G = 12.92 * var_G + if ( var_B > 0.0031308 ) var_B = 1.055 * Math.pow( var_B, 1 / 2.4 ) - 0.055 + else var_B = 12.92 * var_B + + rgb[0] = clamp(var_R * 255, 0, 255) + rgb[1] = clamp(var_G * 255, 0, 255) + rgb[2] = clamp(var_B * 255, 0, 255) + return rgb + } + function rgb2xyz(RGB){ + var var_R = ( RGB[0] / 255 ) // R from 0 to 255 + var var_G = ( RGB[1] / 255 ) // G from 0 to 255 + var var_B = ( RGB[2] / 255 ) // B from 0 to 255 + + if ( var_R > 0.04045 ) var_R = Math.pow( ( var_R + 0.055 ) / 1.055, 2.4) + else var_R = var_R / 12.92 + if ( var_G > 0.04045 ) var_G = Math.pow( ( var_G + 0.055 ) / 1.055, 2.4) + else var_G = var_G / 12.92 + if ( var_B > 0.04045 ) var_B = Math.pow( ( var_B + 0.055 ) / 1.055, 2.4) + else var_B = var_B / 12.92 + + var_R = var_R * 100 + var_G = var_G * 100 + var_B = var_B * 100 + + //Observer. = 2°, Illuminant = D65 + var x = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805 + var y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722 + var z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505 + return [x,y,z] + } + function xyz2hunterlab (XYZ) { + var X = XYZ[0] + var Y = XYZ[1] || 1e-6 // otherwise divide-by-zero error when converting rgb(0,0,0) + var Z = XYZ[2] + var L = 10 * sqrt( Y ) + var a = 17.5 * ( ( ( 1.02 * X ) - Y ) / sqrt( Y ) ) + var b = 7 * ( ( Y - ( 0.847 * Z ) ) / sqrt( Y ) ) + return [L,a,b] + } +} diff --git a/public/assets/javascripts/ui/lib/ModalView.js b/public/assets/javascripts/ui/lib/ModalView.js index d9b518a..e0070ce 100644 --- a/public/assets/javascripts/ui/lib/ModalView.js +++ b/public/assets/javascripts/ui/lib/ModalView.js @@ -1,42 +1,53 @@ var ModalView = View.extend({ - events: { - "click .close": 'close', - }, - - initialize: function(opt){ - if (opt && opt.parent) { - this.parent = opt.parent - } - }, - - usesFileUpload: false, - - show: function(){ - $(".mediaDrawer").removeClass("active") - - if (! this.usesFileUpload) { - $(".fileUpload").removeClass("active") - } - - this.$el.addClass("active") + events: { + "click .close": 'close', + }, + + initialize: function(opt){ + if (opt && opt.parent) { + this.parent = opt.parent + } + }, + + usesFileUpload: false, + + show: function(){ + $(".mediaDrawer").removeClass("active") + $(".fileUpload").removeClass("active") + + if (this.fixedClose) { + $("#fixed_close").addClass("active") + $("#fixed_close").bind("click", this.hide.bind(this)) + } + + this.$el.addClass("active") $("body").addClass("noOverflow") - }, + }, - hide: function(){ + hide: function(){ // $(".mediaDrawer, .room1").removeClass("active editing"); - this.$el.removeClass("active"); + if (this.fixedClose) { + $("#fixed_close").removeClass("active") + $("#fixed_close").unbind("click", this.hide.bind(this)) + } + this.$el.removeClass("active"); $("body").removeClass("noOverflow"); - }, - - close: function(){ - if (window.isModalView) { - window.location.pathname = "/" - } - else { - history.pushState(null, document.title, app.router.originalPath) - this.hide() - } - } + }, + + hideClose: function(){ + $("#fixed_close").removeClass("active") + $("#fixed_close").unbind("click", this.hide.bind(this)) + }, + + close: function(){ + if (window.isModalView) { + window.location.pathname = "/" + } + else { + history.pushState(null, document.title, app.router.originalPath) + this.hide() + } + } }) diff --git a/public/assets/javascripts/ui/lib/Parser.js b/public/assets/javascripts/ui/lib/Parser.js index 52c96e6..411f425 100644 --- a/public/assets/javascripts/ui/lib/Parser.js +++ b/public/assets/javascripts/ui/lib/Parser.js @@ -5,9 +5,12 @@ var Parser = { fetch: function(url, done) { var img = new Image () img.onload = function(){ + if (!img) return var width = img.naturalWidth, height = img.naturalHeight img = null done({ + url: url, + type: "image", token: "", thumbnail: "", title: "", @@ -32,6 +35,8 @@ var Parser = { var width = video.videoWidth, height = video.videoHeight video = null done({ + url: url, + type: "video", token: "", thumbnail: "", title: "", @@ -63,6 +68,8 @@ var Parser = { success: function(result){ var res = result.items[0] done({ + url: url, + type: "youtube", token: id, thumbnail: thumb, title: res.snippet.title, @@ -92,6 +99,8 @@ var Parser = { return } done({ + url: url, + type: "vimeo", token: id, thumbnail: res.thumbnail_large, title: res.title, @@ -103,10 +112,9 @@ var Parser = { }, tag: function (media) { // return '<img class="video" type="vimeo" vid="'+media.token+'" src="'+media.thumbnail+'"><span class="playvid">▶</span>'; - return '<div class="video" style="width: ' + media.width + 'px; height: ' + media.height + 'px; overflow: hidden; position: relative;"><iframe frameborder="0" scrolling="no" seamless="seamless" webkitallowfullscreen="webkitAllowFullScreen" mozallowfullscreen="mozallowfullscreen" allowfullscreen="allowfullscreen" id="okplayer" src="http://player.vimeo.com/video/' + media.token + '?api=1&js_api=1&title=0&byline=0&portrait=0&playbar=0&player_id=okplayer&loop=0&autoplay=0" width="' + media.width + '" height="' + media.height + '" style="position: absolute; top: 0px; left: 0px; width: ' + media.width + 'px; height: ' + media.height + 'px;"></iframe></div>' + return '<div class="video" style="width: ' + media.width + 'px; height: ' + media.height + 'px; overflow: hidden; position: relative;"><iframe frameborder="0" scrolling="no" seamless="seamless" webkitallowfullscreen="webkitAllowFullScreen" mozallowfullscreen="mozallowfullscreen" allowfullscreen="allowfullscreen" id="okplayer" src="http://player.vimeo.com/video/' + media.token + '?api=1&title=0&byline=0&portrait=0&playbar=0&player_id=okplayer&loop=0&autoplay=0" width="' + media.width + '" height="' + media.height + '" style="position: absolute; top: 0px; left: 0px; width: ' + media.width + 'px; height: ' + media.height + 'px;"></iframe></div>' } }, - /* { type: 'soundcloud', regex: /soundcloud.com\/[-a-zA-Z0-9]+\/[-a-zA-Z0-9]+\/?$/i, @@ -118,26 +126,33 @@ var Parser = { + '&client_id=' + '0673fbe6fc794a7750f680747e863b10', success: function(result) { + // console.log(result) done({ + url: url, + type: "soundcloud", token: result.id, - thumbnail: "", - title: "", - width: 100, - height: 100, + thumbnail: result.artwork_url || result.user.avatar_url, + title: result.user.username + " - " + result.title, + width: 166, + height: 166, }) } }); }, tag: function (media) { - return '<iframe width="400" height="166" scrolling="no" frameborder="no"' + + return '<iframe width="166" height="166" scrolling="no" frameborder="no"' + 'src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/' + media.token + '&color=ff6600&auto_play=false&show_artwork=true"></iframe>' } - }, { + }, + /* + { type: 'link', regex: /^http.+/i, fetch: function(url, done) { done({ + url: url, + type: "link", token: "", thumbnail: "", title: "", @@ -152,12 +167,86 @@ var Parser = { */ ], + tumblr: function(url, cb){ + var domain = url.replace(/^https?:\/\//,"").split("/")[0] + if (domain.indexOf(".") == -1) { + domain += ".tumblr.com" + } + $.ajax({ + type: 'GET', + url: "http://" + domain + "/api/read", + dataType: "jsonp", + data: { + format: "json", + }, + success: function(data){ + var media_list = [] + var blog = data.tumblelog + + data.posts.forEach(parse) + cb(media_list) + + function parse(post){ + var media, caption, url + switch (post.type) { + case 'photo': + caption = stripHTML(post['photo-caption']) + if (post.photos.length) { + post.photos.forEach(function(photo){ + var media = { + url: photo['photo-url-1280'], + type: "image", + token: "", + thumbnail: photo['photo-url-500'], + description: caption, + width: parseInt(photo.width), + height: parseInt(photo.height), + } + media_list.push(media) + }) + } + else { + media = { + url: post['photo-url-1280'], + type: "image", + token: "", + thumbnail: post['photo-url-500'], + description: caption, + width: parseInt(post.width), + height: parseInt(post.height), + } + media_list.push(media) + } + break + case 'video': + url = post['video-source'] + if (url.indexOf("http") !== 0) { break } + if (Parser.lookup.youtube.regex.test(url)) { + var id = (url.match(/v=([-_a-zA-Z0-9]{11})/i) || url.match(/youtu.be\/([-_a-zA-Z0-9]{11})/i) || url.match(/embed\/([-_a-zA-Z0-9]{11})/i))[1].split('&')[0]; + var thumb = "http://i.ytimg.com/vi/" + id + "/hqdefault.jpg" + media = { + url: post['video-source'], + type: "youtube", + token: id, + thumbnail: thumb, + title: stripHTML(post['video-caption']), + width: 640, + height: 360, + } + media_list.push(media) + } + break + } + } +// console.log(post) + } + }) + }, + parse: function (url, cb) { var matched = Parser.integrations.some(function(integration){ if (integration.regex.test(url)) { integration.fetch(url, function(res){ - res.url = url - res.type = integration.type cb(res) }) return true @@ -176,6 +265,15 @@ var Parser = { return "" }, + loadImage: function(url, cb, error){ + if (Parser.lookup.image.regex.test(url)) { + Parser.lookup.image.fetch(url, function(media){ + cb(media) + }) + } + else error && error() + }, + thumbnail: function (media) { return '<img src="' + (media.thumbnail || media.url) + '" class="thumb">'; }, diff --git a/public/assets/javascripts/ui/lib/Router.js b/public/assets/javascripts/ui/lib/Router.js index 0b6385c..28905b2 100644 --- a/public/assets/javascripts/ui/lib/Router.js +++ b/public/assets/javascripts/ui/lib/Router.js @@ -16,6 +16,7 @@ var Router = View.extend({ if (pathname in routes) { this[this.routes[pathname]](null) + return } if (path[path.length-1] == null) { diff --git a/public/assets/javascripts/ui/lib/ToggleableView.js b/public/assets/javascripts/ui/lib/ToggleableView.js new file mode 100644 index 0000000..371629f --- /dev/null +++ b/public/assets/javascripts/ui/lib/ToggleableView.js @@ -0,0 +1,19 @@ +var ToggleableView = View.extend({ + + toggle: function(state){ + this.$el.toggleClass("active", state) + }, + + show: function(){ + this.toggle(true) + }, + + hide: function(){ + this.toggle(false) + }, + + visible: function(){ + return this.$el.hasClass("active") + } + +})
\ No newline at end of file diff --git a/public/assets/javascripts/ui/lib/Toolbar.js b/public/assets/javascripts/ui/lib/Toolbar.js new file mode 100644 index 0000000..a9ce51c --- /dev/null +++ b/public/assets/javascripts/ui/lib/Toolbar.js @@ -0,0 +1,22 @@ +var Toolbar = Fiber.extend(function(base){ + var exports = {} + exports.init = function(rapper){ + this.rapper = (typeof rapper == "string") ? $(rapper)[0] : rapper + this.tools = {} + this.els = {} + } + exports.add = function(role, fn){ + var self = this + this.tools[role] = fn + this.els[role] = $("[data-role=" + role + "]", self.rapper) + this.els[role].click(function(){ + $(".active", self.rapper).removeClass('active') + $(this).addClass('active') + fn() + }) + } + exports.pick = function(role){ + this.els[role].trigger("click") + } + return exports +})
\ No newline at end of file diff --git a/public/assets/javascripts/ui/lib/UploadView.js b/public/assets/javascripts/ui/lib/UploadView.js index efaa8c9..d1e2b73 100644 --- a/public/assets/javascripts/ui/lib/UploadView.js +++ b/public/assets/javascripts/ui/lib/UploadView.js @@ -3,88 +3,94 @@ var UploadView = View.extend({ // define uploadAction - events: { - "change .file": "handleFileSelect", - "submit form": "preventDefault", - }, - - initialize: function(){ - this.$file = this.$(".file") - this.$upload = this.$(".upload-icon") + events: { + "change [type=file]": "handleFileSelect", + "submit form": "preventDefault", + }, + + initialize: function(){ + this.$file = this.$("[type=file]") + this.$upload = this.$(".upload-icon") }, beforeUpload: function(){ }, - + handleFileSelect: function(e) { - e.stopPropagation(); - e.preventDefault(); - - this.beforeUpload() + e.stopPropagation(); + e.preventDefault(); + + this.beforeUpload() - var files = e.dataTransfer ? e.dataTransfer.files : e.target.files; + var files = e.dataTransfer ? e.dataTransfer.files : e.target.files; - for (var i = 0, f; f = files[i]; i++) { - if ( ! f.type.match('image.*')) { - continue; - } - - this.getImageDimensions(f) - } - }, - - getImageDimensions: function(f){ - var base = this - - this.$upload.addClass('uploading') + for (var i = 0, f; f = files[i]; i++) { + if ( ! f.type.match('image.*')) { + continue; + } + + this.getImageDimensions(f) + } + }, + + getImageDimensions: function(f){ + var base = this + + this.$upload.addClass('uploading') - var reader = new FileReader(); + var reader = new FileReader(); - reader.onload = function(e) { - var image = new Image() - image.onload = function(){ - var width = image.naturalWidth, - height = image.naturalHeight - base.upload(f, width, height) - } - image.src = e.target.result - } - - reader.readAsDataURL(f); - }, - - upload: function(f, width, height){ - var fd = new FormData() - fd.append('image', f) - fd.append('width', width) - fd.append('height', height) - fd.append('_csrf', $("[name=_csrf]").val()) - - if (this.mediaTag) { - fd.append('tag', this.mediaTag) - } + reader.onload = function(e) { + var image = new Image() + image.onload = function(){ + var width = image.naturalWidth, + height = image.naturalHeight + base.upload(f, width, height) + } + image.src = e.target.result + } + + reader.readAsDataURL(f); + }, + + upload: function(f, width, height){ + var fd = new FormData() + fd.append('image', f) + fd.append('width', width) + fd.append('height', height) + fd.append('_csrf', $("[name=_csrf]").val()) + + if (this.mediaTag) { + fd.append('tag', this.mediaTag) + } - var request = $.ajax({ - url: this.uploadAction, - type: "post", - data: fd, - dataType: "json", - processData: false, - contentType: false, - }) - request.done(this.success.bind(this)) - }, - - success: function(media){ - if (media.error) { - return - } - this.$upload.removeClass('uploading') - this.add(media) - }, - - add: function(media){ - console.log(media) - }, + var request = $.ajax({ + url: this.uploadAction, + type: "post", + data: fd, + dataType: "json", + processData: false, + contentType: false, + }) + request.done(this.success.bind(this)) + }, + + success: function(media){ + if (media.error) { + // console.log(media.error) + this.$upload.removeClass('uploading') + this.error(media.error) + return + } + this.$upload.removeClass('uploading') + this.add(media) + }, + + add: function(media){ + console.log(media) + }, + + error: function(error){ + }, }) diff --git a/public/assets/javascripts/ui/lib/View.js b/public/assets/javascripts/ui/lib/View.js index d94e6db..9a8ab5b 100644 --- a/public/assets/javascripts/ui/lib/View.js +++ b/public/assets/javascripts/ui/lib/View.js @@ -1,139 +1,142 @@ var View = (function($, _){ - var View = function(options) { - this._id = _.uniqueId('view') - this.type = "view" - options || (options = {}); - _.extend(this, _.pick(options, viewOptions)) - this._ensureElement() - this.initialize.apply(this, arguments) - this.delegateEvents() - } + var View = function(options) { + this._id = _.uniqueId('view') + this.type = "view" + options || (options = {}); + _.extend(this, _.pick(options, viewOptions)) + this._ensureElement() + this.initialize.apply(this, arguments) + this.delegateEvents() + } - var delegateEventSplitter = /^(\S+)\s*(.*)$/; + var delegateEventSplitter = /^(\S+)\s*(.*)$/; - var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events']; + var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events']; - _.extend(View.prototype, { + _.extend(View.prototype, { - // The default `tagName` of a View's element is `"div"`. - tagName: 'div', + // The default `tagName` of a View's element is `"div"`. + tagName: 'div', - $: function(selector) { - return this.$el.find(selector); - }, + $: function(selector) { + return this.$el.find(selector); + }, - initialize: function(){}, + initialize: function(){}, - setElement: function(element, delegate) { - if (this.$el) this.undelegateEvents(); - this.$el = element instanceof $ ? element : $(element); - this.el = this.$el[0]; - if (delegate !== false) this.delegateEvents(); - return this; - }, + setElement: function(element, delegate) { + if (this.$el) this.undelegateEvents(); + this.$el = element instanceof $ ? element : $(element); + this.el = this.$el[0]; + if (delegate !== false) this.delegateEvents(); + return this; + }, - // Set callbacks, where `this.events` is a hash of - // - // *{"event selector": "callback"}* - // - // { - // 'mousedown .title': 'edit', - // 'click .button': 'save', - // 'click .open': function(e) { ... } - // } - // - // pairs. Callbacks will be bound to the view, with `this` set properly. - // Uses event delegation for efficiency. - // Omitting the selector binds the event to `this.el`. - // This only works for delegate-able events: not `focus`, `blur`, and - // not `change`, `submit`, and `reset` in Internet Explorer. - delegateEvents: function(events) { - if (!(events || (events = _.result(this, 'events')))) return this; - this.undelegateEvents(); - for (var key in events) { - var method = events[key]; - if (!_.isFunction(method)) method = this[events[key]]; - if (!method) continue; + // Set callbacks, where `this.events` is a hash of + // + // *{"event selector": "callback"}* + // + // { + // 'mousedown .title': 'edit', + // 'click .button': 'save', + // 'click .open': function(e) { ... } + // } + // + // pairs. Callbacks will be bound to the view, with `this` set properly. + // Uses event delegation for efficiency. + // Omitting the selector binds the event to `this.el`. + // This only works for delegate-able events: not `focus`, `blur`, and + // not `change`, `submit`, and `reset` in Internet Explorer. + delegateEvents: function(events) { + if (!(events || (events = _.result(this, 'events')))) return this; + this.undelegateEvents(); + for (var key in events) { + var method = events[key]; + if (!_.isFunction(method)) method = this[events[key]]; + if (!method) continue; - var match = key.match(delegateEventSplitter); - var eventName = match[1], selector = match[2]; - method = _.bind(method, this); - eventName += '.delegateEvents' + this._id; - if (selector === '') { - this.$el.on(eventName, method); - } else { - this.$el.on(eventName, selector, method); - } - } - return this; - }, + var match = key.match(delegateEventSplitter); + var eventName = match[1], selector = match[2]; + method = _.bind(method, this); + eventName += '.delegateEvents' + this._id; + if (is_mobile && (selector === 'mouseenter' || selector === 'mouseleave')) { + continue + } + else if (selector === '') { + this.$el.on(eventName, method); + } else { + this.$el.on(eventName, selector, method); + } + } + return this; + }, - // Clears all callbacks previously bound to the view with `delegateEvents`. - undelegateEvents: function() { - this.$el.off('.delegateEvents' + this._id); - return this; - }, + // Clears all callbacks previously bound to the view with `delegateEvents`. + undelegateEvents: function() { + this.$el.off('.delegateEvents' + this._id); + return this; + }, - // Ensure that the View has a DOM element to render into. - // If `this.el` is a string, pass it through `$()`, take the first - // matching element, and re-assign it to `el`. Otherwise, create - // an element from the `id`, `className` and `tagName` properties. - _ensureElement: function() { - this.setElement(_.result(this, 'el'), false); - }, - - preventDefault: function(e){ - e && e.preventDefault() - }, - - stopPropagation: function(e){ - e && e.stopPropagation() - }, + // Ensure that the View has a DOM element to render into. + // If `this.el` is a string, pass it through `$()`, take the first + // matching element, and re-assign it to `el`. Otherwise, create + // an element from the `id`, `className` and `tagName` properties. + _ensureElement: function() { + this.setElement(_.result(this, 'el'), false); + }, + + preventDefault: function(e){ + e && e.preventDefault() + }, + + stopPropagation: function(e){ + e && e.stopPropagation() + }, - }); + }); - var extend = function(protoProps, staticProps) { - var staticProps = staticProps || {} - var parent = this; - var child; - var childEvents = {}; + var extend = function(protoProps, staticProps) { + var staticProps = staticProps || {} + var parent = this; + var child; + var childEvents = {}; - // The constructor function for the new subclass is either defined by you - // (the "constructor" property in your `extend` definition), or defaulted - // by us to simply call the parent's constructor. - if (protoProps && _.has(protoProps, 'constructor')) { - child = protoProps.constructor; - } else { - child = function(){ return parent.apply(this, arguments); }; - } + // The constructor function for the new subclass is either defined by you + // (the "constructor" property in your `extend` definition), or defaulted + // by us to simply call the parent's constructor. + if (protoProps && _.has(protoProps, 'constructor')) { + child = protoProps.constructor; + } else { + child = function(){ return parent.apply(this, arguments); }; + } - // Extend events so we can subclass views - _.extend(childEvents, parent.prototype.events, protoProps.events) + // Extend events so we can subclass views + _.extend(childEvents, parent.prototype.events, protoProps.events) - // Add static properties to the constructor function, if supplied. - _.extend(child, parent, staticProps); + // Add static properties to the constructor function, if supplied. + _.extend(child, parent, staticProps); - // Set the prototype chain to inherit from `parent`, without calling - // `parent`'s constructor function. - var Surrogate = function(){ this.constructor = child; }; - Surrogate.prototype = parent.prototype; - child.prototype = new Surrogate; + // Set the prototype chain to inherit from `parent`, without calling + // `parent`'s constructor function. + var Surrogate = function(){ this.constructor = child; }; + Surrogate.prototype = parent.prototype; + child.prototype = new Surrogate; - // Add prototype properties (instance properties) to the subclass, - // if supplied. - if (protoProps) _.extend(child.prototype, protoProps); + // Add prototype properties (instance properties) to the subclass, + // if supplied. + if (protoProps) _.extend(child.prototype, protoProps); - // Set a convenience property in case the parent's prototype is needed - // later. - child.prototype.__super__ = parent.prototype; - child.prototype.events = childEvents + // Set a convenience property in case the parent's prototype is needed + // later. + child.prototype.__super__ = parent.prototype; + child.prototype.events = childEvents - return child; - }; + return child; + }; - View.extend = extend; - - return View; + View.extend = extend; + + return View; })(jQuery, _) |
