WordPress.org

Making WordPress.org

Changeset 8107


Ignore:
Timestamp:
01/18/2019 08:24:04 PM (11 months ago)
Author:
iandunn
Message:

WordCamp Payments: Apply coding standards.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-payments/javascript/budget-tool.js

    r8106 r8107  
    1 window.wcb = window.wcb || {models:{}, input:[]};
    2 
    3 (function($){
    4     var $document = $(document),
    5         $container = $('.wcb-budget-container tbody'),
    6         $income = $container.find('.wcb-income-placeholder'),
    7         $expense = $container.find('.wcb-expense-placeholder'),
    8         $meta = $container.find('.wcb-meta-placeholder'),
    9         $summary = $('.wcb-summary-placeholder'),
    10         $form = $('.wcb-submit-form');
    11 
    12     var template_options = {
    13         evaluate:    /<#([\s\S]+?)#>/g,
    14         interpolate: /\{\{\{([\s\S]+?)\}\}\}/g,
    15         escape:      /\{\{([^\}]+?)\}\}(?!\})/g,
    16         variable:    'data'
    17     };
    18 
    19     var Entry = Backbone.Model.extend({
     1window.wcb = window.wcb || { models: {}, input: [] };
     2
     3( function( $ ) {
     4    var wcb = window.wcb;
     5
     6    var $document  = $( document ),
     7        $container = $( '.wcb-budget-container tbody' ),
     8        $income    = $container.find( '.wcb-income-placeholder' ),
     9        $expense   = $container.find( '.wcb-expense-placeholder' ),
     10        $meta      = $container.find( '.wcb-meta-placeholder' ),
     11        $summary   = $( '.wcb-summary-placeholder' ),
     12        $form      = $( '.wcb-submit-form' );
     13
     14    var template_options = {
     15        evaluate    : /<#([\s\S]+?)#>/g,
     16        interpolate : /\{\{\{([\s\S]+?)\}\}\}/g,
     17        escape      : /\{\{([^\}]+?)\}\}(?!\})/g,
     18        variable    : 'data',
     19    };
     20
     21    var Entry = Backbone.Model.extend( {
    2022        defaults: {
    21             type: 'expense',
    22             category: 'other',
    23             amount: 0,
    24             note: '',
    25             new: false,
    26             link: null,
    27 
    28             // metadata
    29             name: '',
    30             value: null
    31         },
    32 
    33         initialize: function() {
    34             this._realAmount = this.getRealAmount();
    35             this._attr = _.clone(this.attributes);
    36         },
    37 
    38         getRealAmount: function() {
    39             if (!this.get('link'))
    40                 return this.get('amount');
    41 
    42             if (this.get('link') in wcb.linkData) {
    43                 var link = wcb.linkData[this.get('link')]
    44                 return link.callback(this.get('amount'));
    45             }
    46 
    47             return 0;
    48         },
    49 
    50         getLinkLabel: function() {
    51             if (!this.get('link'))
    52                 return '';
    53 
    54             if (this.get('link') in wcb.linkData)
    55                 return wcb.linkData[this.get('link')].label;
    56 
    57             return '';
    58         },
    59 
    60         linkHasValue: function() {
    61             if (!this.get('link'))
    62                 return false;
    63 
    64             if (this.get('link') in wcb.linkData)
    65                 return wcb.linkData[this.get('link')].hasValue;
    66 
    67             return false;
    68         },
    69 
    70         hasChanged: function() {
    71             // console.log(this._attr);
    72             // console.log(this.attributes);
    73             // console.log(this._realAmount)
    74 
    75             var _stringify = function(v) {
    76                 if (!v) return v;
    77                 return v.toString();
    78             }
    79 
    80             var changed = _.isEqual(
    81                 _.map(this._attr, _stringify),
    82                 _.map(this.attributes, _stringify)
    83             ) && this._realAmount == this.getRealAmount();
    84             return !changed;
    85         },
    86 
    87         editStart: function() {
    88             this.trigger('edit-start.wordcamp-budgets');
    89         }
    90     });
    91 
    92     var SummaryView = Backbone.View.extend({
    93         className: 'wcb-budget-container wcb-budget-summary',
    94         tagName: 'table',
    95         urls: [],
    96 
    97         events: {
    98             'click .inspire': 'inspire'
    99         },
    100 
    101         render: function() {
    102             var attendees = wcb.table.collection.findWhere({type: 'meta', name: 'attendees'}),
    103                 days      = wcb.table.collection.findWhere({type: 'meta', name: 'days'}),
    104                 data = {
    105                     'income': 0,
    106                     'expenses': 0,
    107                     'variance': 0,
    108                     'variance_raw': 0,
    109                     'per_person': 0
    110                 };
    111 
    112             _.each(wcb.table.collection.where({type: 'income'}), function(item) {
    113                 data['income'] += item.getRealAmount();
    114             });
    115 
    116             _.each(wcb.table.collection.where({type: 'expense'}), function(item) {
    117                 data['expenses'] += item.getRealAmount();
    118             });
    119 
    120             data['variance'] = data['income'] - data['expenses'];
    121             data['variance_raw'] = data['variance'];
    122             data['per_person'] = (attendees && days) ? data['expenses'] / attendees.get('value') / days.get('value'): 0;
    123 
    124             data = _.mapObject(data, function(v, k) {
    125                 if (k == 'variance_raw')
    126                     return v;
    127 
    128                 return v.toLocaleString('en-US', {
    129                     minimumFractionDigits: 2,
    130                     maximumFractionDigits: 2
    131                 });
    132             });
    133 
    134             this.template = _.template($('#wcb-tmpl-summary').html(), null, template_options);
    135             this.$el.html(this.template(data));
    136             return this;
    137         },
    138 
    139         initialize: function() {
    140             $summary.append(this.render().el);
    141             return this;
    142         },
    143 
    144         inspire: function(e) {
    145             e.target.href = this.urls[Math.floor(Math.random()*this.urls.length)];
    146             return true;
    147         }
    148     });
    149 
    150     var EntryView = Backbone.View.extend({
    151         className: 'wcb-entry',
    152         tagName: 'tr',
    153         cancel: false,
    154 
    155         events: {
    156             'keyup': 'keyup',
    157             'click .delete': 'delete',
    158             'click .move': 'move',
    159             'change input': 'editSave',
    160             'change select.category': 'editSave',
    161             'change select.link-value': 'linkChange',
    162             'change select.value': 'editSave',
    163 
    164             'focus input, select': 'focus',
    165             'blur input, select': 'blur'
    166         },
    167 
    168         initialize: function() {
    169             this.model.bind('destroy', this.remove, this);
    170         },
    171 
    172         linkChange: function() {
    173             this.model.set('link', this.$el.find('.link-value').val() || null);
    174             return this;
    175         },
    176 
    177         focus: function(e) {
    178             var $target = $(e.target);
    179             $target.parents('td').addClass('focused');
    180 
    181             if (($target.hasClass('amount') || $target.hasClass('link-value')) && this.model.get('link') && this.model.linkHasValue()) {
    182                 this.$el.find('.amount').val(this.model.get('amount').toLocaleString('en-US', {
    183                     minimumFractionDigits: 2,
    184                     maximumFractionDigits: 2
    185                 }));
    186             }
    187 
    188             if ($target.hasClass('note') && $target.parents('tr').hasClass('is-new')) {
    189                 if (_.contains(['New Expense Item', 'New Income Item'], this.model.get('note'))) {
    190                     this.$el.find('.note').val('');
    191                 }
    192             }
    193 
    194             return this;
    195         },
    196 
    197         blur: function(e) {
    198             var $target = $(e.target);
    199             $target.parents('td').removeClass('focused');
    200 
    201             if (($target.hasClass('amount') || $target.hasClass('link-value')) && this.model.get('link')) {
    202                 this.$el.find('.amount').val(this.model.getRealAmount().toLocaleString('en-US', {
    203                     minimumFractionDigits: 2,
    204                     maximumFractionDigits: 2
    205                 }));
    206             }
    207 
    208             if ($target.hasClass('note') && $target.parents('tr').hasClass('is-new')) {
    209                 if (_.contains(['New Expense Item', 'New Income Item'], this.model.get('note'))) {
    210                     this.$el.find('.note').val(this.model.get('note'));
    211                 }
    212             }
    213 
    214             return this;
    215         },
    216 
    217         render: function() {
    218             var data = this.model.toJSON();
    219             data.realAmount = this.model.getRealAmount();
    220             data.realAmountFormatted = data.realAmount.toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2});
    221             data.amountFormatted = data.amount.toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2});
    222             data.linkLabel = this.model.getLinkLabel();
    223             data.linkHasValue = this.model.linkHasValue();
    224 
    225             this.template = _.template($('#wcb-tmpl-entry').html(), null, template_options);
    226             this.$el.html(this.template(data));
    227             this.$el.toggleClass('has-changed', this.model.hasChanged() && ! this.model.get('new'));
    228             this.$el.toggleClass('is-new', this.model.get('new'));
    229             this.$el.data('wcb-cid', this.model.cid);
    230 
    231             if( data.name === 'currency' && $.fn.hasOwnProperty( 'select2' ) ){
    232                 var currSelect2Box = this.$el.find( 'select' ).select2( { width: '100%' } );
     23            type     : 'expense',
     24            category : 'other',
     25            amount   : 0,
     26            note     : '',
     27            new      : false,
     28            link     : null,
     29
     30            // metadata
     31            name  : '',
     32            value : null,
     33        },
     34
     35        initialize: function() {
     36            this._realAmount = this.getRealAmount();
     37            this._attr       = _.clone( this.attributes );
     38        },
     39
     40        getRealAmount: function() {
     41            if ( ! this.get( 'link' ) ) {
     42                return this.get( 'amount' );
     43            }
     44
     45            if ( this.get( 'link' ) in wcb.linkData ) {
     46                var link = wcb.linkData[ this.get( 'link' ) ];
     47                return link.callback( this.get( 'amount' ) );
     48            }
     49
     50            return 0;
     51        },
     52
     53        getLinkLabel: function() {
     54            if ( ! this.get( 'link' ) ) {
     55                return '';
     56            }
     57
     58            if ( this.get( 'link' ) in wcb.linkData ) {
     59                return wcb.linkData[ this.get( 'link' ) ].label;
     60            }
     61
     62            return '';
     63        },
     64
     65        linkHasValue: function() {
     66            if ( ! this.get( 'link' ) ) {
     67                return false;
     68            }
     69
     70            if ( this.get( 'link' ) in wcb.linkData ) {
     71                return wcb.linkData[ this.get( 'link' ) ].hasValue;
     72            }
     73
     74            return false;
     75        },
     76
     77        hasChanged: function() {
     78            var _stringify = function( v ) {
     79                if ( ! v ) {
     80                    return v;
     81                }
     82                return v.toString();
     83            };
     84
     85            var changed = _.isEqual(
     86                _.map( this._attr, _stringify ),
     87                _.map( this.attributes, _stringify )
     88            ) && this._realAmount == this.getRealAmount();
     89
     90            return ! changed;
     91        },
     92
     93        editStart: function() {
     94            this.trigger( 'edit-start.wordcamp-budgets' );
     95        },
     96    } );
     97
     98    var SummaryView = Backbone.View.extend( {
     99        className : 'wcb-budget-container wcb-budget-summary',
     100        tagName   : 'table',
     101        urls      : [],
     102
     103        events: {
     104            'click .inspire' : 'inspire',
     105        },
     106
     107        render: function() {
     108            var attendees = wcb.table.collection.findWhere( { type: 'meta', name: 'attendees' } ),
     109                days      = wcb.table.collection.findWhere( { type: 'meta', name: 'days' } ),
     110                data      = {
     111                    income       : 0,
     112                    expenses     : 0,
     113                    variance     : 0,
     114                    variance_raw : 0,
     115                    per_person   : 0,
     116                };
     117
     118            _.each( wcb.table.collection.where( { type: 'income' } ), function( item ) {
     119                data[ 'income' ] += item.getRealAmount();
     120            } );
     121
     122            _.each( wcb.table.collection.where( { type: 'expense' } ), function( item ) {
     123                data[ 'expenses' ] += item.getRealAmount();
     124            } );
     125
     126            data[ 'variance' ]     = data[ 'income' ] - data[ 'expenses' ];
     127            data[ 'variance_raw' ] = data[ 'variance' ];
     128            data[ 'per_person' ]   = ( attendees && days ) ? data[ 'expenses' ] / attendees.get( 'value' ) / days.get( 'value' ) : 0;
     129
     130            data = _.mapObject( data, function( v, k ) {
     131                if ( k == 'variance_raw' ) {
     132                    return v;
     133                }
     134
     135                return v.toLocaleString( 'en-US', {
     136                    minimumFractionDigits : 2,
     137                    maximumFractionDigits : 2,
     138                } );
     139            } );
     140
     141            this.template = _.template( $( '#wcb-tmpl-summary' ).html(), null, template_options );
     142            this.$el.html( this.template( data ) );
     143
     144            return this;
     145        },
     146
     147        initialize: function() {
     148            $summary.append( this.render().el );
     149            return this;
     150        },
     151
     152        inspire: function( e ) {
     153            e.target.href = this.urls[ Math.floor( Math.random() * this.urls.length ) ];
     154            return true;
     155        },
     156    } );
     157
     158    var EntryView = Backbone.View.extend( {
     159        className : 'wcb-entry',
     160        tagName   : 'tr',
     161        cancel    : false,
     162
     163        events: {
     164            'keyup'                    : 'keyup',
     165            'click .delete'            : 'delete',
     166            'click .move'              : 'move',
     167            'change input'             : 'editSave',
     168            'change select.category'   : 'editSave',
     169            'change select.link-value' : 'linkChange',
     170            'change select.value'      : 'editSave',
     171
     172            'focus input, select' : 'focus',
     173            'blur input, select'  : 'blur',
     174        },
     175
     176        initialize: function() {
     177            this.model.bind( 'destroy', this.remove, this );
     178        },
     179
     180        linkChange: function() {
     181            this.model.set( 'link', this.$el.find( '.link-value' ).val() || null );
     182            return this;
     183        },
     184
     185        focus: function( e ) {
     186            var $target = $( e.target );
     187            $target.parents( 'td' ).addClass( 'focused' );
     188
     189            if ( ( $target.hasClass( 'amount' ) || $target.hasClass( 'link-value' ) ) && this.model.get( 'link' ) && this.model.linkHasValue() ) {
     190                this.$el.find( '.amount' ).val( this.model.get( 'amount' ).toLocaleString( 'en-US', {
     191                    minimumFractionDigits : 2,
     192                    maximumFractionDigits : 2,
     193                } ) );
     194            }
     195
     196            if ( $target.hasClass( 'note' ) && $target.parents( 'tr' ).hasClass( 'is-new' ) ) {
     197                if ( _.contains( [ 'New Expense Item', 'New Income Item' ], this.model.get( 'note' ) ) ) {
     198                    this.$el.find( '.note' ).val( '' );
     199                }
     200            }
     201
     202            return this;
     203        },
     204
     205        blur: function( e ) {
     206            var $target = $( e.target );
     207            $target.parents( 'td' ).removeClass( 'focused' );
     208
     209            if ( ( $target.hasClass( 'amount' ) || $target.hasClass( 'link-value' ) ) && this.model.get( 'link' ) ) {
     210                this.$el.find( '.amount' ).val( this.model.getRealAmount().toLocaleString( 'en-US', {
     211                    minimumFractionDigits : 2,
     212                    maximumFractionDigits : 2,
     213                } ) );
     214            }
     215
     216            if ( $target.hasClass( 'note' ) && $target.parents( 'tr' ).hasClass( 'is-new' ) ) {
     217                if ( _.contains( [ 'New Expense Item', 'New Income Item' ], this.model.get( 'note' ) ) ) {
     218                    this.$el.find( '.note' ).val( this.model.get( 'note' ) );
     219                }
     220            }
     221
     222            return this;
     223        },
     224
     225        render: function() {
     226            var data                 = this.model.toJSON();
     227            data.realAmount          = this.model.getRealAmount();
     228            data.realAmountFormatted = data.realAmount.toLocaleString( 'en-US', {
     229                minimumFractionDigits : 2,
     230                maximumFractionDigits : 2,
     231            } );
     232            data.amountFormatted     = data.amount.toLocaleString( 'en-US', {
     233                minimumFractionDigits : 2,
     234                maximumFractionDigits : 2,
     235            } );
     236            data.linkLabel           = this.model.getLinkLabel();
     237            data.linkHasValue        = this.model.linkHasValue();
     238
     239            this.template = _.template( $( '#wcb-tmpl-entry' ).html(), null, template_options );
     240            this.$el.html( this.template( data ) );
     241            this.$el.toggleClass( 'has-changed', this.model.hasChanged() && ! this.model.get( 'new' ) );
     242            this.$el.toggleClass( 'is-new', this.model.get( 'new' ) );
     243            this.$el.data( 'wcb-cid', this.model.cid );
     244
     245            if ( data.name === 'currency' && $.fn.hasOwnProperty( 'select2' ) ) {
     246                var currSelect2Box       = this.$el.find( 'select' ).select2( { width: '100%' } );
    233247                var initializedSelectBox = currSelect2Box.data( 'select2' );
    234248                if ( initializedSelectBox ) {
     
    237251            }
    238252
    239             return this;
    240         },
    241 
    242         keyup: function(e) {
    243             if (e.keyCode == 27) {
    244                 return this.editCancel.apply(this, arguments);
    245             } else if (e.keyCode == 13) {
    246                 return this.editSave.apply(this, arguments);
    247             }
    248 
    249             return this;
    250         },
    251 
    252         editSave: function(e) {
    253             if (this.model.get('type') == 'meta') {
    254                 var value = this.$el.find('.value').val(),
    255                     name = this.model.get('name');
    256 
    257                 if (_.contains(['attendees', 'days', 'tracks', 'speakers', 'volunteers'], name)) {
    258                     value = parseInt(value.replace(/[^\d.-]/g, '')) || 0;
    259                 } else if (_.contains(['ticket-price'], name)) {
    260                     value = parseFloat(value.replace(/[^\d.-]/g, '')) || 0;
    261                 }
    262 
    263                 this.model.set('value', value);
    264             } else {
    265                 this.model.set('note', this.$el.find('.note').val());
    266                 this.model.set('category', this.$el.find('.category').val());
    267 
    268                 var $target = $(e.target);
    269                 if ($target.hasClass('amount') || $target.hasClass('link-value')) {
    270                     var amount = parseFloat(this.$el.find('.amount').val().replace(/[^\d.-]/g, ''));
    271                     this.model.set('amount', amount || 0);
    272                 }
     253            return this;
     254        },
     255
     256        keyup: function( e ) {
     257            if ( e.keyCode == 27 ) {
     258                return this.editCancel.apply( this, arguments );
     259            } else if ( e.keyCode == 13 ) {
     260                return this.editSave.apply( this, arguments );
     261            }
     262
     263            return this;
     264        },
     265
     266        editSave: function( e ) {
     267            if ( this.model.get( 'type' ) == 'meta' ) {
     268                var value = this.$el.find( '.value' ).val(),
     269                    name  = this.model.get( 'name' );
     270
     271                if ( _.contains( [ 'attendees', 'days', 'tracks', 'speakers', 'volunteers' ], name ) ) {
     272                    value = parseInt( value.replace( /[^\d.-]/g, '' ) ) || 0;
     273                } else if ( _.contains( [ 'ticket-price' ], name ) ) {
     274                    value = parseFloat( value.replace( /[^\d.-]/g, '' ) ) || 0;
     275                }
     276
     277                this.model.set( 'value', value );
     278            } else {
     279                this.model.set( 'note', this.$el.find( '.note' ).val() );
     280                this.model.set( 'category', this.$el.find( '.category' ).val() );
     281
     282                var $target = $( e.target );
     283                if ( $target.hasClass( 'amount' ) || $target.hasClass( 'link-value' ) ) {
     284                    var amount = parseFloat( this.$el.find( '.amount' ).val().replace( /[^\d.-]/g, '' ) );
     285                    this.model.set( 'amount', amount || 0 );
     286                }
    273287                this.render.apply( this );
    274288            }
    275289
    276             this.clearSelection.apply(this);
    277             return false;
    278         },
    279 
    280         editCancel: function(e) {
    281             this.clearSelection.apply(this);
    282 
    283             if (this.model.get('type') == 'meta') {
    284                 this.$el.find('.value').val(this.model.get('value'));
    285             } else {
    286                 this.$el.find('.amount').val(this.model.get('amount'));
    287                 this.$el.find('.note').val(this.model.get('note'));
    288             }
    289 
    290             this.editSave.apply(this, arguments);
    291             return false;
    292         },
    293 
    294         clearSelection: function() {
    295             if (window.getSelection) {
    296                 if (window.getSelection().empty) {
    297                     window.getSelection().empty();
    298                 } else if (window.getSelection().removeAllRanges) {
    299                     window.getSelection().removeAllRanges();
    300                 }
    301             } else if (document.selection) {
    302                 document.selection.empty();
    303             }
    304         },
    305 
    306         delete: function() {
    307             if (!confirm('Delete this line item?'))
    308                 return false;
    309 
    310             this.model.destroy();
    311             wcb.summary.render.apply(wcb.summary);
    312             return false;
    313         },
    314 
    315         move: function() {
    316             return false;
    317         }
    318     });
    319 
    320     var Entries = Backbone.Collection.extend({
    321         model: Entry
    322     });
    323 
    324     var EntriesView = Backbone.View.extend({
    325         tagName: 'table',
    326         className: 'wcb-table',
    327 
    328         initialize: function() {
    329             this.collection.bind('add', this.addOne, this);
    330             this.collection.bind('change reset', this.refresh, this);
    331         },
    332 
    333         refresh: function(model) {
    334             if (model.get('type') == 'meta') {
    335                 this.render.apply(this);
    336             }
    337 
    338             wcb.summary.render.apply(wcb.summary);
    339             return this;
    340         },
    341 
    342         addOne: function(item) {
    343             var view = new EntryView({model: item});
    344             switch (view.model.get('type')) {
    345                 case 'expense':
    346                     var $c = $expense;
    347                     break;
    348                 case 'income':
    349                     var $c = $income;
    350                     break;
    351                 case 'meta':
    352                 default:
    353                     var $c = $meta;
    354             }
    355 
    356             $c.before(view.render().el);
    357         },
    358 
    359         render: function() {
    360             $container.find('.wcb-entry').remove();
    361             this.collection.each(this.addOne, this);
    362             return this;
    363         }
    364     });
     290            this.clearSelection.apply( this );
     291
     292            return false;
     293        },
     294
     295        editCancel: function( e ) {
     296            this.clearSelection.apply( this );
     297
     298            if ( this.model.get( 'type' ) == 'meta' ) {
     299                this.$el.find( '.value' ).val( this.model.get( 'value' ) );
     300            } else {
     301                this.$el.find( '.amount' ).val( this.model.get( 'amount' ) );
     302                this.$el.find( '.note' ).val( this.model.get( 'note' ) );
     303            }
     304
     305            this.editSave.apply( this, arguments );
     306
     307            return false;
     308        },
     309
     310        clearSelection: function() {
     311            if ( window.getSelection ) {
     312                if ( window.getSelection().empty ) {
     313                    window.getSelection().empty();
     314                } else if ( window.getSelection().removeAllRanges ) {
     315                    window.getSelection().removeAllRanges();
     316                }
     317            } else if ( document.selection ) {
     318                document.selection.empty();
     319            }
     320        },
     321
     322        delete: function() {
     323            if ( ! confirm( 'Delete this line item?' ) ) {
     324                return false;
     325            }
     326
     327            this.model.destroy();
     328            wcb.summary.render.apply( wcb.summary );
     329
     330            return false;
     331        },
     332
     333        move: function() {
     334            return false;
     335        },
     336    } );
     337
     338    var Entries = Backbone.Collection.extend( {
     339        model : Entry,
     340    } );
     341
     342    var EntriesView = Backbone.View.extend( {
     343        tagName   : 'table',
     344        className : 'wcb-table',
     345
     346        initialize: function() {
     347            this.collection.bind( 'add', this.addOne, this );
     348            this.collection.bind( 'change reset', this.refresh, this );
     349        },
     350
     351        refresh: function( model ) {
     352            if ( model.get( 'type' ) == 'meta' ) {
     353                this.render.apply( this );
     354            }
     355
     356            wcb.summary.render.apply( wcb.summary );
     357
     358            return this;
     359        },
     360
     361        addOne: function( item ) {
     362            var view = new EntryView( { model: item } );
     363
     364            switch ( view.model.get( 'type' ) ) {
     365                case 'expense':
     366                    var $c = $expense;
     367                    break;
     368                case 'income':
     369                    var $c = $income;
     370                    break;
     371                case 'meta':
     372                default:
     373                    var $c = $meta;
     374            }
     375
     376            $c.before( view.render().el );
     377        },
     378
     379        render: function() {
     380            $container.find( '.wcb-entry' ).remove();
     381            this.collection.each( this.addOne, this );
     382
     383            return this;
     384        },
     385    } );
    365386
    366387    // Decode HTML entities in category names
     
    369390    } );
    370391
    371     wcb.metaLabels = {
    372         'attendees': 'Attendees',
    373         'days': 'Days',
    374         'tracks': 'Tracks',
    375         'speakers': 'Speakers',
    376         'volunteers': 'Volunteers',
    377         'currency': 'Currency',
    378         'ticket-price': 'Ticket Price'
    379     };
    380 
    381     wcb.linkData = {
    382         'per-speaker': {
    383             'label': 'per speaker',
    384             'hasValue': true,
    385             'callback': function(value) {
    386                 return parseFloat(value) * parseInt(wcb.table.collection.findWhere({type: 'meta', name: 'speakers'}).get('value'));
    387             }
    388         },
    389 
    390         'per-volunteer': {
    391             'label': 'per volunteer',
    392             'hasValue': true,
    393             'callback': function(value) {
    394                 return parseFloat(value) * parseInt(wcb.table.collection.findWhere({type: 'meta', name: 'volunteers'}).get('value'));
    395             }
    396         },
    397 
    398         'per-speaker-volunteer': {
    399             'label': 'per speakers + volunteers',
    400             'hasValue': true,
    401             'callback': function(value) {
    402                 return parseFloat(value) * (
    403                     parseInt(wcb.table.collection.findWhere({type: 'meta', name: 'volunteers'}).get('value'))
    404                     + parseInt(wcb.table.collection.findWhere({type: 'meta', name: 'speakers'}).get('value'))
    405                 );
    406             }
    407         },
    408 
    409         'per-attendee': {
    410             'label': 'per attendee',
    411             'hasValue': true,
    412             'callback': function(value) {
    413                 return parseFloat(value) * parseInt(wcb.table.collection.findWhere({type: 'meta', name: 'attendees'}).get('value'));
    414             }
    415         },
    416 
    417         'per-day': {
    418             'label': 'per day',
    419             'hasValue': true,
    420             'callback': function(value) {
    421                 return parseFloat(value) * parseInt(wcb.table.collection.findWhere({type: 'meta', name: 'days'}).get('value'));
    422             }
    423         },
    424 
    425         'per-track': {
    426             'label': 'per track',
    427             'hasValue': true,
    428             'callback': function(value) {
    429                 return parseFloat(value) * parseInt(wcb.table.collection.findWhere({type: 'meta', name: 'tracks'}).get('value'));
    430             }
    431         },
    432 
    433         'ticket-price-x-attendees': {
    434             'label': 'ticket price &times; attendees',
    435             'hasValue': false,
    436             'callback': function(value) {
    437                 var attendees = wcb.table.collection.findWhere({type: 'meta', name: 'attendees'}).get('value');
    438                 var price = wcb.table.collection.findWhere({type: 'meta', name: 'ticket-price'}).get('value');
    439                 return parseInt(attendees) * parseFloat(price);
    440             }
    441         }
    442     };
    443 
    444     var table = new EntriesView({collection: new Entries()});
    445 
    446     $income.on('click', function() {
    447         table.collection.add(new wcb.models.Entry({
    448             type: 'income',
    449             amount: 0,
    450             note: 'New Income Item',
    451             category: 'other',
    452             new: true
    453         })).editStart();
    454         return false;
    455     });
    456 
    457     $expense.on('click', function() {
    458         table.collection.add(new wcb.models.Entry({
    459             type: 'expense',
    460             amount: 0,
    461             note: 'New Expense Item',
    462             category: 'other',
    463             new: true
    464         })).editStart();
    465         return false;
    466     });
    467 
    468     $form.on('submit', function() {
    469         $container.find('.wcb-entry').each(function(el){
    470             var $this = $(this);
    471                 model = wcb.table.collection.get($this.data('wcb-cid'));
    472 
    473             model.set({'order': $this.index()}, {silent: true});
    474         });
    475 
    476         var sorted = JSON.stringify(wcb.table.collection.sortBy(function(m){
    477             return m.get('type') + ':' + (m.get('order')/Math.pow(10,10)).toFixed(10); // Don't ask.
    478         }));
    479 
    480         $form.find('[name="_wcb_budget_data"]').val(sorted);
    481         return true;
    482     });
    483 
    484     wcb.models.Entry = Entry;
    485     wcb.table = table;
    486     wcb.summary = new SummaryView();
    487 
    488     // Sort all the input by types, meta first, because linked data in
    489     // income and expenses rely on meta values.
    490     var types = ['meta', 'expense', 'income'];
    491     wcb.input = _.sortBy(wcb.input, function(i) {
    492         return types.indexOf(i.type);
    493     });
    494 
    495     _.each(wcb.input, function(i){
    496         wcb.table.collection.add(new wcb.models.Entry(i));
    497     });
    498 
    499     wcb.summary.urls = wcb.urls;
    500     wcb.summary.render();
    501 
    502     // Allow sorting entries.
    503     $container.sortable({
    504         items: '.wcb-entry',
    505         handle: '.move',
    506         axis: 'y',
    507         placeholder: 'wcb-entry-placeholder',
    508         start: function(e, ui) {
    509             ui.placeholder.height(ui.item.height());
    510         }
    511     });
    512 
    513     // Update nonces when necessary.
    514     // TODO: Add post locking.
    515     $document.on('heartbeat-send', function(e, data) {
    516         data['wcb_budgets_heartbeat'] = 1;
    517     });
    518 
    519     $document.on('heartbeat-tick', function(e, data) {
    520         $('#_wpnonce').val(data.wcb_budgets.nonce);
    521     });
    522 
    523     $document.on('click', '#wcb-budget-submit', function() {
    524         if (!confirm('Are you sure you would like to submit this budget for approval?'))
    525             return false;
    526 
    527         return true;
    528     });
    529 
    530     $document.on('click', '#wcb-budget-approve, #wcb-budget-reject', function() {
    531         if (!confirm('Are you sure?'))
    532             return false;
    533 
    534         return true;
    535     });
    536 }(jQuery));
     392    wcb.metaLabels = {
     393        'attendees'    : 'Attendees',
     394        'days'         : 'Days',
     395        'tracks'       : 'Tracks',
     396        'speakers'     : 'Speakers',
     397        'volunteers'   : 'Volunteers',
     398        'currency'     : 'Currency',
     399        'ticket-price' : 'Ticket Price',
     400    };
     401
     402    wcb.linkData = {
     403        'per-speaker' : {
     404            'label'    : 'per speaker',
     405            'hasValue' : true,
     406            'callback' : function( value ) {
     407                return parseFloat( value ) * parseInt( wcb.table.collection.findWhere( {
     408                    type : 'meta',
     409                    name : 'speakers',
     410                } ).get( 'value' ) );
     411            },
     412        },
     413
     414        'per-volunteer' : {
     415            'label'    : 'per volunteer',
     416            'hasValue' : true,
     417            'callback' : function( value ) {
     418                return parseFloat( value ) * parseInt( wcb.table.collection.findWhere( {
     419                    type : 'meta',
     420                    name : 'volunteers',
     421                } ).get( 'value' ) );
     422            },
     423        },
     424
     425        'per-speaker-volunteer' : {
     426            'label'    : 'per speakers + volunteers',
     427            'hasValue' : true,
     428            'callback' : function( value ) {
     429                return parseFloat( value ) * (
     430                    parseInt( wcb.table.collection.findWhere( {
     431                        type : 'meta',
     432                        name : 'volunteers',
     433                    } ).get( 'value' ) )
     434                    + parseInt( wcb.table.collection.findWhere( {
     435                        type : 'meta',
     436                        name : 'speakers',
     437                    } ).get( 'value' ) )
     438                );
     439            },
     440        },
     441
     442        'per-attendee' : {
     443            'label'    : 'per attendee',
     444            'hasValue' : true,
     445            'callback' : function( value ) {
     446                return parseFloat( value ) * parseInt( wcb.table.collection.findWhere( {
     447                    type : 'meta',
     448                    name : 'attendees',
     449                } ).get( 'value' ) );
     450            },
     451        },
     452
     453        'per-day' : {
     454            'label'    : 'per day',
     455            'hasValue' : true,
     456            'callback' : function( value ) {
     457                return parseFloat( value ) * parseInt( wcb.table.collection.findWhere( {
     458                    type : 'meta',
     459                    name : 'days',
     460                } ).get( 'value' ) );
     461            },
     462        },
     463
     464        'per-track' : {
     465            'label'    : 'per track',
     466            'hasValue' : true,
     467            'callback' : function( value ) {
     468                return parseFloat( value ) * parseInt( wcb.table.collection.findWhere( {
     469                    type : 'meta',
     470                    name : 'tracks',
     471                } ).get( 'value' ) );
     472            },
     473        },
     474
     475        'ticket-price-x-attendees' : {
     476            'label'    : 'ticket price &times; attendees',
     477            'hasValue' : false,
     478            'callback' : function( value ) {
     479                var attendees = wcb.table.collection.findWhere( {
     480                    type : 'meta',
     481                    name : 'attendees',
     482                } ).get( 'value' );
     483                var price     = wcb.table.collection.findWhere( {
     484                    type : 'meta',
     485                    name : 'ticket-price',
     486                } ).get( 'value' );
     487
     488                return parseInt( attendees ) * parseFloat( price );
     489            },
     490        },
     491    };
     492
     493    var table = new EntriesView( { collection: new Entries() } );
     494
     495    $income.on( 'click', function() {
     496        table.collection.add( new wcb.models.Entry( {
     497            type     : 'income',
     498            amount   : 0,
     499            note     : 'New Income Item',
     500            category : 'other',
     501            new      : true,
     502        } ) ).editStart();
     503        return false;
     504    } );
     505
     506    $expense.on( 'click', function() {
     507        table.collection.add( new wcb.models.Entry( {
     508            type     : 'expense',
     509            amount   : 0,
     510            note     : 'New Expense Item',
     511            category : 'other',
     512            new      : true,
     513        } ) ).editStart();
     514        return false;
     515    } );
     516
     517    $form.on( 'submit', function() {
     518        $container.find( '.wcb-entry' ).each( function( el ) {
     519            var $this = $( this );
     520            model     = wcb.table.collection.get( $this.data( 'wcb-cid' ) );
     521
     522            model.set( { 'order': $this.index() }, { silent: true } );
     523        } );
     524
     525        var sorted = JSON.stringify( wcb.table.collection.sortBy( function( m ) {
     526            return m.get( 'type' ) + ':' + ( m.get( 'order' ) / Math.pow( 10, 10 ) ).toFixed( 10 ); // Don't ask.
     527        } ) );
     528
     529        $form.find( '[name="_wcb_budget_data"]' ).val( sorted );
     530
     531        return true;
     532    } );
     533
     534    wcb.models.Entry = Entry;
     535    wcb.table        = table;
     536    wcb.summary      = new SummaryView();
     537
     538    // Sort all the input by types, meta first, because linked data in
     539    // income and expenses rely on meta values.
     540    var types = [ 'meta', 'expense', 'income' ];
     541    wcb.input = _.sortBy( wcb.input, function( i ) {
     542        return types.indexOf( i.type );
     543    } );
     544
     545    _.each( wcb.input, function( i ) {
     546        wcb.table.collection.add( new wcb.models.Entry( i ) );
     547    } );
     548
     549    wcb.summary.urls = wcb.urls;
     550    wcb.summary.render();
     551
     552    // Allow sorting entries.
     553    $container.sortable( {
     554        items       : '.wcb-entry',
     555        handle      : '.move',
     556        axis        : 'y',
     557        placeholder : 'wcb-entry-placeholder',
     558        start       : function( e, ui ) {
     559            ui.placeholder.height( ui.item.height() );
     560        },
     561    } );
     562
     563    // Update nonces when necessary.
     564    // TODO: Add post locking.
     565    $document.on( 'heartbeat-send', function( e, data ) {
     566        data[ 'wcb_budgets_heartbeat' ] = 1;
     567    } );
     568
     569    $document.on( 'heartbeat-tick', function( e, data ) {
     570        $( '#_wpnonce' ).val( data.wcb_budgets.nonce );
     571    } );
     572
     573    $document.on( 'click', '#wcb-budget-submit', function() {
     574        if ( ! confirm( 'Are you sure you would like to submit this budget for approval?' ) ) {
     575            return false;
     576        }
     577
     578        return true;
     579    } );
     580
     581    $document.on( 'click', '#wcb-budget-approve, #wcb-budget-reject', function() {
     582        if ( ! confirm( 'Are you sure?' ) ) {
     583            return false;
     584        }
     585
     586        return true;
     587    } );
     588}( jQuery ) );
Note: See TracChangeset for help on using the changeset viewer.