diff --git a/app-base/application.js b/app-base/application.js index ed29111..d2f0247 100644 --- a/app-base/application.js +++ b/app-base/application.js @@ -47,9 +47,7 @@ var loadUserSets = function loadUserSets ( user_id, next ) { //next.apply(null,arguments); showError('Error loading sets' + (textStatus ? ': ' + textStatus + ' (' + jqXHR.status + ')' : '') ); }, - complete: function() { - console.log(arguments); - } + timeout: 10000 }); } diff --git a/app-base/controllers/set-controller.js b/app-base/controllers/set-controller.js index d1c6307..bcde376 100644 --- a/app-base/controllers/set-controller.js +++ b/app-base/controllers/set-controller.js @@ -3,29 +3,71 @@ var Controller = require('controllers/base/controller'), SetModel = require('models/set-model'), ErrorView = require('views/error-view'); +var current_opts = prev_opts = {}; // hack this sh*t + module.exports = Controller.extend({ show : function ( opts ) { - - this.model = new SetModel(); + // console.log("set#show", opts.setid, opts.cellid); + + prev_opts = current_opts; + current_opts = opts; + + this.compose('set', { + compose : function() { + // console.log("composing"); + + // create set model + this.model = new SetModel(); + + // create set view + this.view = new SetView({ + region: 'content', + model: this.model + }); + + this.model.fetch({ + id : opts.setid, + + error : function(model, response, options) { + //Chaplin.helpers.redirectTo('error#show', {message: 'Error message'}); // use this to redirect to an error page (changes url) + new ErrorView( {message : 'Couldn\'t get the set you requested. (' + response.status + ')'} ); + } + }); + + this.model.synced(function(){ + this.view.render(); - this.model.fetch({ - id : opts.setid, + // scroll (jump) to cellid + _(function() { + if (current_opts.cellid) { + this.model.collectionView.scrollToCell(current_opts.cellid, 0); + } + }).bind(this).defer(); + }, this); + }, - error : function(model, response, options) { - //Chaplin.helpers.redirectTo('error#show', {message: 'Error message'}); // use this to redirect to an error page (changes url) - new ErrorView( {message : 'Couldn\'t get the set you requested. (' + response.status + ')'} ); + check : function() { + // differnet set -> reload + if ( current_opts.setid != prev_opts.setid ) { + return false; //rerun compose() + } + + // same set, but removed cell id -> reload + if ( current_opts.cellid == undefined && current_opts.setid == prev_opts.setid ) { + return false; //rerun compose() + } + + // same set, cell id given -> scroll to cell + if (current_opts.cellid) { + this.model.collectionView.scrollToCell(current_opts.cellid, 0); + } + + return true; // don't rerun compose() } - }); - this.model.synced(function(){ - setView.render(); - }); - - var setView = this.view = new SetView({ - region: 'content', - model: this.model }); + } }); diff --git a/app-base/css/11-app.css b/app-base/css/11-app.css index 1e50a06..b1de894 100644 --- a/app-base/css/11-app.css +++ b/app-base/css/11-app.css @@ -1,8 +1,8 @@ #app-background { /*background-image: url('http://motionbank-media.s3.amazonaws.com/dh/app/imgs/backs/background-1.jpg');*/ - background: -webkit-radial-gradient(45px 45px, cover, #666 0%, #222 100%); - background: -moz-radial-gradient(45px 45px, cover, #666 0%, #222 100%); - background: radial-gradient(45px 45px, cover, #666 0%, #222 100%); + background: -webkit-radial-gradient(45px 45px, cover, #3b4241 0%, #1d2121 100%); + background: -moz-radial-gradient(45px 45px, cover, #3b4241 0%, #1d2121 100%); + background: radial-gradient(45px 45px, cover, #3b4241 0%, #1d2121 100%); background-size: cover; -webkit-background-size: cover; -moz-background-size: cover; diff --git a/app-base/css/34-cell.css b/app-base/css/34-cell.css index b0d61ba..7365e25 100644 --- a/app-base/css/34-cell.css +++ b/app-base/css/34-cell.css @@ -228,3 +228,13 @@ .cell-collection .cell.type-text .info { display: none; }*/ +.cell .loading { color:white; position:absolute; top:0;left:0;bottom:0;right:0; font-size:200%; text-align:center; vertical-align: middle; line-height:100%;} +.cell .loading span { display:inline-block; margin-top:30%; } +.cell .loading span:after { content:'•'; } +.cell .loading .dot1 { -webkit-animation: fadeOut 0.7s 0.00s infinite alternate; animation: fadeOut 0.7s 0.00s infinite alternate; } +.cell .loading .dot2 { -webkit-animation: fadeOut 0.7s 0.35s infinite alternate; animation: fadeOut 0.7s 0.35s infinite alternate; } +.cell .loading .dot3 { -webkit-animation: fadeOut 0.7s 0.70s infinite alternate; animation: fadeOut 0.7s 0.70s infinite alternate; } +@-webkit-keyframes fadeOut { from {opacity:1;} to {opacity:0;} } +@keyframes fadeOut { from {opacity:1;} to {opacity:0;} } +.cell .content { position:relative; } /* so .loading doesn't overlay it */ + diff --git a/app-base/models/cell-model.js b/app-base/models/cell-model.js index 9eded1b..52bbb57 100644 --- a/app-base/models/cell-model.js +++ b/app-base/models/cell-model.js @@ -19,6 +19,7 @@ module.exports = BaseModel.extend({ modeltype : 'cell', + // attributes that can't be overwritten in fields lockedAttributes : { type : null, sets : null, @@ -29,13 +30,17 @@ module.exports = BaseModel.extend({ }, // check if this cell has the sticky flag set - // TODO: using fields is not necessary. just use this.attributes.sticky with RegEx.test - isSticky : function() { - return _.any(this.attributes.fields, function(field) { - return ( field.name === 'sticky' && (field.value === 'true' || field.value === '1') ); - }); + // TODO: just use getFlag('sticky') instead + isSticky : function () { + return this.getFlag('sticky'); }, + // checks if an attribute is present and either 'true' or '1' + getFlag : function (flag) { + return /true|1/i.test(this.get(flag)); + }, + + // sets attributes and applies overrides set via fields set : function ( opts ) { // override some attributes per set<->cell connection if ( opts && typeof opts === 'object' && 'fields' in opts ) { diff --git a/app-base/routes.js b/app-base/routes.js index eb7a820..51cada8 100644 --- a/app-base/routes.js +++ b/app-base/routes.js @@ -1,8 +1,10 @@ module.exports = function(match) { + + match( 'set/:setid', 'set#show' ); + match( 'set/:setid/', 'set#show' ); + match( 'set/:setid/:cellid', 'set#show' ); + match( 'set/:setid/:cellid/', 'set#show' ); - match( 'set/:setid', 'set#show' - //,{ constraints: { setid: /^\d+$/ }} - ); match( '', 'cover#index' ); // match( 'error', 'error#show' ); // to test and error page (to redirect to) diff --git a/app-base/views/cell-collection-view.js b/app-base/views/cell-collection-view.js index 1c2e59f..b4957f0 100644 --- a/app-base/views/cell-collection-view.js +++ b/app-base/views/cell-collection-view.js @@ -1,3 +1,4 @@ +/* cell-collection-view.js */ var CellDefaultView = require('views/cell-view'), BaseCollectionView = require('views/base/collection-view'), mediator = require('mediator'), @@ -21,6 +22,7 @@ module.exports = BaseCollectionView.extend({ }, render : function () { + console.log("rendering cell collection"); BaseCollectionView.prototype.render.apply(this,arguments); // after rendring is finished attach scroll listener _(function(){ @@ -54,6 +56,15 @@ module.exports = BaseCollectionView.extend({ } return cellView; + }, + + // scroll to a cell + scrollToCell : function (cellid, time) { + if (cellid == undefined) return; + var cellView = _.find(this.subviews, function(cellView) { + return cellView.model.id == cellid; + }); + if (cellView) cellView.scrollTo(time); } }); \ No newline at end of file diff --git a/app-base/views/cell-types/cell-iframe-view.js b/app-base/views/cell-types/cell-iframe-view.js index cf218fa..852c1c4 100644 --- a/app-base/views/cell-types/cell-iframe-view.js +++ b/app-base/views/cell-types/cell-iframe-view.js @@ -1,83 +1,72 @@ +/* cell-iframe-view.js */ var CellDefaultView = require('views/cell-view'), config = require('config/config'), pm = require('postmessenger'), hasher = require('hasher'); module.exports = CellDefaultView.extend({ + // attributes governing how a cell behaves in the view + // cell types have default values. can be overridden via fields + // these are the defaults use by most cell types + defaultViewAttributes : { + autoload : 1, // open on scroll in? + sticky : 0, // don't close on scroll out? + solo: 0 // close other cells on open? + }, - // events : { - // 'click' : function () { - // this.renderContent(); - // } - // }, - - // keep this in sync with cell-vimeo! - render : function () { + events : { + 'click' : function () { + // console.log("click"); + if ( !this.isOpen() ) { + this.open(); + } + } + }, - CellDefaultView.prototype.render.apply(this,arguments); + loadState : "closed", - if ( this.model.attributes['autoload'] && - /^(1|true)$/i.test(this.model.attributes['autoload']) ) { - this.renderContent(); - } + isOpen : function() { + return this.loadState.toLowerCase() == "open"; + }, - return this; + isClosed : function() { + return this.loadState.toLowerCase() == "closed"; }, - renderContent : function () { - // load iframe from data-src - $('iframe',this.$el).attr('src',$('iframe',this.$el).data('src')); - - // connect to iframe with postmessenger - _(function(){ - - var view = this; - var iframe = $('iframe',this.$el); - - iframe.load(function() { - // show content, hide info - $('.element-hidden',view.$el).removeClass('element-hidden'); - $('.info',view.$el).addClass('element-hidden'); - - view.$iframe = $(this); - // if iframe on another domain add that to the accept list - var src = view.model.get('iframe-src'); - if ( /^http[s]?:\/\/.+/.test(src) ) { - var iframe_domain = (function(){ - var p = src.split('/'); - return p[0]+'//'+p[2]; - })(); - pm.accept(iframe_domain); - } - - // connect it - pm.send( - 'connect?', - { listener_id: hasher.generate(20) }, - this.contentWindow, - iframe_domain - ); - }); - - }).bind(this).defer(); + isLoading : function() { + return this.loadState.toLowerCase() == "loading"; + }, - this.$el.css({ - 'background-image' : 'none' + initialize : function () { + CellDefaultView.prototype.initialize.apply(this,arguments); + // fill in missing view attributs with defaults + _.defaults(this.model.attributes, this.defaultViewAttributes); + + // listen for solo event. close if in same solo group + this.subscribeEvent('!solo', function(args) { + // console.log("solo "); + // console.log(args); + // skip if we sent that event + if ( args.origin == this ) { return; } + if ( args.group == this.model.get('solo') ) { + // close if open or loading + if (!this.isClosed()) this.close(); + } }); }, getTemplateData : function () { var data = CellDefaultView.prototype.getTemplateData.apply(this,arguments); + if ( Handlebars.compile && data['iframe-src'] ) { data['iframe-src'] = Handlebars.compile(data['iframe-src'])(config); } - var spl = data['iframe-src'].split('?'); - data['iframe-src'] = spl[0] + '?' + 'domain=http://' + config.host + '&' + (spl[1] || ''); - // if ( false === /^http[s]:\/\/.+/.test(data['iframe-src']) ) { - // data['iframe-src'] = 'http://' + config.host + config.baseUrl + data['iframe-src']; - // } + if ( data['iframe-src'] ) { + var spl = data['iframe-src'].split('?'); + data['iframe-src'] = spl[0] + '?' + 'domain=http://' + config.host + '&' + (spl[1] || ''); + } - // collect attributes for +

{{{title}}}

{{description}}
-
-
-
\ No newline at end of file diff --git a/bower.json b/bower.json index b934cfd..abfcb5f 100644 --- a/bower.json +++ b/bower.json @@ -5,7 +5,7 @@ "dependencies": { "chaplin" : "~0.11.3", "console-polyfill" : "~0.1.0", - "lodash" : "~1.3.1", + "lodash" : "~2.3.0", "jquery" : "~2.0.2", "normalize-css" : "~2.1.2", "h5bp-helpers" : "~0.1.0",