1
0
Fork 0

initial commit

This commit is contained in:
Sangbum Kim 2017-04-27 23:30:52 +09:00
commit 9e2a58cd4d
127 changed files with 23001 additions and 0 deletions

130
.gitignore vendored Normal file
View File

@ -0,0 +1,130 @@
# Created by https://www.gitignore.io/api/intellij,go,linux,osx,windows
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
.idea
*.iml
## File-based project format:
*.ipr
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### Go ###
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof
### Linux ###
*~
*.swp
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
### OSX ###
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Windows ###
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
build/
bind/
vendor/
mecab/
*.log
.vscode/
changer
settings_test.yml

61
Makefile Normal file
View File

@ -0,0 +1,61 @@
# This how we want to name the binary output
BINARY=changer
# These are the values we want to pass for VERSION and BUILD
# git tag 1.0.1
# git commit -am "One more change after the tags"
VERSION=`git describe --always`
BUILD=`date +%FT%T%z`
# Setup the -ldflags option for go build here, interpolate the variable values
LDFLAGS=-ldflags "-w -s -X amuz.es/gogs/infra/changer/util.version=${VERSION} -X amuz.es/gogs/infra/changer/util.buildDate=${BUILD}"
CGO_ENABLED=0
# Builds the project
build:
go build ${LDFLAGS} -o ${BINARY}
strip -x ${BINARY}
# Builds the project
setup:
go get -u github.com/kardianos/govendor
go get -u github.com/jteeuwen/go-bindata/...
# go get -u github.com/gogo/protobuf/proto
# go get -u github.com/gogo/protobuf/protoc-gen-gogo
# go get -u github.com/gogo/protobuf/gogoproto
# go get -u github.com/gogo/protobuf/protoc-gen-gofast
# go get -u github.com/gogo/protobuf/protoc-gen-gogofaster
# go get -u github.com/golang/protobuf/proto
${GOPATH}/bin/govendor fetch -v +missing
#libjpeg-turbo
generate:
go get -u github.com/gogo/protobuf/proto
go get -u github.com/gogo/protobuf/protoc-gen-gogo
go get -u github.com/gogo/protobuf/gogoproto
go get -u github.com/gogo/protobuf/protoc-gen-gofast
go get -u github.com/gogo/protobuf/protoc-gen-gogofaster
go get -u github.com/golang/protobuf/proto
go get -u github.com/mailru/easyjson
protoc --gogofaster_out=. --proto_path=../../:. subsys/redis/app_token_data.proto
go-bindata -nomemcopy -ignore .DS_Store -prefix asset/static -o bind/static/data.go -pkg static asset/static/...
go-bindata -nomemcopy -ignore .DS_Store -prefix asset/template -o bind/template/data.go -pkg template asset/template/...
#${GOPATH}/bin/ffjson subsys/http/iface/rest.go
${GOPATH}/bin/easyjson subsys/http/iface/rest.go
# go-bindata -debug -nomemcopy -ignore .DS_Store -prefix asset/static -o bind/static/data.go -pkg static asset/static/...
# go-bindata -debug -nomemcopy -ignore .DS_Store -prefix asset/template -o bind/template/data.go -pkg template asset/template/...
strip:
upx rooibos
# Installs our project: copies binaries
install:
go install ${LDFLAGS}
# Cleans our project: deletes binaries
clean:
if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi
.PHONY: clean install

98
README.md Normal file
View File

@ -0,0 +1,98 @@
![alt tag](https://upload.wikimedia.org/wikipedia/commons/2/23/Golang.png)
[![Build Status](https://travis-ci.org/Massad/gin-boilerplate.svg?branch=master)](https://travis-ci.org/Massad/gin-boilerplate)
[![Join the chat at https://gitter.im/Massad/gin-boilerplate](https://badges.gitter.im/Massad/gin-boilerplate.svg)](https://gitter.im/Massad/gin-boilerplate?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Welcome to **Golang Gin boilerplate**!
The fastest way to deploy a restful api's with [Gin Framework](https://gin-gonic.github.io/gin/) with a structured project that defaults to **PostgreSQL** database and **Redis** as the session storage.
## Configured with
* [go-gorp](github.com/go-gorp/gorp): Go Relational Persistence
* [RedisStore](https://github.com/gin-gonic/contrib/tree/master/sessions): Gin middleware for session management with multi-backend support (currently cookie, Redis).
* Built-in **CORS Middleware**
* Feature **PostgreSQL 9.4** JSON queries
* Unit test
### Installation
```
$ go get github.com/Massad/gin-boilerplate
```
```
$ cd $GOPATH/src/github.com/Massad/gin-boilerplate
```
```
$ go get -t -v ./...
```
> Sometimes you need to get this package manually
```
$ go get github.com/bmizerany/assert
```
You will find the **database.sql** in `db/database.sql`
And you can import the postgres database using this command:
```
$ psql -U postgres -h localhost < ./db/database.sql
```
## Running Your Application
```
$ go run *.go
```
## Building Your Application
```
$ go build -v
```
```
$ ./gin-boilerplate
```
## Testing Your Application
```
$ go test -v ./tests/*
```
## Import Postman Collection (API's)
You can import from this [link](https://www.getpostman.com/collections/ac0680f90961bafd5de7). If you don't have **Postman**, check this link [https://www.getpostman.com](https://www.getpostman.com/)
## Contribution
You are welcome to contribute to keep it up to date and always improving!
If you have any question or need help, drop a message at [https://gitter.im/Massad/gin-boilerplate](https://gitter.im/Massad/gin-boilerplate)
---
## License
(The MIT License)
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,12 @@
<svg version="1.1" id="loader-1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
width="40px" height="40px" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
<path fill="#eb3c6a" d="M43.935,25.145c0-10.318-8.364-18.683-18.683-18.683c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615c8.072,0,14.615,6.543,14.615,14.615H43.935z">
<animateTransform attributeType="xml"
attributeName="transform"
type="rotate"
from="0 25 25"
to="360 25 25"
dur="0.6s"
repeatCount="indefinite"/>
</path>
</svg>

After

Width:  |  Height:  |  Size: 603 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
asset/static/images/bug.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -0,0 +1,33 @@
define([
'require',
'jquery',
'svg!../../images/ajax-loader.svg',
'jquery.blockui'
], function (require,
$,
loadimg) {
"use strict";
return {
blockUI: function (item) {
$(item).block({
message: loadimg,
css: {
border: 'none',
padding: '0px',
width: '40px',
height: '40px',
backgroundColor: 'transparent'
},
overlayCSS: {
backgroundColor: '#fff',
opacity: 0.9,
cursor: 'wait'
}
});
}
,
unblockUI: function (item) {
$(item).unblock();
}
}
});

View File

@ -0,0 +1,102 @@
'use strict';
function dep(baseUrl) {
// Require.js allows us to configure shortcut alias
return {
baseUrl: baseUrl,
bundles: {
// "javascripts/common/export.min": [
// 'javascripts/common/enums',
// 'javascripts/common/routes'
// ],
"javascripts/common/mixed": [
'javascripts/common/tether.mixed',
'javascripts/common/toastr.mixed'
]
},
map: {
'*': {
tpl: 'https://cdnjs.cloudflare.com/ajax/libs/requirejs-tpl/0.0.2/tpl.min.js',
toastr: 'javascripts/common/toastr.mixed',
tether: 'javascripts/common/tether.mixed',
postcode: 'javascripts/common/postcode.mixed!',
},
'javascripts/common/toastr.mixed': {
'toastr': 'toastr'
},
'javascripts/common/tether.mixed': {
'tether': 'tether'
},
},
paths: {
text: 'https://cdnjs.cloudflare.com/ajax/libs/require-text/2.0.12/text.min',
svg: 'libs/requirejs-svg-0.0.1/svg.min',
css: 'https://cdnjs.cloudflare.com/ajax/libs/require-css/0.1.8/css.min',
json: 'https://cdnjs.cloudflare.com/ajax/libs/requirejs-plugins/1.0.3/json.min',
noext: 'https://cdnjs.cloudflare.com/ajax/libs/requirejs-plugins/1.0.3/noext.min',
slimscroll: 'https://cdnjs.cloudflare.com/ajax/libs/jQuery-slimScroll/1.3.8/jquery.slimscroll.min',
jquery: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min',
'jquery.form': 'https://cdnjs.cloudflare.com/ajax/libs/jquery.form/3.51/jquery.form.min',
'jquery.blockui': 'https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min',
underscore: 'https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min',
'underscore.string': 'https://cdnjs.cloudflare.com/ajax/libs/underscore.string/3.3.4/underscore.string.min',
toastr: 'https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.3/toastr.min',
bootstrap: 'https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/js/bootstrap',
domReady: 'https://cdnjs.cloudflare.com/ajax/libs/require-domReady/2.0.1/domReady.min',
backbone: 'https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min',
'backbone.paginator': 'https://cdnjs.cloudflare.com/ajax/libs/backbone.paginator/2.0.5/backbone.paginator.min',
'backbone.bootstrapModal': 'libs/backbone-bootstrap-modal/backbone-bootstrap-modal',
'backbone.computedfields': 'libs/backbone-computedfields-0.0.11/backbone.computedfields.min',
moment: 'https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.16.0/moment.min',
tether: 'https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether',
'autoNumeric': 'https://cdnjs.cloudflare.com/ajax/libs/autonumeric/1.9.46/autoNumeric.min',
'browser-update': 'https://browser-update.org/update.min',
},
// scripts that do not call define() to register a module
shim: {
bootstrap: {
deps: ['jquery', 'tether'],
// exports: "$.fn.tooltip"
},
slimscroll: {
deps: ['jquery'],
exports: "$.fn.slimScroll"
},
underscore: {
exports: '_'
},
backbone: {
deps: [
'underscore',
'jquery'
],
exports: 'Backbone'
},
'jquery.form': {
deps: ['jquery'],
exports: '$.fn.ajaxSubmit'
},
toastr: {
deps: [
'css!https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.3/toastr.min'
]
},
'backbone.computedfields': {
deps: [
'backbone',
],
exports: 'Backbone.ComputedFields',
},
'ion.rangeSlider': {
deps: [
'jquery',
'css!https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.1.4/css/ion.rangeSlider.min',
'css!https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.1.4/css/ion.rangeSlider.skinFlat.min'
],
exports: '$.fn.ionRangeSlider'
}
}
};
};

View File

@ -0,0 +1,34 @@
define(['require', 'domReady', 'jquery', 'bootstrap', 'slimscroll'], function (require, domReady, $, bootstrap) {
"use strict";
// Slimscroll
$('.slimscroll').slimscroll({
height: "100%",
color: "#ccc",
distance: "0",
opacity: 0.3,
allowPageScroll: true,
borderRadius: "0",
railBorderRadius: "0"
});
// Makes .page-inner height same as .page-sidebar height
var sidebarAndContentHeight = function () {
var content = $('.page-inner'),
sidebar = $('.page-sidebar'),
body = $('body'),
height = $(window).height();
if (height >= content.height()) {
content.attr('style', 'min-height:' + height + 'px !important');
}
};
domReady(function () {
sidebarAndContentHeight();
$(window).on('resize', sidebarAndContentHeight);
window.$buoop = {vs: {i: 9, f: -2, o: -2, s: 6, c: -2}, unsecure: true, api: 4};
require(['browser-update']);
});
});

View File

@ -0,0 +1,26 @@
define('javascripts/common/tether.mixed',['tether'], function (tether) {
"use strict";
window.Tether=tether;
return tether;
});
define('javascripts/common/toastr.mixed',['toastr'], function (toastr) {
"use strict";
toastr.options = {
closeButton: true,
debug: false,
newestOnTop: true,
progressBar: false,
positionClass: 'toast-top-right',
preventDuplicates: false,
onclick: null,
showDuration: '300',
hideDuration: '1000',
timeOut: '5000',
extendedTimeOut: '1000',
showEasing: 'swing',
hideEasing: 'linear',
showMethod: 'fadeIn',
hideMethod: 'fadeOut'
};
return toastr;
});

View File

@ -0,0 +1,20 @@
define(['jquery', 'underscore', 'backbone.bootstrapModal', 'tpl!views/widgets/modal'], function ($, _, Modal, template) {
"use strict";
return Modal.extend({
initialize: function (options) {
this.options = _.extend({
title: null,
okText: 'OK',
focusOk: true,
okCloses: false,
cancelText: 'Cancel',
showFooter: true,
allowCancel: true,
escape: true,
animate: true,
template: template,
enterTriggersOk: false
}, options);
}
});
});

View File

@ -0,0 +1,284 @@
/**
* Bootstrap Modal wrapper for use with Backbone.
*
* Takes care of instantiation, manages multiple modals,
* adds several options and removes the element from the DOM when closed
*
* @author Charles Davison <charlie@powmedia.co.uk>
*
* Events:
* shown: Fired when the modal has finished animating in
* hidden: Fired when the modal has finished animating out
* cancel: The user dismissed the modal
* ok: The user clicked OK
*/
define(['jquery', 'underscore', 'backbone'], function ($, _, Backbone) {
//Set custom template settings
var _interpolateBackup = _.templateSettings;
_.templateSettings = {
interpolate: /\{\{(.+?)\}\}/g,
evaluate: /<%([\s\S]+?)%>/g
};
var template = _.template('\
<div class="modal-dialog"><div class="modal-content">\
<% if (title) { %>\
<div class="modal-header">\
<% if (allowCancel) { %>\
<a class="close">&times;</a>\
<% } %>\
<h4>{{title}}</h4>\
</div>\
<% } %>\
<div class="modal-body">{{content}}</div>\
<% if (showFooter) { %>\
<div class="modal-footer">\
<% if (allowCancel) { %>\
<% if (cancelText) { %>\
<a href="#" class="btn cancel">{{cancelText}}</a>\
<% } %>\
<% } %>\
<a href="#" class="btn ok btn-primary">{{okText}}</a>\
</div>\
<% } %>\
</div></div>\
');
//Reset to users' template settings
_.templateSettings = _interpolateBackup;
var Modal = Backbone.View.extend({
className: 'modal',
events: {
'click .close': function(event) {
event.preventDefault();
this.trigger('cancel');
if (this.options.content && this.options.content.trigger) {
this.options.content.trigger('cancel', this);
}
},
'click .cancel': function(event) {
event.preventDefault();
this.trigger('cancel');
if (this.options.content && this.options.content.trigger) {
this.options.content.trigger('cancel', this);
}
},
'click .ok': function(event) {
event.preventDefault();
this.trigger('ok');
if (this.options.content && this.options.content.trigger) {
this.options.content.trigger('ok', this);
}
if (this.options.okCloses) {
this.close();
}
},
'keypress': function(event) {
if (this.options.enterTriggersOk && event.which == 13) {
event.preventDefault();
this.trigger('ok');
if (this.options.content && this.options.content.trigger) {
this.options.content.trigger('ok', this);
}
if (this.options.okCloses) {
this.close();
}
}
}
},
/**
* Creates an instance of a Bootstrap Modal
*
* @see http://twitter.github.com/bootstrap/javascript.html#modals
*
* @param {Object} options
* @param {String|View} [options.content] Modal content. Default: none
* @param {String} [options.title] Title. Default: none
* @param {String} [options.okText] Text for the OK button. Default: 'OK'
* @param {String} [options.cancelText] Text for the cancel button. Default: 'Cancel'. If passed a falsey value, the button will be removed
* @param {Boolean} [options.allowCancel Whether the modal can be closed, other than by pressing OK. Default: true
* @param {Boolean} [options.escape] Whether the 'esc' key can dismiss the modal. Default: true, but false if options.cancellable is true
* @param {Boolean} [options.animate] Whether to animate in/out. Default: false
* @param {Function} [options.template] Compiled underscore template to override the default one
* @param {Boolean} [options.enterTriggersOk] Whether the 'enter' key will trigger OK. Default: false
*/
initialize: function(options) {
this.options = _.extend({
title: null,
okText: 'OK',
focusOk: true,
okCloses: true,
cancelText: 'Cancel',
showFooter: true,
allowCancel: true,
escape: true,
animate: false,
template: template,
enterTriggersOk: false
}, options);
},
/**
* Creates the DOM element
*
* @api private
*/
render: function() {
var $el = this.$el,
options = this.options,
content = options.content;
//Create the modal container
$el.html(options.template(options));
var $content = this.$content = $el.find('.modal-body')
//Insert the main content if it's a view
if (content && content.$el) {
content.render();
$el.find('.modal-body').html(content.$el);
}
if (options.animate) $el.addClass('fade');
this.isRendered = true;
return this;
},
/**
* Renders and shows the modal
*
* @param {Function} [cb] Optional callback that runs only when OK is pressed.
*/
open: function(cb) {
if (!this.isRendered) this.render();
var self = this,
$el = this.$el;
//Create it
$el.modal(_.extend({
keyboard: this.options.allowCancel,
backdrop: this.options.allowCancel ? true : 'static'
}, this.options.modalOptions));
//Focus OK button
$el.one('shown.bs.modal', function() {
if (self.options.focusOk) {
$el.find('.btn.ok').focus();
}
if (self.options.content && self.options.content.trigger) {
self.options.content.trigger('shown', self);
}
self.trigger('shown');
});
//Adjust the modal and backdrop z-index; for dealing with multiple modals
var numModals = Modal.count,
$backdrop = $('.modal-backdrop:eq('+numModals+')'),
backdropIndex = parseInt($backdrop.css('z-index'),10),
elIndex = parseInt($backdrop.css('z-index'), 10);
$backdrop.css('z-index', backdropIndex + numModals);
this.$el.css('z-index', elIndex + numModals);
if (this.options.allowCancel) {
$backdrop.one('click', function() {
if (self.options.content && self.options.content.trigger) {
self.options.content.trigger('cancel', self);
}
self.trigger('cancel');
});
$(document).one('keyup.dismiss.modal', function (e) {
e.which == 27 && self.trigger('cancel');
if (self.options.content && self.options.content.trigger) {
e.which == 27 && self.options.content.trigger('shown', self);
}
});
}
this.on('cancel', function() {
self.close();
});
Modal.count++;
//Run callback on OK if provided
if (cb) {
self.on('ok', cb);
}
return this;
},
/**
* Closes the modal
*/
close: function() {
var self = this,
$el = this.$el;
//Check if the modal should stay open
if (this._preventClose) {
this._preventClose = false;
return;
}
$el.one('hidden.bs.modal', function onHidden(e) {
// Ignore events propagated from interior objects, like bootstrap tooltips
if(e.target !== e.currentTarget){
return $el.one('hidden', onHidden);
}
self.remove();
if (self.options.content && self.options.content.trigger) {
self.options.content.trigger('hidden', self);
}
self.trigger('hidden');
});
$el.modal('hide');
Modal.count--;
},
/**
* Stop the modal from closing.
* Can be called from within a 'close' or 'ok' event listener.
*/
preventClose: function() {
this._preventClose = true;
}
}, {
//STATICS
//The number of modals on display
count: 0
});
return Modal;
});

View File

@ -0,0 +1,136 @@
// Backbone.ComputedFields, v0.0.10
// Copyright (c)2014 alexander.beletsky@gmail.com
// Distributed under MIT license
// https://github.com/alexanderbeletsky/backbone-computedfields
Backbone.ComputedFields = (function(Backbone, _){
var ComputedFields = function (model) {
this.model = model;
this._computedFields = [];
this.initialize();
};
_.extend(ComputedFields.prototype, {
initialize: function () {
_.bindAll(
this,
'_bindModelEvents',
'_computeFieldValue',
'_dependentFields',
'_isModelInitialized',
'_lookUpComputedFields',
'_thenComputedChanges',
'_thenDependentChanges',
'_toJSON',
'_wrapJSON',
'initialize'
);
this._lookUpComputedFields();
this._bindModelEvents();
this._wrapJSON();
},
_lookUpComputedFields: function () {
for (var obj in this.model.computed) {
var field = this.model.computed[obj];
if (field && (field.set || field.get)) {
this._computedFields.push({name: obj, field: field});
}
}
},
_bindModelEvents: function () {
_.each(this._computedFields, function (computedField) {
var fieldName = computedField.name;
var field = computedField.field;
var updateComputed = _.bind(function () {
var value = this._computeFieldValue(field);
this.model.set(fieldName, value, { skipChangeEvent: true });
}, this);
var updateDependent = _.bind(function (model, value, options) {
if (options && options.skipChangeEvent) {
return;
}
if (field.set) {
var fields = this._dependentFields(field.depends);
value = value || this.model.get(fieldName);
field.set.call(this.model, value, fields);
this.model.set(fields, options);
}
}, this);
this._thenDependentChanges(field.depends, updateComputed);
this._thenComputedChanges(fieldName, updateDependent);
if (this._isModelInitialized()) {
updateComputed();
}
}, this);
},
_isModelInitialized: function () {
return !_.isEmpty(this.model.attributes);
},
_thenDependentChanges: function (depends, callback) {
_.each(depends, function (name) {
if (typeof (name) === 'string') {
this.model.on('change:' + name, callback);
}
if (typeof (name) === 'function') {
name.call(this.model, callback);
}
}, this);
},
_thenComputedChanges: function (fieldName, callback) {
this.model.on('change:' + fieldName, callback);
},
_wrapJSON: function () {
this.model.toJSON = _.wrap(this.model.toJSON, this._toJSON);
},
_toJSON: function (toJSON) {
var args = Array.prototype.slice.call(arguments, 1),
attributes = toJSON.apply(this.model, args),
strip = !!(args[0] || {}).computedFields;
var stripped = strip ? {} : _.reduce(this._computedFields, function (memo, computed) {
if (computed.field.toJSON === false) {
memo.push(computed.name);
}
return memo;
},[]);
return _.omit(attributes, stripped);
},
_computeFieldValue: function (computedField) {
if (computedField && computedField.get) {
var fields = this._dependentFields(computedField.depends);
return computedField.get.call(this.model, fields);
}
},
_dependentFields: function (depends) {
return _.reduce(depends, function (memo, field) {
memo[field] = this.model.get(field);
return memo;
}, {}, this);
}
});
return ComputedFields;
})(Backbone, _);

View File

@ -0,0 +1 @@
Backbone.ComputedFields=function(a,b){var c=function(a){this.model=a,this._computedFields=[],this.initialize()};return b.extend(c.prototype,{initialize:function(){b.bindAll(this,"_bindModelEvents","_computeFieldValue","_dependentFields","_isModelInitialized","_lookUpComputedFields","_thenComputedChanges","_thenDependentChanges","_toJSON","_wrapJSON","initialize"),this._lookUpComputedFields(),this._bindModelEvents(),this._wrapJSON()},_lookUpComputedFields:function(){for(var a in this.model.computed){var b=this.model.computed[a];b&&(b.set||b.get)&&this._computedFields.push({name:a,field:b})}},_bindModelEvents:function(){b.each(this._computedFields,function(a){var c=a.name,d=a.field,e=b.bind(function(){var a=this._computeFieldValue(d);this.model.set(c,a,{skipChangeEvent:!0})},this),f=b.bind(function(a,b,e){if((!e||!e.skipChangeEvent)&&d.set){var f=this._dependentFields(d.depends);b=b||this.model.get(c),d.set.call(this.model,b,f),this.model.set(f,e)}},this);this._thenDependentChanges(d.depends,e),this._thenComputedChanges(c,f),this._isModelInitialized()&&e()},this)},_isModelInitialized:function(){return!b.isEmpty(this.model.attributes)},_thenDependentChanges:function(a,c){b.each(a,function(a){"string"==typeof a&&this.model.on("change:"+a,c),"function"==typeof a&&a.call(this.model,c)},this)},_thenComputedChanges:function(a,b){this.model.on("change:"+a,b)},_wrapJSON:function(){this.model.toJSON=b.wrap(this.model.toJSON,this._toJSON)},_toJSON:function(a){var c=Array.prototype.slice.call(arguments,1),d=a.apply(this.model,c),e=!!(c[0]||{}).computedFields,f=e?{}:b.reduce(this._computedFields,function(a,b){return b.field.toJSON===!1&&a.push(b.name),a},[]);return b.omit(d,f)},_computeFieldValue:function(a){if(a&&a.get){var b=this._dependentFields(a.depends);return a.get.call(this.model,b)}},_dependentFields:function(a){return b.reduce(a,function(a,b){return a[b]=this.model.get(b),a},{},this)}}),c}(Backbone,_);

View File

@ -0,0 +1,75 @@
/*jslint regexp: true */
/*global define */
define(['module', 'text'], function (module, textPlugin) {
'use strict';
var svg = {
buildMap: {},
sprite_id: 'requirejs-svg-sprite',
sprite: null,
extractGraphicAsSymbol: function(document, svgText) {
var div = document.createElement('div');
div.innerHTML = svgText;
var element = div.querySelector('svg');
var id = element.getAttribute('id');
var viewBox = element.getAttribute('viewbox') || element.getAttribute('viewBox');
return svg.createSymbol(document, id, element, viewBox);
},
createSymbol: function(document, id, element, viewBox) {
var symbol = document.createElementNS('http://www.w3.org/2000/svg', 'symbol');
while (element.firstChild) {
symbol.appendChild(element.firstChild);
}
typeof id === 'string' && symbol.setAttribute('id', id);
typeof viewBox === 'string' && symbol.setAttribute('viewBox', viewBox);
return symbol;
},
createSprite: function(document) {
svg.sprite = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.sprite.setAttribute('style', 'display: none');
svg.sprite.setAttribute('id', this.sprite_id);
return svg.sprite;
},
appendSprite: function(content) {
if (! svg.sprite) {
svg.createSprite(document);
document.body.appendChild(svg.sprite);
}
svg.sprite.appendChild( svg.extractGraphicAsSymbol(document, content) );
},
finishLoad: function(name, onLoad, config) {
return function(content) {
if (config && !config.isBuild) {
svg.appendSprite(content);
}
else {
svg.buildMap[name] = content;
}
return onLoad(content);
};
},
load: function(name, req, onLoad, config) {
textPlugin.load(name + '!strip', req, svg.finishLoad(name, onLoad, config), config);
},
write: function (pluginName, moduleName, write/*, config*/) {
if (svg.buildMap.hasOwnProperty(moduleName)) {
var content = textPlugin.jsEscape(svg.buildMap[moduleName]);
write.asModule(pluginName + "!" + moduleName,
"define(['" + pluginName + "'], function (svg) { svg.appendSprite('" + content + "');});\n"
);
}
}
};
return svg;
});

View File

@ -0,0 +1,3 @@
define(["module","text"],function(g,f){var b={b:{},j:"requirejs-svg-sprite",a:null,h:function(a,e){var c=a.createElement("div");c.innerHTML=e;var c=c.querySelector("svg"),d=c.getAttribute("id"),f=c.getAttribute("viewbox")||c.getAttribute("viewBox");return b.g(a,d,c,f)},g:function(a,b,c,d){for(a=a.createElementNS("http://www.w3.org/2000/svg","symbol");c.firstChild;)a.appendChild(c.firstChild);"string"===typeof b&&a.setAttribute("id",b);"string"===typeof d&&a.setAttribute("viewBox",d);return a},f:function(a){b.a=
a.createElementNS("http://www.w3.org/2000/svg","svg");b.a.setAttribute("style","display: none");b.a.setAttribute("id",this.j);return b.a},c:function(a){b.a||(b.f(document),document.body.appendChild(b.a));b.a.appendChild(b.h(document,a))},i:function(a,e,c){return function(d){c&&!c.m?b.c(d):b.b[a]=d;return e(d)}},load:function(a,e,c,d){f.load(a+"!strip",e,b.i(a,c,d),d)},write:function(a,e,c){if(b.b.hasOwnProperty(e)){var d=f.o(b.b[e]);c.l(a+"!"+e,"define(['"+a+"'], function (svg) { svg.appendSprite('"+
d+"');});\n")}}};return b});

View File

@ -0,0 +1,484 @@
.select2-container {
box-sizing: border-box;
display: inline-block;
margin: 0;
position: relative;
vertical-align: middle; }
.select2-container .select2-selection--single {
box-sizing: border-box;
cursor: pointer;
display: block;
height: 28px;
user-select: none;
-webkit-user-select: none; }
.select2-container .select2-selection--single .select2-selection__rendered {
display: block;
padding-left: 8px;
padding-right: 20px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap; }
.select2-container .select2-selection--single .select2-selection__clear {
position: relative; }
.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered {
padding-right: 8px;
padding-left: 20px; }
.select2-container .select2-selection--multiple {
box-sizing: border-box;
cursor: pointer;
display: block;
min-height: 32px;
user-select: none;
-webkit-user-select: none; }
.select2-container .select2-selection--multiple .select2-selection__rendered {
display: inline-block;
overflow: hidden;
padding-left: 8px;
text-overflow: ellipsis;
white-space: nowrap; }
.select2-container .select2-search--inline {
float: left; }
.select2-container .select2-search--inline .select2-search__field {
box-sizing: border-box;
border: none;
font-size: 100%;
margin-top: 5px;
padding: 0; }
.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button {
-webkit-appearance: none; }
.select2-dropdown {
background-color: white;
border: 1px solid #aaa;
border-radius: 4px;
box-sizing: border-box;
display: block;
position: absolute;
left: -100000px;
width: 100%;
z-index: 1051; }
.select2-results {
display: block; }
.select2-results__options {
list-style: none;
margin: 0;
padding: 0; }
.select2-results__option {
padding: 6px;
user-select: none;
-webkit-user-select: none; }
.select2-results__option[aria-selected] {
cursor: pointer; }
.select2-container--open .select2-dropdown {
left: 0; }
.select2-container--open .select2-dropdown--above {
border-bottom: none;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0; }
.select2-container--open .select2-dropdown--below {
border-top: none;
border-top-left-radius: 0;
border-top-right-radius: 0; }
.select2-search--dropdown {
display: block;
padding: 4px; }
.select2-search--dropdown .select2-search__field {
padding: 4px;
width: 100%;
box-sizing: border-box; }
.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button {
-webkit-appearance: none; }
.select2-search--dropdown.select2-search--hide {
display: none; }
.select2-close-mask {
border: 0;
margin: 0;
padding: 0;
display: block;
position: fixed;
left: 0;
top: 0;
min-height: 100%;
min-width: 100%;
height: auto;
width: auto;
opacity: 0;
z-index: 99;
background-color: #fff;
filter: alpha(opacity=0); }
.select2-hidden-accessible {
border: 0 !important;
clip: rect(0 0 0 0) !important;
height: 1px !important;
margin: -1px !important;
overflow: hidden !important;
padding: 0 !important;
position: absolute !important;
width: 1px !important; }
.select2-container--default .select2-selection--single {
background-color: #fff;
border: 1px solid #aaa;
border-radius: 4px; }
.select2-container--default .select2-selection--single .select2-selection__rendered {
color: #444;
line-height: 28px; }
.select2-container--default .select2-selection--single .select2-selection__clear {
cursor: pointer;
float: right;
font-weight: bold; }
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #999; }
.select2-container--default .select2-selection--single .select2-selection__arrow {
height: 26px;
position: absolute;
top: 1px;
right: 1px;
width: 20px; }
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-color: #888 transparent transparent transparent;
border-style: solid;
border-width: 5px 4px 0 4px;
height: 0;
left: 50%;
margin-left: -4px;
margin-top: -2px;
position: absolute;
top: 50%;
width: 0; }
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear {
float: left; }
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow {
left: 1px;
right: auto; }
.select2-container--default.select2-container--disabled .select2-selection--single {
background-color: #eee;
cursor: default; }
.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear {
display: none; }
.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
border-color: transparent transparent #888 transparent;
border-width: 0 4px 5px 4px; }
.select2-container--default .select2-selection--multiple {
background-color: white;
border: 1px solid #aaa;
border-radius: 4px;
cursor: text; }
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
box-sizing: border-box;
list-style: none;
margin: 0;
padding: 0 5px;
width: 100%; }
.select2-container--default .select2-selection--multiple .select2-selection__rendered li {
list-style: none; }
.select2-container--default .select2-selection--multiple .select2-selection__placeholder {
color: #999;
margin-top: 5px;
float: left; }
.select2-container--default .select2-selection--multiple .select2-selection__clear {
cursor: pointer;
float: right;
font-weight: bold;
margin-top: 5px;
margin-right: 10px; }
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background-color: #e4e4e4;
border: 1px solid #aaa;
border-radius: 4px;
cursor: default;
float: left;
margin-right: 5px;
margin-top: 5px;
padding: 0 5px; }
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #999;
cursor: pointer;
display: inline-block;
font-weight: bold;
margin-right: 2px; }
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
color: #333; }
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline {
float: right; }
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
margin-left: 5px;
margin-right: auto; }
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
margin-left: 2px;
margin-right: auto; }
.select2-container--default.select2-container--focus .select2-selection--multiple {
border: solid black 1px;
outline: 0; }
.select2-container--default.select2-container--disabled .select2-selection--multiple {
background-color: #eee;
cursor: default; }
.select2-container--default.select2-container--disabled .select2-selection__choice__remove {
display: none; }
.select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple {
border-top-left-radius: 0;
border-top-right-radius: 0; }
.select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0; }
.select2-container--default .select2-search--dropdown .select2-search__field {
border: 1px solid #aaa; }
.select2-container--default .select2-search--inline .select2-search__field {
background: transparent;
border: none;
outline: 0;
box-shadow: none;
-webkit-appearance: textfield; }
.select2-container--default .select2-results > .select2-results__options {
max-height: 200px;
overflow-y: auto; }
.select2-container--default .select2-results__option[role=group] {
padding: 0; }
.select2-container--default .select2-results__option[aria-disabled=true] {
color: #999; }
.select2-container--default .select2-results__option[aria-selected=true] {
background-color: #ddd; }
.select2-container--default .select2-results__option .select2-results__option {
padding-left: 1em; }
.select2-container--default .select2-results__option .select2-results__option .select2-results__group {
padding-left: 0; }
.select2-container--default .select2-results__option .select2-results__option .select2-results__option {
margin-left: -1em;
padding-left: 2em; }
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -2em;
padding-left: 3em; }
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -3em;
padding-left: 4em; }
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -4em;
padding-left: 5em; }
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -5em;
padding-left: 6em; }
.select2-container--default .select2-results__option--highlighted[aria-selected] {
background-color: #5897fb;
color: white; }
.select2-container--default .select2-results__group {
cursor: default;
display: block;
padding: 6px; }
.select2-container--classic .select2-selection--single {
background-color: #f7f7f7;
border: 1px solid #aaa;
border-radius: 4px;
outline: 0;
background-image: -webkit-linear-gradient(top, white 50%, #eeeeee 100%);
background-image: -o-linear-gradient(top, white 50%, #eeeeee 100%);
background-image: linear-gradient(to bottom, white 50%, #eeeeee 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); }
.select2-container--classic .select2-selection--single:focus {
border: 1px solid #5897fb; }
.select2-container--classic .select2-selection--single .select2-selection__rendered {
color: #444;
line-height: 28px; }
.select2-container--classic .select2-selection--single .select2-selection__clear {
cursor: pointer;
float: right;
font-weight: bold;
margin-right: 10px; }
.select2-container--classic .select2-selection--single .select2-selection__placeholder {
color: #999; }
.select2-container--classic .select2-selection--single .select2-selection__arrow {
background-color: #ddd;
border: none;
border-left: 1px solid #aaa;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
height: 26px;
position: absolute;
top: 1px;
right: 1px;
width: 20px;
background-image: -webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0); }
.select2-container--classic .select2-selection--single .select2-selection__arrow b {
border-color: #888 transparent transparent transparent;
border-style: solid;
border-width: <