Restructure of lib directory.
This commit is contained in:
parent
e27664ec1c
commit
c8b276ba38
25 changed files with 0 additions and 15369 deletions
|
@ -1,66 +0,0 @@
|
||||||
$ = jQuery.sub()
|
|
||||||
|
|
||||||
class App.Com
|
|
||||||
_instance = undefined # Must be declared here to force the closure on the class
|
|
||||||
@ajax: (args) -> # Must be a static method
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
|
|
||||||
_instance.ajax(args)
|
|
||||||
_instance
|
|
||||||
|
|
||||||
# The actual Singleton class
|
|
||||||
class _Singleton
|
|
||||||
defaults:
|
|
||||||
contentType: 'application/json'
|
|
||||||
dataType: 'json'
|
|
||||||
processData: false
|
|
||||||
headers: {'X-Requested-With': 'XMLHttpRequest'}
|
|
||||||
cache: false
|
|
||||||
async: true
|
|
||||||
|
|
||||||
queue_list: {}
|
|
||||||
count: 0
|
|
||||||
|
|
||||||
constructor: (@args) ->
|
|
||||||
|
|
||||||
# bindings
|
|
||||||
$('body').bind( 'ajaxSend', =>
|
|
||||||
@_show_spinner()
|
|
||||||
).bind( 'ajaxComplete', =>
|
|
||||||
@_hide_spinner()
|
|
||||||
)
|
|
||||||
|
|
||||||
# show error messages
|
|
||||||
$('body').bind( 'ajaxError', ( e, jqxhr, settings, exception ) ->
|
|
||||||
status = jqxhr.status
|
|
||||||
detail = jqxhr.responseText
|
|
||||||
if !status && !detail
|
|
||||||
detail = 'General communication error, maybe internet is not available!'
|
|
||||||
new App.ErrorModal(
|
|
||||||
message: 'StatusCode: ' + status
|
|
||||||
detail: detail
|
|
||||||
close: true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
ajax: (params, defaults) ->
|
|
||||||
data = $.extend({}, @defaults, defaults, params)
|
|
||||||
if params['id']
|
|
||||||
if @queue_list[ params['id'] ]
|
|
||||||
@queue_list[ params['id'] ].abort()
|
|
||||||
@queue_list[ params['id'] ] = $.ajax( data )
|
|
||||||
else
|
|
||||||
$.ajax( data )
|
|
||||||
|
|
||||||
# console.log('AJAX', params['url'] )
|
|
||||||
|
|
||||||
_show_spinner: =>
|
|
||||||
@count++
|
|
||||||
$('.spinner').show()
|
|
||||||
|
|
||||||
_hide_spinner: =>
|
|
||||||
@count--
|
|
||||||
if @count == 0
|
|
||||||
$('.spinner').hide()
|
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
$ = jQuery.sub()
|
|
||||||
|
|
||||||
class App.Auth
|
|
||||||
|
|
||||||
@login: (params) ->
|
|
||||||
console.log 'login(...)', params
|
|
||||||
App.Com.ajax(
|
|
||||||
id: 'login',
|
|
||||||
type: 'POST',
|
|
||||||
url: '/signin',
|
|
||||||
data: JSON.stringify(params.data),
|
|
||||||
success: (data, status, xhr) =>
|
|
||||||
|
|
||||||
# clear store
|
|
||||||
App.Store.clear('all')
|
|
||||||
|
|
||||||
# execute callback
|
|
||||||
params.success(data, status, xhr)
|
|
||||||
|
|
||||||
error: (xhr, statusText, error) =>
|
|
||||||
params.error(xhr, statusText, error)
|
|
||||||
)
|
|
||||||
|
|
||||||
@loginCheck: ->
|
|
||||||
console.log 'loginCheck(...)'
|
|
||||||
App.Com.ajax(
|
|
||||||
id: 'login_check',
|
|
||||||
async: false,
|
|
||||||
type: 'GET',
|
|
||||||
url: '/signshow',
|
|
||||||
success: (data, status, xhr) =>
|
|
||||||
console.log 'logincheck:success', data
|
|
||||||
|
|
||||||
# if session is not valid
|
|
||||||
if data.error
|
|
||||||
|
|
||||||
# update config
|
|
||||||
for key, value of data.config
|
|
||||||
window.Config[key] = value
|
|
||||||
|
|
||||||
# empty session
|
|
||||||
window.Session = {}
|
|
||||||
|
|
||||||
# update websocked auth info
|
|
||||||
App.WebSocket.auth()
|
|
||||||
|
|
||||||
# rebuild navbar with new navbar items
|
|
||||||
App.Event.trigger 'navrebuild'
|
|
||||||
|
|
||||||
return false;
|
|
||||||
|
|
||||||
# set avatar
|
|
||||||
if !data.session.image
|
|
||||||
data.session.image = 'http://placehold.it/48x48'
|
|
||||||
|
|
||||||
# update config
|
|
||||||
for key, value of data.config
|
|
||||||
window.Config[key] = value
|
|
||||||
|
|
||||||
# store user data
|
|
||||||
for key, value of data.session
|
|
||||||
window.Session[key] = value
|
|
||||||
|
|
||||||
# update websocked auth info
|
|
||||||
App.WebSocket.auth()
|
|
||||||
|
|
||||||
# refresh/load default collections
|
|
||||||
for key, value of data.default_collections
|
|
||||||
App.Collection.reset( type: key, data: value )
|
|
||||||
|
|
||||||
# rebuild navbar with new navbar items
|
|
||||||
App.Event.trigger 'navrebuild', data.session
|
|
||||||
|
|
||||||
# rebuild navbar with updated ticket count of overviews
|
|
||||||
App.Event.trigger 'navupdate_remote'
|
|
||||||
|
|
||||||
error: (xhr, statusText, error) =>
|
|
||||||
console.log 'loginCheck:error'#, error, statusText, xhr.statusCode
|
|
||||||
|
|
||||||
# empty session
|
|
||||||
window.Session = {}
|
|
||||||
|
|
||||||
# clear store
|
|
||||||
App.Store.clear('all')
|
|
||||||
|
|
||||||
# update websocked auth info
|
|
||||||
App.WebSocket.auth()
|
|
||||||
)
|
|
||||||
|
|
||||||
@logout: ->
|
|
||||||
console.log 'logout(...)'
|
|
||||||
App.Com.ajax(
|
|
||||||
id: 'logout',
|
|
||||||
type: 'DELETE',
|
|
||||||
url: '/signout',
|
|
||||||
success: =>
|
|
||||||
|
|
||||||
# update websocked auth info
|
|
||||||
App.WebSocket.auth()
|
|
||||||
|
|
||||||
# clear store
|
|
||||||
App.Store.clear('all')
|
|
||||||
|
|
||||||
error: (xhr, statusText, error) =>
|
|
||||||
|
|
||||||
# update websocked auth info
|
|
||||||
App.WebSocket.auth()
|
|
||||||
)
|
|
|
@ -1,179 +0,0 @@
|
||||||
/*!
|
|
||||||
* linkify - v0.3 - 6/27/2009
|
|
||||||
* http://benalman.com/code/test/js-linkify/
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009 "Cowboy" Ben Alman
|
|
||||||
* Licensed under the MIT license
|
|
||||||
* http://benalman.com/about/license/
|
|
||||||
*
|
|
||||||
* Some regexps adapted from http://userscripts.org/scripts/review/7122
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Turn text into linkified html.
|
|
||||||
//
|
|
||||||
// var html = linkify( text, options );
|
|
||||||
//
|
|
||||||
// options:
|
|
||||||
//
|
|
||||||
// callback (Function) - default: undefined - if defined, this will be called
|
|
||||||
// for each link- or non-link-chunk with two arguments, text and href. If the
|
|
||||||
// chunk is non-link, href will be omitted.
|
|
||||||
//
|
|
||||||
// punct_regexp (RegExp | Boolean) - a RegExp that can be used to trim trailing
|
|
||||||
// punctuation from links, instead of the default.
|
|
||||||
//
|
|
||||||
// This is a work in progress, please let me know if (and how) it fails!
|
|
||||||
|
|
||||||
window.linkify = (function(){
|
|
||||||
var
|
|
||||||
SCHEME = "[a-z\\d.-]+://",
|
|
||||||
IPV4 = "(?:(?:[0-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.){3}(?:[0-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])",
|
|
||||||
HOSTNAME = "(?:(?:[^\\s!@#$%^&*()_=+[\\]{}\\\\|;:'\",.<>/?]+)\\.)+",
|
|
||||||
TLD = "(?:ac|ad|aero|ae|af|ag|ai|al|am|an|ao|aq|arpa|ar|asia|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|biz|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|cat|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|coop|com|co|cr|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|edu|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gov|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|info|int|in|io|iq|ir|is|it|je|jm|jobs|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mil|mk|ml|mm|mn|mobi|mo|mp|mq|mr|ms|mt|museum|mu|mv|mw|mx|my|mz|name|na|nc|net|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|org|pa|pe|pf|pg|ph|pk|pl|pm|pn|pro|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sy|sz|tc|td|tel|tf|tg|th|tj|tk|tl|tm|tn|to|tp|travel|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|xn--0zwm56d|xn--11b5bs3a9aj6g|xn--80akhbyknj4f|xn--9t4b11yi5a|xn--deba0ad|xn--g6w251d|xn--hgbk6aj7f53bba|xn--hlcj6aya9esc7a|xn--jxalpdlp|xn--kgbechtv|xn--zckzah|ye|yt|yu|za|zm|zw)",
|
|
||||||
HOST_OR_IP = "(?:" + HOSTNAME + TLD + "|" + IPV4 + ")",
|
|
||||||
PATH = "(?:[;/][^#?<>\\s]*)?",
|
|
||||||
QUERY_FRAG = "(?:\\?[^#<>\\s]*)?(?:#[^<>\\s]*)?",
|
|
||||||
URI1 = "\\b" + SCHEME + "[^<>\\s]+",
|
|
||||||
URI2 = "\\b" + HOST_OR_IP + PATH + QUERY_FRAG + "(?!\\w)",
|
|
||||||
|
|
||||||
MAILTO = "mailto:",
|
|
||||||
EMAIL = "(?:" + MAILTO + ")?[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@" + HOST_OR_IP + QUERY_FRAG + "(?!\\w)",
|
|
||||||
|
|
||||||
URI_RE = new RegExp( "(?:" + URI1 + "|" + URI2 + "|" + EMAIL + ")", "ig" ),
|
|
||||||
SCHEME_RE = new RegExp( "^" + SCHEME, "i" ),
|
|
||||||
|
|
||||||
quotes = {
|
|
||||||
"'": "`",
|
|
||||||
'>': '<',
|
|
||||||
')': '(',
|
|
||||||
']': '[',
|
|
||||||
'}': '{',
|
|
||||||
'»': '«',
|
|
||||||
'›': '‹'
|
|
||||||
},
|
|
||||||
|
|
||||||
default_options = {
|
|
||||||
callback: function( text, href ) {
|
|
||||||
// return href ? '<a href="' + href + '" title="' + href + '">' + text + '<\/a>' : text;
|
|
||||||
return href ? '<a href="' + href + '" title="' + href + '" target="_blank">' + text + '<\/a>' : text;
|
|
||||||
},
|
|
||||||
punct_regexp: /(?:[!?.,:;'"]|(?:&|&)(?:lt|gt|quot|apos|raquo|laquo|rsaquo|lsaquo);)$/
|
|
||||||
};
|
|
||||||
|
|
||||||
return function( txt, options ) {
|
|
||||||
options = options || {};
|
|
||||||
|
|
||||||
// me
|
|
||||||
txt = txt
|
|
||||||
.replace(/&/g, '&')
|
|
||||||
.replace(/"/g, '"')
|
|
||||||
.replace(/'/g, ''')
|
|
||||||
.replace(/</g, '<')
|
|
||||||
.replace(/>/g, '>');
|
|
||||||
// me
|
|
||||||
// Temp variables.
|
|
||||||
var arr,
|
|
||||||
i,
|
|
||||||
link,
|
|
||||||
href,
|
|
||||||
|
|
||||||
// Output HTML.
|
|
||||||
html = '',
|
|
||||||
|
|
||||||
// Store text / link parts, in order, for re-combination.
|
|
||||||
parts = [],
|
|
||||||
|
|
||||||
// Used for keeping track of indices in the text.
|
|
||||||
idx_prev,
|
|
||||||
idx_last,
|
|
||||||
idx,
|
|
||||||
link_last,
|
|
||||||
|
|
||||||
// Used for trimming trailing punctuation and quotes from links.
|
|
||||||
matches_begin,
|
|
||||||
matches_end,
|
|
||||||
quote_begin,
|
|
||||||
quote_end;
|
|
||||||
|
|
||||||
// Initialize options.
|
|
||||||
for ( i in default_options ) {
|
|
||||||
if ( options[ i ] === undefined ) {
|
|
||||||
options[ i ] = default_options[ i ];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find links.
|
|
||||||
while ( arr = URI_RE.exec( txt ) ) {
|
|
||||||
|
|
||||||
link = arr[0];
|
|
||||||
idx_last = URI_RE.lastIndex;
|
|
||||||
idx = idx_last - link.length;
|
|
||||||
|
|
||||||
// Not a link if preceded by certain characters.
|
|
||||||
if ( /[\/:]/.test( txt.charAt( idx - 1 ) ) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trim trailing punctuation.
|
|
||||||
do {
|
|
||||||
// If no changes are made, we don't want to loop forever!
|
|
||||||
link_last = link;
|
|
||||||
|
|
||||||
quote_end = link.substr( -1 )
|
|
||||||
quote_begin = quotes[ quote_end ];
|
|
||||||
|
|
||||||
// Ending quote character?
|
|
||||||
if ( quote_begin ) {
|
|
||||||
matches_begin = link.match( new RegExp( '\\' + quote_begin + '(?!$)', 'g' ) );
|
|
||||||
matches_end = link.match( new RegExp( '\\' + quote_end, 'g' ) );
|
|
||||||
|
|
||||||
// If quotes are unbalanced, remove trailing quote character.
|
|
||||||
if ( ( matches_begin ? matches_begin.length : 0 ) < ( matches_end ? matches_end.length : 0 ) ) {
|
|
||||||
link = link.substr( 0, link.length - 1 );
|
|
||||||
idx_last--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ending non-quote punctuation character?
|
|
||||||
if ( options.punct_regexp ) {
|
|
||||||
link = link.replace( options.punct_regexp, function(a){
|
|
||||||
idx_last -= a.length;
|
|
||||||
return '';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} while ( link.length && link !== link_last );
|
|
||||||
|
|
||||||
href = link;
|
|
||||||
|
|
||||||
// Add appropriate protocol to naked links.
|
|
||||||
if ( !SCHEME_RE.test( href ) ) {
|
|
||||||
href = ( href.indexOf( '@' ) !== -1 ? ( !href.indexOf( MAILTO ) ? '' : MAILTO )
|
|
||||||
: !href.indexOf( 'irc.' ) ? 'irc://'
|
|
||||||
: !href.indexOf( 'ftp.' ) ? 'ftp://'
|
|
||||||
: 'http://' )
|
|
||||||
+ href;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push preceding non-link text onto the array.
|
|
||||||
if ( idx_prev != idx ) {
|
|
||||||
parts.push([ txt.slice( idx_prev, idx ) ]);
|
|
||||||
idx_prev = idx_last;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push massaged link onto the array
|
|
||||||
parts.push([ link, href ]);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Push remaining non-link text onto the array.
|
|
||||||
parts.push([ txt.substr( idx_prev ) ]);
|
|
||||||
|
|
||||||
// Process the array items.
|
|
||||||
for ( i = 0; i < parts.length; i++ ) {
|
|
||||||
html += options.callback.apply( window, parts[i] );
|
|
||||||
}
|
|
||||||
|
|
||||||
// In case of catastrophic failure, return the original text;
|
|
||||||
return html || txt;
|
|
||||||
};
|
|
||||||
|
|
||||||
})();
|
|
100
app/assets/javascripts/app/lib/bootstrap-dropdown.js
vendored
100
app/assets/javascripts/app/lib/bootstrap-dropdown.js
vendored
|
@ -1,100 +0,0 @@
|
||||||
/* ============================================================
|
|
||||||
* bootstrap-dropdown.js v2.0.4
|
|
||||||
* http://twitter.github.com/bootstrap/javascript.html#dropdowns
|
|
||||||
* ============================================================
|
|
||||||
* Copyright 2012 Twitter, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
* ============================================================ */
|
|
||||||
|
|
||||||
|
|
||||||
!function ($) {
|
|
||||||
|
|
||||||
"use strict"; // jshint ;_;
|
|
||||||
|
|
||||||
|
|
||||||
/* DROPDOWN CLASS DEFINITION
|
|
||||||
* ========================= */
|
|
||||||
|
|
||||||
var toggle = '[data-toggle="dropdown"]'
|
|
||||||
, Dropdown = function (element) {
|
|
||||||
var $el = $(element).on('click.dropdown.data-api', this.toggle)
|
|
||||||
$('html').on('click.dropdown.data-api', function () {
|
|
||||||
$el.parent().removeClass('open')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Dropdown.prototype = {
|
|
||||||
|
|
||||||
constructor: Dropdown
|
|
||||||
|
|
||||||
, toggle: function (e) {
|
|
||||||
var $this = $(this)
|
|
||||||
, $parent
|
|
||||||
, selector
|
|
||||||
, isActive
|
|
||||||
|
|
||||||
if ($this.is('.disabled, :disabled')) return
|
|
||||||
|
|
||||||
selector = $this.attr('data-target')
|
|
||||||
|
|
||||||
if (!selector) {
|
|
||||||
selector = $this.attr('href')
|
|
||||||
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
|
|
||||||
}
|
|
||||||
|
|
||||||
$parent = $(selector)
|
|
||||||
$parent.length || ($parent = $this.parent())
|
|
||||||
|
|
||||||
isActive = $parent.hasClass('open')
|
|
||||||
|
|
||||||
clearMenus()
|
|
||||||
|
|
||||||
if (!isActive) $parent.toggleClass('open')
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearMenus() {
|
|
||||||
$(toggle).parent().removeClass('open')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* DROPDOWN PLUGIN DEFINITION
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
$.fn.dropdown = function (option) {
|
|
||||||
return this.each(function () {
|
|
||||||
var $this = $(this)
|
|
||||||
, data = $this.data('dropdown')
|
|
||||||
if (!data) $this.data('dropdown', (data = new Dropdown(this)))
|
|
||||||
if (typeof option == 'string') data[option].call($this)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
$.fn.dropdown.Constructor = Dropdown
|
|
||||||
|
|
||||||
|
|
||||||
/* APPLY TO STANDARD DROPDOWN ELEMENTS
|
|
||||||
* =================================== */
|
|
||||||
|
|
||||||
$(function () {
|
|
||||||
$('html').on('click.dropdown.data-api', clearMenus)
|
|
||||||
$('body')
|
|
||||||
.on('click.dropdown', '.dropdown form', function (e) { e.stopPropagation() })
|
|
||||||
.on('click.dropdown.data-api', toggle, Dropdown.prototype.toggle)
|
|
||||||
})
|
|
||||||
|
|
||||||
}(window.jQuery);
|
|
218
app/assets/javascripts/app/lib/bootstrap-modal.js
vendored
218
app/assets/javascripts/app/lib/bootstrap-modal.js
vendored
|
@ -1,218 +0,0 @@
|
||||||
/* =========================================================
|
|
||||||
* bootstrap-modal.js v2.0.4
|
|
||||||
* http://twitter.github.com/bootstrap/javascript.html#modals
|
|
||||||
* =========================================================
|
|
||||||
* Copyright 2012 Twitter, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
* ========================================================= */
|
|
||||||
|
|
||||||
|
|
||||||
!function ($) {
|
|
||||||
|
|
||||||
"use strict"; // jshint ;_;
|
|
||||||
|
|
||||||
|
|
||||||
/* MODAL CLASS DEFINITION
|
|
||||||
* ====================== */
|
|
||||||
|
|
||||||
var Modal = function (content, options) {
|
|
||||||
this.options = options
|
|
||||||
this.$element = $(content)
|
|
||||||
.delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
|
|
||||||
}
|
|
||||||
|
|
||||||
Modal.prototype = {
|
|
||||||
|
|
||||||
constructor: Modal
|
|
||||||
|
|
||||||
, toggle: function () {
|
|
||||||
return this[!this.isShown ? 'show' : 'hide']()
|
|
||||||
}
|
|
||||||
|
|
||||||
, show: function () {
|
|
||||||
var that = this
|
|
||||||
, e = $.Event('show')
|
|
||||||
|
|
||||||
this.$element.trigger(e)
|
|
||||||
|
|
||||||
if (this.isShown || e.isDefaultPrevented()) return
|
|
||||||
|
|
||||||
$('body').addClass('modal-open')
|
|
||||||
|
|
||||||
this.isShown = true
|
|
||||||
|
|
||||||
escape.call(this)
|
|
||||||
backdrop.call(this, function () {
|
|
||||||
var transition = $.support.transition && that.$element.hasClass('fade')
|
|
||||||
|
|
||||||
if (!that.$element.parent().length) {
|
|
||||||
that.$element.appendTo(document.body) //don't move modals dom position
|
|
||||||
}
|
|
||||||
|
|
||||||
that.$element
|
|
||||||
.show()
|
|
||||||
|
|
||||||
if (transition) {
|
|
||||||
that.$element[0].offsetWidth // force reflow
|
|
||||||
}
|
|
||||||
|
|
||||||
that.$element.addClass('in')
|
|
||||||
|
|
||||||
transition ?
|
|
||||||
that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) :
|
|
||||||
that.$element.trigger('shown')
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
, hide: function (e) {
|
|
||||||
e && e.preventDefault()
|
|
||||||
|
|
||||||
var that = this
|
|
||||||
|
|
||||||
e = $.Event('hide')
|
|
||||||
|
|
||||||
this.$element.trigger(e)
|
|
||||||
|
|
||||||
if (!this.isShown || e.isDefaultPrevented()) return
|
|
||||||
|
|
||||||
this.isShown = false
|
|
||||||
|
|
||||||
$('body').removeClass('modal-open')
|
|
||||||
|
|
||||||
escape.call(this)
|
|
||||||
|
|
||||||
this.$element.removeClass('in')
|
|
||||||
|
|
||||||
$.support.transition && this.$element.hasClass('fade') ?
|
|
||||||
hideWithTransition.call(this) :
|
|
||||||
hideModal.call(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* MODAL PRIVATE METHODS
|
|
||||||
* ===================== */
|
|
||||||
|
|
||||||
function hideWithTransition() {
|
|
||||||
var that = this
|
|
||||||
, timeout = setTimeout(function () {
|
|
||||||
that.$element.off($.support.transition.end)
|
|
||||||
hideModal.call(that)
|
|
||||||
}, 500)
|
|
||||||
|
|
||||||
this.$element.one($.support.transition.end, function () {
|
|
||||||
clearTimeout(timeout)
|
|
||||||
hideModal.call(that)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideModal(that) {
|
|
||||||
this.$element
|
|
||||||
.hide()
|
|
||||||
.trigger('hidden')
|
|
||||||
|
|
||||||
backdrop.call(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
function backdrop(callback) {
|
|
||||||
var that = this
|
|
||||||
, animate = this.$element.hasClass('fade') ? 'fade' : ''
|
|
||||||
|
|
||||||
if (this.isShown && this.options.backdrop) {
|
|
||||||
var doAnimate = $.support.transition && animate
|
|
||||||
|
|
||||||
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
|
|
||||||
.appendTo(document.body)
|
|
||||||
|
|
||||||
if (this.options.backdrop != 'static') {
|
|
||||||
this.$backdrop.click($.proxy(this.hide, this))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
|
|
||||||
|
|
||||||
this.$backdrop.addClass('in')
|
|
||||||
|
|
||||||
doAnimate ?
|
|
||||||
this.$backdrop.one($.support.transition.end, callback) :
|
|
||||||
callback()
|
|
||||||
|
|
||||||
} else if (!this.isShown && this.$backdrop) {
|
|
||||||
this.$backdrop.removeClass('in')
|
|
||||||
|
|
||||||
$.support.transition && this.$element.hasClass('fade')?
|
|
||||||
this.$backdrop.one($.support.transition.end, $.proxy(removeBackdrop, this)) :
|
|
||||||
removeBackdrop.call(this)
|
|
||||||
|
|
||||||
} else if (callback) {
|
|
||||||
callback()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeBackdrop() {
|
|
||||||
this.$backdrop.remove()
|
|
||||||
this.$backdrop = null
|
|
||||||
}
|
|
||||||
|
|
||||||
function escape() {
|
|
||||||
var that = this
|
|
||||||
if (this.isShown && this.options.keyboard) {
|
|
||||||
$(document).on('keyup.dismiss.modal', function ( e ) {
|
|
||||||
e.which == 27 && that.hide()
|
|
||||||
})
|
|
||||||
} else if (!this.isShown) {
|
|
||||||
$(document).off('keyup.dismiss.modal')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* MODAL PLUGIN DEFINITION
|
|
||||||
* ======================= */
|
|
||||||
|
|
||||||
$.fn.modal = function (option) {
|
|
||||||
return this.each(function () {
|
|
||||||
var $this = $(this)
|
|
||||||
, data = $this.data('modal')
|
|
||||||
, options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
|
|
||||||
if (!data) $this.data('modal', (data = new Modal(this, options)))
|
|
||||||
if (typeof option == 'string') data[option]()
|
|
||||||
else if (options.show) data.show()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
$.fn.modal.defaults = {
|
|
||||||
backdrop: true
|
|
||||||
, keyboard: true
|
|
||||||
, show: true
|
|
||||||
}
|
|
||||||
|
|
||||||
$.fn.modal.Constructor = Modal
|
|
||||||
|
|
||||||
|
|
||||||
/* MODAL DATA-API
|
|
||||||
* ============== */
|
|
||||||
|
|
||||||
$(function () {
|
|
||||||
$('body').on('click.modal.data-api', '[data-toggle="modal"]', function ( e ) {
|
|
||||||
var $this = $(this), href
|
|
||||||
, $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
|
|
||||||
, option = $target.data('modal') ? 'toggle' : $.extend({}, $target.data(), $this.data())
|
|
||||||
|
|
||||||
e.preventDefault()
|
|
||||||
$target.modal(option)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
}(window.jQuery);
|
|
|
@ -1,98 +0,0 @@
|
||||||
/* ===========================================================
|
|
||||||
* bootstrap-popover.js v2.0.4
|
|
||||||
* http://twitter.github.com/bootstrap/javascript.html#popovers
|
|
||||||
* ===========================================================
|
|
||||||
* Copyright 2012 Twitter, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
* =========================================================== */
|
|
||||||
|
|
||||||
|
|
||||||
!function ($) {
|
|
||||||
|
|
||||||
"use strict"; // jshint ;_;
|
|
||||||
|
|
||||||
|
|
||||||
/* POPOVER PUBLIC CLASS DEFINITION
|
|
||||||
* =============================== */
|
|
||||||
|
|
||||||
var Popover = function ( element, options ) {
|
|
||||||
this.init('popover', element, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
|
|
||||||
========================================== */
|
|
||||||
|
|
||||||
Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
|
|
||||||
|
|
||||||
constructor: Popover
|
|
||||||
|
|
||||||
, setContent: function () {
|
|
||||||
var $tip = this.tip()
|
|
||||||
, title = this.getTitle()
|
|
||||||
, content = this.getContent()
|
|
||||||
|
|
||||||
$tip.find('.popover-title')[this.isHTML(title) ? 'html' : 'text'](title)
|
|
||||||
$tip.find('.popover-content > *')[this.isHTML(content) ? 'html' : 'text'](content)
|
|
||||||
|
|
||||||
$tip.removeClass('fade top bottom left right in')
|
|
||||||
}
|
|
||||||
|
|
||||||
, hasContent: function () {
|
|
||||||
return this.getTitle() || this.getContent()
|
|
||||||
}
|
|
||||||
|
|
||||||
, getContent: function () {
|
|
||||||
var content
|
|
||||||
, $e = this.$element
|
|
||||||
, o = this.options
|
|
||||||
|
|
||||||
content = $e.attr('data-content')
|
|
||||||
|| (typeof o.content == 'function' ? o.content.call($e[0]) : o.content)
|
|
||||||
|
|
||||||
return content
|
|
||||||
}
|
|
||||||
|
|
||||||
, tip: function () {
|
|
||||||
if (!this.$tip) {
|
|
||||||
this.$tip = $(this.options.template)
|
|
||||||
}
|
|
||||||
return this.$tip
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
/* POPOVER PLUGIN DEFINITION
|
|
||||||
* ======================= */
|
|
||||||
|
|
||||||
$.fn.popover = function (option) {
|
|
||||||
return this.each(function () {
|
|
||||||
var $this = $(this)
|
|
||||||
, data = $this.data('popover')
|
|
||||||
, options = typeof option == 'object' && option
|
|
||||||
if (!data) $this.data('popover', (data = new Popover(this, options)))
|
|
||||||
if (typeof option == 'string') data[option]()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
$.fn.popover.Constructor = Popover
|
|
||||||
|
|
||||||
$.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
|
|
||||||
placement: 'right'
|
|
||||||
, content: ''
|
|
||||||
, template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
|
|
||||||
})
|
|
||||||
|
|
||||||
}(window.jQuery);
|
|
135
app/assets/javascripts/app/lib/bootstrap-tab.js
vendored
135
app/assets/javascripts/app/lib/bootstrap-tab.js
vendored
|
@ -1,135 +0,0 @@
|
||||||
/* ========================================================
|
|
||||||
* bootstrap-tab.js v2.0.4
|
|
||||||
* http://twitter.github.com/bootstrap/javascript.html#tabs
|
|
||||||
* ========================================================
|
|
||||||
* Copyright 2012 Twitter, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
* ======================================================== */
|
|
||||||
|
|
||||||
|
|
||||||
!function ($) {
|
|
||||||
|
|
||||||
"use strict"; // jshint ;_;
|
|
||||||
|
|
||||||
|
|
||||||
/* TAB CLASS DEFINITION
|
|
||||||
* ==================== */
|
|
||||||
|
|
||||||
var Tab = function ( element ) {
|
|
||||||
this.element = $(element)
|
|
||||||
}
|
|
||||||
|
|
||||||
Tab.prototype = {
|
|
||||||
|
|
||||||
constructor: Tab
|
|
||||||
|
|
||||||
, show: function () {
|
|
||||||
var $this = this.element
|
|
||||||
, $ul = $this.closest('ul:not(.dropdown-menu)')
|
|
||||||
, selector = $this.attr('data-target')
|
|
||||||
, previous
|
|
||||||
, $target
|
|
||||||
, e
|
|
||||||
|
|
||||||
if (!selector) {
|
|
||||||
selector = $this.attr('href')
|
|
||||||
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $this.parent('li').hasClass('active') ) return
|
|
||||||
|
|
||||||
previous = $ul.find('.active a').last()[0]
|
|
||||||
|
|
||||||
e = $.Event('show', {
|
|
||||||
relatedTarget: previous
|
|
||||||
})
|
|
||||||
|
|
||||||
$this.trigger(e)
|
|
||||||
|
|
||||||
if (e.isDefaultPrevented()) return
|
|
||||||
|
|
||||||
$target = $(selector)
|
|
||||||
|
|
||||||
this.activate($this.parent('li'), $ul)
|
|
||||||
this.activate($target, $target.parent(), function () {
|
|
||||||
$this.trigger({
|
|
||||||
type: 'shown'
|
|
||||||
, relatedTarget: previous
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
, activate: function ( element, container, callback) {
|
|
||||||
var $active = container.find('> .active')
|
|
||||||
, transition = callback
|
|
||||||
&& $.support.transition
|
|
||||||
&& $active.hasClass('fade')
|
|
||||||
|
|
||||||
function next() {
|
|
||||||
$active
|
|
||||||
.removeClass('active')
|
|
||||||
.find('> .dropdown-menu > .active')
|
|
||||||
.removeClass('active')
|
|
||||||
|
|
||||||
element.addClass('active')
|
|
||||||
|
|
||||||
if (transition) {
|
|
||||||
element[0].offsetWidth // reflow for transition
|
|
||||||
element.addClass('in')
|
|
||||||
} else {
|
|
||||||
element.removeClass('fade')
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( element.parent('.dropdown-menu') ) {
|
|
||||||
element.closest('li.dropdown').addClass('active')
|
|
||||||
}
|
|
||||||
|
|
||||||
callback && callback()
|
|
||||||
}
|
|
||||||
|
|
||||||
transition ?
|
|
||||||
$active.one($.support.transition.end, next) :
|
|
||||||
next()
|
|
||||||
|
|
||||||
$active.removeClass('in')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* TAB PLUGIN DEFINITION
|
|
||||||
* ===================== */
|
|
||||||
|
|
||||||
$.fn.tab = function ( option ) {
|
|
||||||
return this.each(function () {
|
|
||||||
var $this = $(this)
|
|
||||||
, data = $this.data('tab')
|
|
||||||
if (!data) $this.data('tab', (data = new Tab(this)))
|
|
||||||
if (typeof option == 'string') data[option]()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
$.fn.tab.Constructor = Tab
|
|
||||||
|
|
||||||
|
|
||||||
/* TAB DATA-API
|
|
||||||
* ============ */
|
|
||||||
|
|
||||||
$(function () {
|
|
||||||
$('body').on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
|
|
||||||
e.preventDefault()
|
|
||||||
$(this).tab('show')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
}(window.jQuery);
|
|
275
app/assets/javascripts/app/lib/bootstrap-tooltip.js
vendored
275
app/assets/javascripts/app/lib/bootstrap-tooltip.js
vendored
|
@ -1,275 +0,0 @@
|
||||||
/* ===========================================================
|
|
||||||
* bootstrap-tooltip.js v2.0.4
|
|
||||||
* http://twitter.github.com/bootstrap/javascript.html#tooltips
|
|
||||||
* Inspired by the original jQuery.tipsy by Jason Frame
|
|
||||||
* ===========================================================
|
|
||||||
* Copyright 2012 Twitter, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
* ========================================================== */
|
|
||||||
|
|
||||||
|
|
||||||
!function ($) {
|
|
||||||
|
|
||||||
"use strict"; // jshint ;_;
|
|
||||||
|
|
||||||
|
|
||||||
/* TOOLTIP PUBLIC CLASS DEFINITION
|
|
||||||
* =============================== */
|
|
||||||
|
|
||||||
var Tooltip = function (element, options) {
|
|
||||||
this.init('tooltip', element, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
Tooltip.prototype = {
|
|
||||||
|
|
||||||
constructor: Tooltip
|
|
||||||
|
|
||||||
, init: function (type, element, options) {
|
|
||||||
var eventIn
|
|
||||||
, eventOut
|
|
||||||
|
|
||||||
this.type = type
|
|
||||||
this.$element = $(element)
|
|
||||||
this.options = this.getOptions(options)
|
|
||||||
this.enabled = true
|
|
||||||
|
|
||||||
if (this.options.trigger != 'manual') {
|
|
||||||
eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
|
|
||||||
eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
|
|
||||||
this.$element.on(eventIn, this.options.selector, $.proxy(this.enter, this))
|
|
||||||
this.$element.on(eventOut, this.options.selector, $.proxy(this.leave, this))
|
|
||||||
}
|
|
||||||
|
|
||||||
this.options.selector ?
|
|
||||||
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
|
|
||||||
this.fixTitle()
|
|
||||||
}
|
|
||||||
|
|
||||||
, getOptions: function (options) {
|
|
||||||
options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data())
|
|
||||||
|
|
||||||
if (options.delay && typeof options.delay == 'number') {
|
|
||||||
options.delay = {
|
|
||||||
show: options.delay
|
|
||||||
, hide: options.delay
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return options
|
|
||||||
}
|
|
||||||
|
|
||||||
, enter: function (e) {
|
|
||||||
var self = $(e.currentTarget)[this.type](this._options).data(this.type)
|
|
||||||
|
|
||||||
if (!self.options.delay || !self.options.delay.show) return self.show()
|
|
||||||
|
|
||||||
clearTimeout(this.timeout)
|
|
||||||
self.hoverState = 'in'
|
|
||||||
this.timeout = setTimeout(function() {
|
|
||||||
if (self.hoverState == 'in') self.show()
|
|
||||||
}, self.options.delay.show)
|
|
||||||
}
|
|
||||||
|
|
||||||
, leave: function (e) {
|
|
||||||
var self = $(e.currentTarget)[this.type](this._options).data(this.type)
|
|
||||||
|
|
||||||
if (this.timeout) clearTimeout(this.timeout)
|
|
||||||
if (!self.options.delay || !self.options.delay.hide) return self.hide()
|
|
||||||
|
|
||||||
self.hoverState = 'out'
|
|
||||||
this.timeout = setTimeout(function() {
|
|
||||||
if (self.hoverState == 'out') self.hide()
|
|
||||||
}, self.options.delay.hide)
|
|
||||||
}
|
|
||||||
|
|
||||||
, show: function () {
|
|
||||||
var $tip
|
|
||||||
, inside
|
|
||||||
, pos
|
|
||||||
, actualWidth
|
|
||||||
, actualHeight
|
|
||||||
, placement
|
|
||||||
, tp
|
|
||||||
|
|
||||||
if (this.hasContent() && this.enabled) {
|
|
||||||
$tip = this.tip()
|
|
||||||
this.setContent()
|
|
||||||
|
|
||||||
if (this.options.animation) {
|
|
||||||
$tip.addClass('fade')
|
|
||||||
}
|
|
||||||
|
|
||||||
placement = typeof this.options.placement == 'function' ?
|
|
||||||
this.options.placement.call(this, $tip[0], this.$element[0]) :
|
|
||||||
this.options.placement
|
|
||||||
|
|
||||||
inside = /in/.test(placement)
|
|
||||||
|
|
||||||
$tip
|
|
||||||
.remove()
|
|
||||||
.css({ top: 0, left: 0, display: 'block' })
|
|
||||||
.appendTo(inside ? this.$element : document.body)
|
|
||||||
|
|
||||||
pos = this.getPosition(inside)
|
|
||||||
|
|
||||||
actualWidth = $tip[0].offsetWidth
|
|
||||||
actualHeight = $tip[0].offsetHeight
|
|
||||||
|
|
||||||
switch (inside ? placement.split(' ')[1] : placement) {
|
|
||||||
case 'bottom':
|
|
||||||
tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
|
|
||||||
break
|
|
||||||
case 'top':
|
|
||||||
tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
|
|
||||||
break
|
|
||||||
case 'left':
|
|
||||||
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
|
|
||||||
break
|
|
||||||
case 'right':
|
|
||||||
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
$tip
|
|
||||||
.css(tp)
|
|
||||||
.addClass(placement)
|
|
||||||
.addClass('in')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
, isHTML: function(text) {
|
|
||||||
// html string detection logic adapted from jQuery
|
|
||||||
return typeof text != 'string'
|
|
||||||
|| ( text.charAt(0) === "<"
|
|
||||||
&& text.charAt( text.length - 1 ) === ">"
|
|
||||||
&& text.length >= 3
|
|
||||||
) || /^(?:[^<]*<[\w\W]+>[^>]*$)/.exec(text)
|
|
||||||
}
|
|
||||||
|
|
||||||
, setContent: function () {
|
|
||||||
var $tip = this.tip()
|
|
||||||
, title = this.getTitle()
|
|
||||||
|
|
||||||
$tip.find('.tooltip-inner')[this.isHTML(title) ? 'html' : 'text'](title)
|
|
||||||
$tip.removeClass('fade in top bottom left right')
|
|
||||||
}
|
|
||||||
|
|
||||||
, hide: function () {
|
|
||||||
var that = this
|
|
||||||
, $tip = this.tip()
|
|
||||||
|
|
||||||
$tip.removeClass('in')
|
|
||||||
|
|
||||||
function removeWithAnimation() {
|
|
||||||
var timeout = setTimeout(function () {
|
|
||||||
$tip.off($.support.transition.end).remove()
|
|
||||||
}, 500)
|
|
||||||
|
|
||||||
$tip.one($.support.transition.end, function () {
|
|
||||||
clearTimeout(timeout)
|
|
||||||
$tip.remove()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
$.support.transition && this.$tip.hasClass('fade') ?
|
|
||||||
removeWithAnimation() :
|
|
||||||
$tip.remove()
|
|
||||||
}
|
|
||||||
|
|
||||||
, fixTitle: function () {
|
|
||||||
var $e = this.$element
|
|
||||||
if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
|
|
||||||
$e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
, hasContent: function () {
|
|
||||||
return this.getTitle()
|
|
||||||
}
|
|
||||||
|
|
||||||
, getPosition: function (inside) {
|
|
||||||
return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), {
|
|
||||||
width: this.$element[0].offsetWidth
|
|
||||||
, height: this.$element[0].offsetHeight
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
, getTitle: function () {
|
|
||||||
var title
|
|
||||||
, $e = this.$element
|
|
||||||
, o = this.options
|
|
||||||
|
|
||||||
title = $e.attr('data-original-title')
|
|
||||||
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
|
|
||||||
|
|
||||||
return title
|
|
||||||
}
|
|
||||||
|
|
||||||
, tip: function () {
|
|
||||||
return this.$tip = this.$tip || $(this.options.template)
|
|
||||||
}
|
|
||||||
|
|
||||||
, validate: function () {
|
|
||||||
if (!this.$element[0].parentNode) {
|
|
||||||
this.hide()
|
|
||||||
this.$element = null
|
|
||||||
this.options = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
, enable: function () {
|
|
||||||
this.enabled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
, disable: function () {
|
|
||||||
this.enabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
, toggleEnabled: function () {
|
|
||||||
this.enabled = !this.enabled
|
|
||||||
}
|
|
||||||
|
|
||||||
, toggle: function () {
|
|
||||||
this[this.tip().hasClass('in') ? 'hide' : 'show']()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* TOOLTIP PLUGIN DEFINITION
|
|
||||||
* ========================= */
|
|
||||||
|
|
||||||
$.fn.tooltip = function ( option ) {
|
|
||||||
return this.each(function () {
|
|
||||||
var $this = $(this)
|
|
||||||
, data = $this.data('tooltip')
|
|
||||||
, options = typeof option == 'object' && option
|
|
||||||
if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
|
|
||||||
if (typeof option == 'string') data[option]()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
$.fn.tooltip.Constructor = Tooltip
|
|
||||||
|
|
||||||
$.fn.tooltip.defaults = {
|
|
||||||
animation: true
|
|
||||||
, placement: 'top'
|
|
||||||
, selector: false
|
|
||||||
, template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
|
|
||||||
, trigger: 'hover'
|
|
||||||
, title: ''
|
|
||||||
, delay: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
}(window.jQuery);
|
|
|
@ -1,61 +0,0 @@
|
||||||
/* ===================================================
|
|
||||||
* bootstrap-transition.js v2.0.4
|
|
||||||
* http://twitter.github.com/bootstrap/javascript.html#transitions
|
|
||||||
* ===================================================
|
|
||||||
* Copyright 2012 Twitter, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
* ========================================================== */
|
|
||||||
|
|
||||||
|
|
||||||
!function ($) {
|
|
||||||
|
|
||||||
$(function () {
|
|
||||||
|
|
||||||
"use strict"; // jshint ;_;
|
|
||||||
|
|
||||||
|
|
||||||
/* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
|
|
||||||
* ======================================================= */
|
|
||||||
|
|
||||||
$.support.transition = (function () {
|
|
||||||
|
|
||||||
var transitionEnd = (function () {
|
|
||||||
|
|
||||||
var el = document.createElement('bootstrap')
|
|
||||||
, transEndEventNames = {
|
|
||||||
'WebkitTransition' : 'webkitTransitionEnd'
|
|
||||||
, 'MozTransition' : 'transitionend'
|
|
||||||
, 'OTransition' : 'oTransitionEnd'
|
|
||||||
, 'msTransition' : 'MSTransitionEnd'
|
|
||||||
, 'transition' : 'transitionend'
|
|
||||||
}
|
|
||||||
, name
|
|
||||||
|
|
||||||
for (name in transEndEventNames){
|
|
||||||
if (el.style[name] !== undefined) {
|
|
||||||
return transEndEventNames[name]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}())
|
|
||||||
|
|
||||||
return transitionEnd && {
|
|
||||||
end: transitionEnd
|
|
||||||
}
|
|
||||||
|
|
||||||
})()
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
}(window.jQuery);
|
|
|
@ -1,181 +0,0 @@
|
||||||
class App.ClipBoard
|
|
||||||
_instance = undefined
|
|
||||||
|
|
||||||
@bind: (el) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.bind(el)
|
|
||||||
|
|
||||||
@getSelected: ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.getSelected()
|
|
||||||
|
|
||||||
@getSelectedLast: ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.getSelectedLast()
|
|
||||||
|
|
||||||
@keycode: (code) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.keycode(code)
|
|
||||||
|
|
||||||
class _Singleton
|
|
||||||
constructor: ->
|
|
||||||
@selection = ''
|
|
||||||
@selectionLast = ''
|
|
||||||
|
|
||||||
# bind to fill selected text into
|
|
||||||
bind: (el) ->
|
|
||||||
$(el).bind('mouseup', =>
|
|
||||||
|
|
||||||
# check selection on mouse up
|
|
||||||
@selection = @_getSelected()
|
|
||||||
if @selection
|
|
||||||
@selectionLast = @selection
|
|
||||||
)
|
|
||||||
$(el).bind('keyup', (e) =>
|
|
||||||
|
|
||||||
# check selection on sonder key
|
|
||||||
if e.keyCode == 91
|
|
||||||
@selection = @_getSelected()
|
|
||||||
if @selection
|
|
||||||
@selectionLast = @selection
|
|
||||||
|
|
||||||
# check selection of arrow keys
|
|
||||||
if e.keyCode == 37 || e.keyCode == 38 || e.keyCode == 39 || e.keyCode == 40
|
|
||||||
@selection = @_getSelected()
|
|
||||||
if @selection
|
|
||||||
@selectionLast = @selection
|
|
||||||
)
|
|
||||||
|
|
||||||
# get cross browser selected string
|
|
||||||
_getSelected: ->
|
|
||||||
text = '';
|
|
||||||
if window.getSelection
|
|
||||||
text = window.getSelection()
|
|
||||||
else if document.getSelection
|
|
||||||
text = document.getSelection()
|
|
||||||
else if document.selection
|
|
||||||
text = document.selection.createRange().text
|
|
||||||
if text
|
|
||||||
text = text.toString().trim()
|
|
||||||
text
|
|
||||||
|
|
||||||
# get current selection
|
|
||||||
getSelected: ->
|
|
||||||
@selection
|
|
||||||
|
|
||||||
# get latest selection
|
|
||||||
getSelectedLast: ->
|
|
||||||
@selectionLast
|
|
||||||
|
|
||||||
keycode: (code) ->
|
|
||||||
for key, value of @keycodesTable()
|
|
||||||
if value.toString() is code.toString()
|
|
||||||
return key
|
|
||||||
|
|
||||||
keycodesTable: ->
|
|
||||||
map = {
|
|
||||||
'backspace' : 8,
|
|
||||||
'tab' : 9,
|
|
||||||
'enter' : 13,
|
|
||||||
'shift' : 16,
|
|
||||||
'ctrl' : 17,
|
|
||||||
'alt' : 18,
|
|
||||||
'space' : 32,
|
|
||||||
'pause_break' : '19',
|
|
||||||
'caps_lock' : '20',
|
|
||||||
'escape' : '27',
|
|
||||||
'page_up' : '33',
|
|
||||||
'page down' : '34',
|
|
||||||
'end' : '35',
|
|
||||||
'home' : '36',
|
|
||||||
'left_arrow' : '37',
|
|
||||||
'up_arrow' : '38',
|
|
||||||
'right_arrow' : '39',
|
|
||||||
'down_arrow' : '40',
|
|
||||||
'insert' : '45',
|
|
||||||
'delete' : '46',
|
|
||||||
'0' : '48',
|
|
||||||
'1' : '49',
|
|
||||||
'2' : '50',
|
|
||||||
'3' : '51',
|
|
||||||
'4' : '52',
|
|
||||||
'5' : '53',
|
|
||||||
'6' : '54',
|
|
||||||
'7' : '55',
|
|
||||||
'8' : '56',
|
|
||||||
'9' : '57',
|
|
||||||
'a' : '65',
|
|
||||||
'b' : '66',
|
|
||||||
'c' : '67',
|
|
||||||
'd' : '68',
|
|
||||||
'e' : '69',
|
|
||||||
'f' : '70',
|
|
||||||
'g' : '71',
|
|
||||||
'h' : '72',
|
|
||||||
'i' : '73',
|
|
||||||
'j' : '74',
|
|
||||||
'k' : '75',
|
|
||||||
'l' : '76',
|
|
||||||
'm' : '77',
|
|
||||||
'n' : '78',
|
|
||||||
'o' : '79',
|
|
||||||
'p' : '80',
|
|
||||||
'q' : '81',
|
|
||||||
'r' : '82',
|
|
||||||
's' : '83',
|
|
||||||
't' : '84',
|
|
||||||
'u' : '85',
|
|
||||||
'v' : '86',
|
|
||||||
'w' : '87',
|
|
||||||
'x' : '88',
|
|
||||||
'y' : '89',
|
|
||||||
'z' : '90',
|
|
||||||
'left_window key' : '91',
|
|
||||||
'right_window key' : '92',
|
|
||||||
'select_key' : '93',
|
|
||||||
'numpad 0' : '96',
|
|
||||||
'numpad 1' : '97',
|
|
||||||
'numpad 2' : '98',
|
|
||||||
'numpad 3' : '99',
|
|
||||||
'numpad 4' : '100',
|
|
||||||
'numpad 5' : '101',
|
|
||||||
'numpad 6' : '102',
|
|
||||||
'numpad 7' : '103',
|
|
||||||
'numpad 8' : '104',
|
|
||||||
'numpad 9' : '105',
|
|
||||||
'multiply' : '106',
|
|
||||||
'add' : '107',
|
|
||||||
'subtract' : '109',
|
|
||||||
'decimal point' : '110',
|
|
||||||
'divide' : '111',
|
|
||||||
'f1' : '112',
|
|
||||||
'f2' : '113',
|
|
||||||
'f3' : '114',
|
|
||||||
'f4' : '115',
|
|
||||||
'f5' : '116',
|
|
||||||
'f6' : '117',
|
|
||||||
'f7' : '118',
|
|
||||||
'f8' : '119',
|
|
||||||
'f9' : '120',
|
|
||||||
'f10' : '121',
|
|
||||||
'f11' : '122',
|
|
||||||
'f12' : '123',
|
|
||||||
'num_lock' : '144',
|
|
||||||
'scroll_lock' : '145',
|
|
||||||
'semi_colon' : '186',
|
|
||||||
'equal_sign' : '187',
|
|
||||||
'comma' : '188',
|
|
||||||
'dash' : '189',
|
|
||||||
'period' : '190',
|
|
||||||
'forward_slash' : '191',
|
|
||||||
'grave_accent' : '192',
|
|
||||||
'open_bracket' : '219',
|
|
||||||
'backslash' : '220',
|
|
||||||
'closebracket' : '221',
|
|
||||||
'single_quote' : '222'
|
|
||||||
}
|
|
||||||
map
|
|
|
@ -1,363 +0,0 @@
|
||||||
class App.Collection
|
|
||||||
_instance = undefined
|
|
||||||
|
|
||||||
@init: ->
|
|
||||||
_instance = new _Singleton
|
|
||||||
|
|
||||||
@load: ( args ) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.load( args )
|
|
||||||
|
|
||||||
@reset: ( args ) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.reset( args )
|
|
||||||
|
|
||||||
@find: ( type, id, callback, force ) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.find( type, id, callback, force )
|
|
||||||
|
|
||||||
@get: ( args ) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.get( args )
|
|
||||||
|
|
||||||
@all: ( type ) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.all( type )
|
|
||||||
|
|
||||||
@deleteAll: ( type ) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.deleteAll( type )
|
|
||||||
|
|
||||||
@findByAttribute: ( type, key, value ) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.findByAttribute( type, key, value )
|
|
||||||
|
|
||||||
@count: ( type ) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.count( type )
|
|
||||||
|
|
||||||
@fetch: ( type ) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.fetch( type )
|
|
||||||
|
|
||||||
@observe: (args) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.observe(args)
|
|
||||||
|
|
||||||
@observeUnbindLevel: (level) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.observeUnbindLevel(level)
|
|
||||||
|
|
||||||
@_observeStats: ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance._observeStats()
|
|
||||||
|
|
||||||
class _Singleton
|
|
||||||
|
|
||||||
constructor: (@args) ->
|
|
||||||
|
|
||||||
# add trigger - bind new events
|
|
||||||
App.Event.bind 'loadCollection', (data) =>
|
|
||||||
|
|
||||||
# load collections
|
|
||||||
if data.collections
|
|
||||||
for type of data.collections
|
|
||||||
|
|
||||||
console.log 'loadCollection:trigger', type, data.collections[type]
|
|
||||||
@load( localStorage: data.localStorage, type: type, data: data.collections[type] )
|
|
||||||
|
|
||||||
# add trigger - bind new events
|
|
||||||
App.Event.bind 'resetCollection', (data) =>
|
|
||||||
|
|
||||||
# load collections
|
|
||||||
if data.collections
|
|
||||||
for type of data.collections
|
|
||||||
|
|
||||||
console.log 'resetCollection:trigger', type, data.collections[type]
|
|
||||||
@reset( localStorage: data.localStorage, type: type, data: data.collections[type] )
|
|
||||||
|
|
||||||
# find collections to load
|
|
||||||
@_loadCollectionAll()
|
|
||||||
|
|
||||||
_loadCollectionAll: ->
|
|
||||||
list = App.Store.list()
|
|
||||||
for key in list
|
|
||||||
parts = key.split('::')
|
|
||||||
if parts[0] is 'collection'
|
|
||||||
data = App.Store.get( key )
|
|
||||||
if data && data.localStorage
|
|
||||||
console.log('load INIT', data)
|
|
||||||
@load( data )
|
|
||||||
|
|
||||||
reset: (params) ->
|
|
||||||
console.log( 'reset', params )
|
|
||||||
|
|
||||||
# empty in-memory
|
|
||||||
App[ params.type ].refresh( [], { clear: true } )
|
|
||||||
|
|
||||||
# remove permanent storage
|
|
||||||
list = App.Store.list()
|
|
||||||
for key in list
|
|
||||||
parts = key.split('::')
|
|
||||||
if parts[0] is 'collection' && parts[1] is params.type
|
|
||||||
App.Store.delete(key)
|
|
||||||
|
|
||||||
# load with new data
|
|
||||||
@load(params)
|
|
||||||
|
|
||||||
load: (params) ->
|
|
||||||
console.log( 'load', params )
|
|
||||||
|
|
||||||
return if _.isEmpty( params.data )
|
|
||||||
|
|
||||||
localStorage = params.localStorage
|
|
||||||
|
|
||||||
# load full array once
|
|
||||||
if _.isArray( params.data )
|
|
||||||
# console.log( 'load ARRAY', params.data)
|
|
||||||
App[ params.type ].refresh( params.data )
|
|
||||||
|
|
||||||
# remember in store if not already requested from local storage
|
|
||||||
if !localStorage
|
|
||||||
for object in params.data
|
|
||||||
App.Store.write( 'collection::' + params.type + '::' + object.id, { type: params.type, localStorage: true, data: [ object ] } )
|
|
||||||
return
|
|
||||||
|
|
||||||
# load data from object
|
|
||||||
# if _.isObject( params.data )
|
|
||||||
for key, object of params.data
|
|
||||||
# console.log( 'load OB', object)
|
|
||||||
App[ params.type ].refresh( object )
|
|
||||||
|
|
||||||
# remember in store if not already requested from local storage
|
|
||||||
if !localStorage
|
|
||||||
App.Store.write( 'collection::' + params.type + '::' + object.id, { type: params.type, localStorage: true, data: [ object ] } )
|
|
||||||
|
|
||||||
find: ( type, id, callback, force ) ->
|
|
||||||
|
|
||||||
# console.log( 'find', type, id, force )
|
|
||||||
# if App[type].exists( id ) && !callback
|
|
||||||
if !force && App[type].exists( id )
|
|
||||||
# console.log( 'find exists', type, id )
|
|
||||||
data = App[type].find( id )
|
|
||||||
if callback
|
|
||||||
callback( data )
|
|
||||||
else
|
|
||||||
if force
|
|
||||||
console.log( 'find forced to load!', type, id )
|
|
||||||
else
|
|
||||||
console.log( 'find not loaded!', type, id )
|
|
||||||
if callback
|
|
||||||
|
|
||||||
# execute callback if record got loaded
|
|
||||||
App[type].one 'refresh', ->
|
|
||||||
console.log 'loaded..' + type + '..', id
|
|
||||||
|
|
||||||
data = App.Collection.find( type, id )
|
|
||||||
callback( data )
|
|
||||||
|
|
||||||
# fetch object
|
|
||||||
console.log 'loading..' + type + '..', id
|
|
||||||
App[type].fetch( id: id )
|
|
||||||
return true
|
|
||||||
return false
|
|
||||||
|
|
||||||
# users
|
|
||||||
if type == 'User'
|
|
||||||
|
|
||||||
# set socal media links
|
|
||||||
if data['accounts']
|
|
||||||
for account of data['accounts']
|
|
||||||
if account == 'twitter'
|
|
||||||
data['accounts'][account]['link'] = 'http://twitter.com/' + data['accounts'][account]['username']
|
|
||||||
if account == 'facebook'
|
|
||||||
data['accounts'][account]['link'] = 'https://www.facebook.com/profile.php?id=' + data['accounts'][account]['uid']
|
|
||||||
|
|
||||||
# set image url
|
|
||||||
if data && !data['image']
|
|
||||||
data['image'] = 'http://placehold.it/48x48'
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
# tickets
|
|
||||||
else if type == 'Ticket'
|
|
||||||
|
|
||||||
# priority
|
|
||||||
data.ticket_priority = @find( 'TicketPriority', data.ticket_priority_id )
|
|
||||||
|
|
||||||
# state
|
|
||||||
data.ticket_state = @find( 'TicketState', data.ticket_state_id )
|
|
||||||
|
|
||||||
# group
|
|
||||||
data.group = @find( 'Group', data.group_id )
|
|
||||||
|
|
||||||
# customer
|
|
||||||
if data.customer_id
|
|
||||||
data.customer = @find( 'User', data.customer_id )
|
|
||||||
|
|
||||||
# owner
|
|
||||||
if data.owner_id
|
|
||||||
data.owner = @find( 'User', data.owner_id )
|
|
||||||
|
|
||||||
# add created & updated
|
|
||||||
if data.created_by_id
|
|
||||||
data.created_by = @find( 'User', data.created_by_id )
|
|
||||||
if data.updated_by_id
|
|
||||||
data.updated_by = @find( 'User', data.updated_by_id )
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
# articles
|
|
||||||
else if type == 'TicketArticle'
|
|
||||||
|
|
||||||
# add created & updated
|
|
||||||
data.created_by = @find( 'User', data.created_by_id )
|
|
||||||
|
|
||||||
# add possible actions
|
|
||||||
data.article_type = @find( 'TicketArticleType', data.ticket_article_type_id )
|
|
||||||
data.article_sender = @find( 'TicketArticleSender', data.ticket_article_sender_id )
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
# history
|
|
||||||
else if type == 'History'
|
|
||||||
|
|
||||||
# add user
|
|
||||||
data.created_by = @find( 'User', data.created_by_id )
|
|
||||||
|
|
||||||
# add possible actions
|
|
||||||
if data.history_attribute_id
|
|
||||||
data.attribute = @find( 'HistoryAttribute', data.history_attribute_id )
|
|
||||||
if data.history_type_id
|
|
||||||
data.type = @find( 'HistoryType', data.history_type_id )
|
|
||||||
if data.history_object_id
|
|
||||||
data.object = @find( 'HistoryObject', data.history_object_id )
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
else
|
|
||||||
return data
|
|
||||||
|
|
||||||
get: (params) ->
|
|
||||||
console.log('get')
|
|
||||||
App[ params.type ].refresh( object, options: { clear: true } )
|
|
||||||
|
|
||||||
all: (params) ->
|
|
||||||
all = App[ params.type ].all()
|
|
||||||
all_complied = []
|
|
||||||
for item in all
|
|
||||||
item_new = @find( params.type, item.id )
|
|
||||||
all_complied.push item_new
|
|
||||||
|
|
||||||
if params.filter
|
|
||||||
all_complied = @_filter( all_complied, params.filter )
|
|
||||||
|
|
||||||
if params.filterExtended
|
|
||||||
all_complied = @_filterExtended( all_complied, params.filterExtended )
|
|
||||||
|
|
||||||
if params.sortBy
|
|
||||||
all_complied = @_sortBy( all_complied, params.sortBy )
|
|
||||||
|
|
||||||
if params.order
|
|
||||||
all_complied = @_order( all_complied, params.order )
|
|
||||||
|
|
||||||
return all_complied
|
|
||||||
|
|
||||||
deleteAll: (type) ->
|
|
||||||
App[type].deleteAll()
|
|
||||||
|
|
||||||
findByAttribute: ( type, key, value ) ->
|
|
||||||
App[type].findByAttribute( key, value )
|
|
||||||
|
|
||||||
count: ( type ) ->
|
|
||||||
App[type].count()
|
|
||||||
|
|
||||||
fetch: ( type ) ->
|
|
||||||
App[type].fetch()
|
|
||||||
|
|
||||||
_sortBy: ( collection, attribute ) ->
|
|
||||||
_.sortBy( collection, (item) ->
|
|
||||||
return '' if item[ attribute ] is undefined || item[ attribute ] is null
|
|
||||||
return item[ attribute ].toLowerCase()
|
|
||||||
)
|
|
||||||
|
|
||||||
_order: ( collection, attribute ) ->
|
|
||||||
if attribute is 'DESC'
|
|
||||||
return collection.reverse()
|
|
||||||
return collection
|
|
||||||
|
|
||||||
_filter: ( collection, filter ) ->
|
|
||||||
for key, value of filter
|
|
||||||
collection = _.filter( collection, (item) ->
|
|
||||||
if item[ key ] is value
|
|
||||||
return item
|
|
||||||
)
|
|
||||||
return collection
|
|
||||||
|
|
||||||
_filterExtended: ( collection, filters ) ->
|
|
||||||
collection = _.filter( collection, (item) ->
|
|
||||||
|
|
||||||
# check all filters
|
|
||||||
for filter in filters
|
|
||||||
|
|
||||||
# all conditions need match
|
|
||||||
matchInner = undefined
|
|
||||||
for key, value of filter
|
|
||||||
|
|
||||||
if matchInner isnt false
|
|
||||||
reg = new RegExp( value, 'i' )
|
|
||||||
if item[ key ] isnt undefined && item[ key ] isnt null && item[ key ].match( reg )
|
|
||||||
matchInner = true
|
|
||||||
else
|
|
||||||
matchInner = false
|
|
||||||
|
|
||||||
# if all matched, add item to new collection
|
|
||||||
if matchInner is true
|
|
||||||
return item
|
|
||||||
|
|
||||||
return
|
|
||||||
)
|
|
||||||
return collection
|
|
||||||
|
|
||||||
observeUnbindLevel: (level) ->
|
|
||||||
return if !@observeCurrent
|
|
||||||
return if !@observeCurrent[level]
|
|
||||||
for observers in @observeCurrent[level]
|
|
||||||
@_observeUnbind( observers )
|
|
||||||
@observeCurrent[level] = []
|
|
||||||
|
|
||||||
observe: (data) ->
|
|
||||||
if !@observeCurrent
|
|
||||||
@observeCurrent = {}
|
|
||||||
|
|
||||||
if !@observeCurrent[ data.level ]
|
|
||||||
@observeCurrent[ data.level ] = []
|
|
||||||
|
|
||||||
@observeCurrent[ data.level ].push data.collections
|
|
||||||
for observe in data.collections
|
|
||||||
events = observe.event.split(' ')
|
|
||||||
for event in events
|
|
||||||
if App[ observe.collection ]
|
|
||||||
App[ observe.collection ].bind( event, observe.callback )
|
|
||||||
|
|
||||||
_observeUnbind: (observers) ->
|
|
||||||
for observe in observers
|
|
||||||
events = observe.event.split(' ')
|
|
||||||
for event in events
|
|
||||||
if App[ observe.collection ]
|
|
||||||
App[ observe.collection ].unbind( event, observe.callback )
|
|
||||||
|
|
||||||
_observeStats: ->
|
|
||||||
@observeCurrent
|
|
|
@ -1,90 +0,0 @@
|
||||||
class App.Event
|
|
||||||
_instance = undefined
|
|
||||||
|
|
||||||
@init: ->
|
|
||||||
_instance = new _Singleton
|
|
||||||
|
|
||||||
@bind: ( events, callback, level ) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.bind( events, callback, level )
|
|
||||||
|
|
||||||
@unbind: ( events, callback, level ) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.unbind( events, callback, level )
|
|
||||||
|
|
||||||
@trigger: ( events, data ) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.trigger( events, data )
|
|
||||||
|
|
||||||
@unbindLevel: (level) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.unbindLevel(level)
|
|
||||||
|
|
||||||
@_allBindings: ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance._allBindings()
|
|
||||||
|
|
||||||
class _Singleton
|
|
||||||
|
|
||||||
constructor: ->
|
|
||||||
@eventCurrent = {}
|
|
||||||
|
|
||||||
unbindLevel: (level) ->
|
|
||||||
return if !@eventCurrent[level]
|
|
||||||
for item in @eventCurrent[level]
|
|
||||||
@unbind( item.event, item.callback, level )
|
|
||||||
@eventCurrent[level] = []
|
|
||||||
|
|
||||||
bind: ( events, callback, level ) ->
|
|
||||||
|
|
||||||
if !level
|
|
||||||
level = '_all'
|
|
||||||
|
|
||||||
if !@eventCurrent[level]
|
|
||||||
@eventCurrent[level] = []
|
|
||||||
|
|
||||||
# level boundary events
|
|
||||||
eventList = events.split(' ')
|
|
||||||
for event in eventList
|
|
||||||
|
|
||||||
# remember all events
|
|
||||||
@eventCurrent[ level ].push {
|
|
||||||
event: event,
|
|
||||||
callback: callback,
|
|
||||||
}
|
|
||||||
|
|
||||||
# bind
|
|
||||||
Spine.bind( event, callback )
|
|
||||||
|
|
||||||
unbind: ( events, callback, level ) ->
|
|
||||||
|
|
||||||
if !level
|
|
||||||
level = '_all'
|
|
||||||
|
|
||||||
if !@eventCurrent[level]
|
|
||||||
@eventCurrent[level] = []
|
|
||||||
|
|
||||||
eventList = events.split(' ')
|
|
||||||
for event in eventList
|
|
||||||
|
|
||||||
# remove from
|
|
||||||
@eventCurrent[level] = _.filter( @eventCurrent[level], (item) ->
|
|
||||||
if callback
|
|
||||||
return item if item.event isnt event && item.callback isnt callback
|
|
||||||
else
|
|
||||||
return item if item.event isnt event
|
|
||||||
)
|
|
||||||
Spine.unbind( event, callback )
|
|
||||||
|
|
||||||
trigger: ( events, data ) ->
|
|
||||||
eventList = events.split(' ')
|
|
||||||
for event in eventList
|
|
||||||
Spine.trigger event, data
|
|
||||||
|
|
||||||
_allBindings: ->
|
|
||||||
@eventCurrent
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,169 +0,0 @@
|
||||||
$ = jQuery.sub()
|
|
||||||
|
|
||||||
class App.i18n
|
|
||||||
_instance = undefined
|
|
||||||
|
|
||||||
@init: ->
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
|
|
||||||
@translateContent: ( string, args... ) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.translate_content( string, args )
|
|
||||||
|
|
||||||
@translateInline: ( string, args... ) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.translate_inline( string, args )
|
|
||||||
|
|
||||||
@translateTimestamp: ( args ) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.timestamp( args )
|
|
||||||
|
|
||||||
class _Singleton
|
|
||||||
|
|
||||||
constructor: ->
|
|
||||||
@locale = 'de'
|
|
||||||
@timestampFormat = 'yyyy-mm-dd HH:MM'
|
|
||||||
@set( @locale )
|
|
||||||
|
|
||||||
# $('.translation [contenteditable]')
|
|
||||||
$('body')
|
|
||||||
.delegate '.translation', 'focus', (e) =>
|
|
||||||
$this = $(e.target)
|
|
||||||
$this.data 'before', $this.html()
|
|
||||||
# console.log('11111current', $this.html())
|
|
||||||
return $this
|
|
||||||
# .delegate '.translation', 'blur keyup paste', (e) =>
|
|
||||||
.delegate '.translation', 'blur', (e) =>
|
|
||||||
$this = $(e.target)
|
|
||||||
source = $this.attr('data-text')
|
|
||||||
|
|
||||||
# get new translation
|
|
||||||
translation_new = $this.html()
|
|
||||||
translation_new = ('' + translation_new)
|
|
||||||
.replace(/<.+?>/g, '')
|
|
||||||
|
|
||||||
# set new translation
|
|
||||||
$this.html(translation_new)
|
|
||||||
|
|
||||||
# update translation
|
|
||||||
return if $this.data('before') is translation_new
|
|
||||||
console.log 'Translation Update', translation_new, $this.data 'before'
|
|
||||||
$this.data 'before', translation_new
|
|
||||||
|
|
||||||
# update runtime translation map
|
|
||||||
@map[ source ] = translation_new
|
|
||||||
|
|
||||||
# replace rest in page
|
|
||||||
$(".translation[data-text='#{source}']").html( translation_new )
|
|
||||||
|
|
||||||
# update permanent translation map
|
|
||||||
translation = App.Collection.findByAttribute( 'Translation', 'source', source )
|
|
||||||
if translation
|
|
||||||
translation.updateAttribute( 'target', translation_new )
|
|
||||||
else
|
|
||||||
translation = new App.Translation
|
|
||||||
translation.load(
|
|
||||||
locale: @locale,
|
|
||||||
source: source,
|
|
||||||
target: translation_new,
|
|
||||||
)
|
|
||||||
translation.save()
|
|
||||||
|
|
||||||
return $this
|
|
||||||
|
|
||||||
set: ( locale ) ->
|
|
||||||
@map = {}
|
|
||||||
App.Com.ajax(
|
|
||||||
id: 'i18n-set-' + locale,
|
|
||||||
type: 'GET',
|
|
||||||
url: '/translations/lang/' + locale,
|
|
||||||
async: false,
|
|
||||||
success: (data, status, xhr) =>
|
|
||||||
|
|
||||||
# set timestamp format
|
|
||||||
if data.timestampFormat
|
|
||||||
@timestampFormat = data.timestampFormat
|
|
||||||
|
|
||||||
# load translation collection
|
|
||||||
for object in data.list
|
|
||||||
|
|
||||||
# set runtime lookup table
|
|
||||||
@map[ object[1] ] = object[2]
|
|
||||||
|
|
||||||
# load in collection if needed
|
|
||||||
App.Translation.refresh( { id: object[0], source: object[1], target: object[2], locale: @locale } )
|
|
||||||
|
|
||||||
error: (xhr, statusText, error) =>
|
|
||||||
console.log 'error', error, statusText, xhr.statusCode
|
|
||||||
)
|
|
||||||
|
|
||||||
translate_inline: ( string, args... ) =>
|
|
||||||
@translate( string, args... )
|
|
||||||
|
|
||||||
translate_content: ( string, args... ) =>
|
|
||||||
translated = @translate( string, args... )
|
|
||||||
# replace = '<span class="translation" contenteditable="true" data-text="' + @escape(string) + '">' + translated + '<span class="icon-edit"></span>'
|
|
||||||
if window.Config['Translation']
|
|
||||||
replace = '<span class="translation" contenteditable="true" data-text="' + @escape(string) + '">' + translated + ''
|
|
||||||
# if !@_translated
|
|
||||||
# replace += '<span class="missing">XX</span>'
|
|
||||||
replace += '</span>'
|
|
||||||
else
|
|
||||||
translated
|
|
||||||
|
|
||||||
translate: ( string, args... ) =>
|
|
||||||
|
|
||||||
# return '' on undefined
|
|
||||||
return '' if string is undefined
|
|
||||||
|
|
||||||
# return translation
|
|
||||||
if @map[string] isnt undefined
|
|
||||||
@_translated = true
|
|
||||||
translated = @map[string]
|
|
||||||
else
|
|
||||||
@_translated = false
|
|
||||||
translated = string
|
|
||||||
|
|
||||||
# search %s
|
|
||||||
for arg in args
|
|
||||||
translated = translated.replace(/%s/, arg)
|
|
||||||
|
|
||||||
# escape
|
|
||||||
translated = @escape(translated)
|
|
||||||
|
|
||||||
# return translated string
|
|
||||||
return translated
|
|
||||||
|
|
||||||
escape: ( string ) ->
|
|
||||||
string = ( '' + string )
|
|
||||||
.replace(/&/g, '&')
|
|
||||||
.replace(/</g, '<')
|
|
||||||
.replace(/>/g, '>')
|
|
||||||
.replace(/\x22/g, '"')
|
|
||||||
|
|
||||||
timestamp: ( time ) =>
|
|
||||||
s = ( num, digits ) ->
|
|
||||||
while num.toString().length < digits
|
|
||||||
num = "0" + num
|
|
||||||
return num
|
|
||||||
|
|
||||||
timeObject = new Date(time)
|
|
||||||
d = timeObject.getDate()
|
|
||||||
m = timeObject.getMonth() + 1
|
|
||||||
y = timeObject.getFullYear()
|
|
||||||
S = timeObject.getSeconds()
|
|
||||||
M = timeObject.getMinutes()
|
|
||||||
H = timeObject.getHours()
|
|
||||||
format = @timestampFormat
|
|
||||||
format = format.replace /dd/, s( d, 2 )
|
|
||||||
format = format.replace /d/, d
|
|
||||||
format = format.replace /mm/, s( m, 2 )
|
|
||||||
format = format.replace /m/, m
|
|
||||||
format = format.replace /yyyy/, y
|
|
||||||
format = format.replace /SS/, s( S, 2 )
|
|
||||||
format = format.replace /MM/, s( M, 2 )
|
|
||||||
format = format.replace /HH/, s( H, 2 )
|
|
||||||
return format
|
|
|
@ -1,76 +0,0 @@
|
||||||
|
|
||||||
class App.Run extends App.Controller
|
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
@log 'RUN app'
|
|
||||||
@el = $('#app')
|
|
||||||
|
|
||||||
# init collections
|
|
||||||
App.Collection.init()
|
|
||||||
|
|
||||||
# create web socket connection
|
|
||||||
App.WebSocket.connect()
|
|
||||||
|
|
||||||
# init of i18n
|
|
||||||
App.i18n.init()
|
|
||||||
|
|
||||||
# start navigation controller
|
|
||||||
new App.Navigation( el: @el.find('#navigation') )
|
|
||||||
|
|
||||||
# check if session already exists/try to get session data from server
|
|
||||||
App.Auth.loginCheck()
|
|
||||||
|
|
||||||
# start notify controller
|
|
||||||
new App.Notify( el: @el.find('#notify') )
|
|
||||||
|
|
||||||
# start content
|
|
||||||
new App.Content( el: @el.find('#content') )
|
|
||||||
|
|
||||||
# bind to fill selected text into
|
|
||||||
App.ClipBoard.bind( @el )
|
|
||||||
|
|
||||||
class App.Content extends Spine.Controller
|
|
||||||
className: 'container'
|
|
||||||
|
|
||||||
constructor: ->
|
|
||||||
super
|
|
||||||
@log 'RUN content'
|
|
||||||
|
|
||||||
for route, callback of Config.Routes
|
|
||||||
do (route, callback) =>
|
|
||||||
@route(route, (params) ->
|
|
||||||
|
|
||||||
# remove observers for page
|
|
||||||
App.Collection.observeUnbindLevel('page')
|
|
||||||
|
|
||||||
# remove events for page
|
|
||||||
App.Event.unbindLevel('page')
|
|
||||||
|
|
||||||
# unbind in controller area
|
|
||||||
@el.unbind()
|
|
||||||
@el.undelegate()
|
|
||||||
|
|
||||||
# send current controller
|
|
||||||
params_only = {}
|
|
||||||
for i of params
|
|
||||||
if typeof params[i] isnt 'object'
|
|
||||||
params_only[i] = params[i]
|
|
||||||
|
|
||||||
# tell server what we are calling right now
|
|
||||||
App.WebSocket.send(
|
|
||||||
action: 'active_controller',
|
|
||||||
controller: route,
|
|
||||||
params: params_only,
|
|
||||||
)
|
|
||||||
|
|
||||||
# remove waypoints
|
|
||||||
$('footer').waypoint('remove')
|
|
||||||
|
|
||||||
params.el = @el
|
|
||||||
new callback( params )
|
|
||||||
|
|
||||||
# scroll to top
|
|
||||||
# window.scrollTo(0,0)
|
|
||||||
)
|
|
||||||
|
|
||||||
Spine.Route.setup()
|
|
File diff suppressed because one or more lines are too long
9301
app/assets/javascripts/app/lib/jquery-1.8.1.js
vendored
9301
app/assets/javascripts/app/lib/jquery-1.8.1.js
vendored
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
@ -1,162 +0,0 @@
|
||||||
/**
|
|
||||||
* @name Elastic
|
|
||||||
* @descripton Elastic is jQuery plugin that grow and shrink your textareas automatically
|
|
||||||
* @version 1.6.11
|
|
||||||
* @requires jQuery 1.2.6+
|
|
||||||
*
|
|
||||||
* @author Jan Jarfalk
|
|
||||||
* @author-email jan.jarfalk@unwrongest.com
|
|
||||||
* @author-website http://www.unwrongest.com
|
|
||||||
*
|
|
||||||
* @licence MIT License - http://www.opensource.org/licenses/mit-license.php
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function($){
|
|
||||||
jQuery.fn.extend({
|
|
||||||
elastic: function() {
|
|
||||||
|
|
||||||
// We will create a div clone of the textarea
|
|
||||||
// by copying these attributes from the textarea to the div.
|
|
||||||
var mimics = [
|
|
||||||
'paddingTop',
|
|
||||||
'paddingRight',
|
|
||||||
'paddingBottom',
|
|
||||||
'paddingLeft',
|
|
||||||
'fontSize',
|
|
||||||
'lineHeight',
|
|
||||||
'fontFamily',
|
|
||||||
'width',
|
|
||||||
'fontWeight',
|
|
||||||
'border-top-width',
|
|
||||||
'border-right-width',
|
|
||||||
'border-bottom-width',
|
|
||||||
'border-left-width',
|
|
||||||
'borderTopStyle',
|
|
||||||
'borderTopColor',
|
|
||||||
'borderRightStyle',
|
|
||||||
'borderRightColor',
|
|
||||||
'borderBottomStyle',
|
|
||||||
'borderBottomColor',
|
|
||||||
'borderLeftStyle',
|
|
||||||
'borderLeftColor'
|
|
||||||
];
|
|
||||||
|
|
||||||
return this.each( function() {
|
|
||||||
|
|
||||||
// Elastic only works on textareas
|
|
||||||
if ( this.type !== 'textarea' ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var $textarea = jQuery(this),
|
|
||||||
$twin = jQuery('<div />').css({
|
|
||||||
'position' : 'absolute',
|
|
||||||
'display' : 'none',
|
|
||||||
'word-wrap' : 'break-word',
|
|
||||||
'white-space' :'pre-wrap'
|
|
||||||
}),
|
|
||||||
lineHeight = parseInt($textarea.css('line-height'),10) || parseInt($textarea.css('font-size'),'10'),
|
|
||||||
minheight = parseInt($textarea.css('height'),10) || lineHeight*3,
|
|
||||||
maxheight = parseInt($textarea.css('max-height'),10) || Number.MAX_VALUE,
|
|
||||||
goalheight = 0;
|
|
||||||
|
|
||||||
// Opera returns max-height of -1 if not set
|
|
||||||
if (maxheight < 0) { maxheight = Number.MAX_VALUE; }
|
|
||||||
|
|
||||||
// Append the twin to the DOM
|
|
||||||
// We are going to meassure the height of this, not the textarea.
|
|
||||||
$twin.appendTo($textarea.parent());
|
|
||||||
|
|
||||||
// Copy the essential styles (mimics) from the textarea to the twin
|
|
||||||
var i = mimics.length;
|
|
||||||
while(i--){
|
|
||||||
$twin.css(mimics[i].toString(),$textarea.css(mimics[i].toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Updates the width of the twin. (solution for textareas with widths in percent)
|
|
||||||
function setTwinWidth(){
|
|
||||||
var curatedWidth = Math.floor(parseInt($textarea.width(),10));
|
|
||||||
if($twin.width() !== curatedWidth){
|
|
||||||
$twin.css({'width': curatedWidth + 'px'});
|
|
||||||
|
|
||||||
// Update height of textarea
|
|
||||||
update(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets a given height and overflow state on the textarea
|
|
||||||
function setHeightAndOverflow(height, overflow){
|
|
||||||
|
|
||||||
var curratedHeight = Math.floor(parseInt(height,10));
|
|
||||||
if($textarea.height() !== curratedHeight){
|
|
||||||
$textarea.css({'height': curratedHeight + 'px','overflow':overflow});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function will update the height of the textarea if necessary
|
|
||||||
function update(forced) {
|
|
||||||
|
|
||||||
// Get curated content from the textarea.
|
|
||||||
var textareaContent = $textarea.val().replace(/&/g,'&').replace(/ {2}/g, ' ').replace(/<|>/g, '>').replace(/\n/g, '<br />');
|
|
||||||
|
|
||||||
// Compare curated content with curated twin.
|
|
||||||
var twinContent = $twin.html().replace(/<br>/ig,'<br />');
|
|
||||||
|
|
||||||
if(forced || textareaContent+' ' !== twinContent){
|
|
||||||
|
|
||||||
// Add an extra white space so new rows are added when you are at the end of a row.
|
|
||||||
$twin.html(textareaContent+' ');
|
|
||||||
|
|
||||||
// Change textarea height if twin plus the height of one line differs more than 3 pixel from textarea height
|
|
||||||
if(Math.abs($twin.height() + lineHeight - $textarea.height()) > 3){
|
|
||||||
|
|
||||||
var goalheight = $twin.height()+lineHeight;
|
|
||||||
if(goalheight >= maxheight) {
|
|
||||||
setHeightAndOverflow(maxheight,'auto');
|
|
||||||
} else if(goalheight <= minheight) {
|
|
||||||
setHeightAndOverflow(minheight,'hidden');
|
|
||||||
} else {
|
|
||||||
setHeightAndOverflow(goalheight,'hidden');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide scrollbars
|
|
||||||
$textarea.css({'overflow':'hidden'});
|
|
||||||
|
|
||||||
// Update textarea size on keyup, change, cut and paste
|
|
||||||
$textarea.bind('keyup change cut paste', function(){
|
|
||||||
update();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update width of twin if browser or textarea is resized (solution for textareas with widths in percent)
|
|
||||||
$(window).bind('resize', setTwinWidth);
|
|
||||||
$textarea.bind('resize', setTwinWidth);
|
|
||||||
$textarea.bind('update', update);
|
|
||||||
|
|
||||||
// Compact textarea on blur
|
|
||||||
$textarea.bind('blur',function(){
|
|
||||||
if($twin.height() < maxheight){
|
|
||||||
if($twin.height() > minheight) {
|
|
||||||
$textarea.height($twin.height());
|
|
||||||
} else {
|
|
||||||
$textarea.height(minheight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// And this line is to catch the browser paste event
|
|
||||||
$textarea.bind('input paste',function(e){ setTimeout( update, 250); });
|
|
||||||
|
|
||||||
// Run update once when elastic is initialized
|
|
||||||
update();
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})(jQuery);
|
|
|
@ -1,220 +0,0 @@
|
||||||
/**
|
|
||||||
* jQuery Noty Plugin v1.1.1
|
|
||||||
* Authors: Nedim Arabacı (http://ned.im), Muhittin Özer (http://muhittinozer.com)
|
|
||||||
*
|
|
||||||
* Examples and Documentation - http://needim.github.com/noty/
|
|
||||||
*
|
|
||||||
* Licensed under the MIT licenses:
|
|
||||||
* http://www.opensource.org/licenses/mit-license.php
|
|
||||||
*
|
|
||||||
**/
|
|
||||||
(function($) {
|
|
||||||
$.noty = function(options, customContainer) {
|
|
||||||
|
|
||||||
var base = this;
|
|
||||||
var $noty = null;
|
|
||||||
var isCustom = false;
|
|
||||||
|
|
||||||
base.init = function(options) {
|
|
||||||
base.options = $.extend({}, $.noty.defaultOptions, options);
|
|
||||||
base.options.type = base.options.cssPrefix+base.options.type;
|
|
||||||
base.options.id = base.options.type+'_'+new Date().getTime();
|
|
||||||
base.options.layout = base.options.cssPrefix+'layout_'+base.options.layout;
|
|
||||||
|
|
||||||
if (base.options.custom.container) customContainer = base.options.custom.container;
|
|
||||||
isCustom = ($.type(customContainer) === 'object') ? true : false;
|
|
||||||
|
|
||||||
return base.addQueue();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Push notification to queue
|
|
||||||
base.addQueue = function() {
|
|
||||||
var isGrowl = ($.inArray(base.options.layout, $.noty.growls) == -1) ? false : true;
|
|
||||||
if (!isGrowl) (base.options.force) ? $.noty.queue.unshift({options: base.options}) : $.noty.queue.push({options: base.options});
|
|
||||||
return base.render(isGrowl);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Render the noty
|
|
||||||
base.render = function(isGrowl) {
|
|
||||||
|
|
||||||
// Layout spesific container settings
|
|
||||||
var container = (isCustom) ? customContainer.addClass(base.options.theme+' '+base.options.layout+' noty_custom_container') : $('body');
|
|
||||||
if (isGrowl) {
|
|
||||||
if ($('ul.noty_cont.' + base.options.layout).length == 0)
|
|
||||||
container.prepend($('<ul/>').addClass('noty_cont ' + base.options.layout));
|
|
||||||
container = $('ul.noty_cont.' + base.options.layout);
|
|
||||||
} else {
|
|
||||||
if ($.noty.available) {
|
|
||||||
var fromQueue = $.noty.queue.shift(); // Get noty from queue
|
|
||||||
if ($.type(fromQueue) === 'object') {
|
|
||||||
$.noty.available = false;
|
|
||||||
base.options = fromQueue.options;
|
|
||||||
} else {
|
|
||||||
$.noty.available = true; // Queue is over
|
|
||||||
return base.options.id;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return base.options.id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
base.container = container;
|
|
||||||
|
|
||||||
// Generating noty bar
|
|
||||||
base.bar = $('<div class="noty_bar"/>').attr('id', base.options.id).addClass(base.options.theme+' '+base.options.layout+' '+base.options.type);
|
|
||||||
$noty = base.bar;
|
|
||||||
$noty.append(base.options.template).find('.noty_text').html(base.options.text);
|
|
||||||
$noty.data('noty_options', base.options);
|
|
||||||
|
|
||||||
// Close button display
|
|
||||||
(base.options.closeButton) ? $noty.addClass('noty_closable').find('.noty_close').show() : $noty.find('.noty_close').remove();
|
|
||||||
|
|
||||||
// Bind close event to button
|
|
||||||
$noty.find('.noty_close').bind('click', function() { $noty.trigger('noty.close'); });
|
|
||||||
|
|
||||||
// If we have a button we must disable closeOnSelfClick and closeOnSelfOver option
|
|
||||||
if (base.options.buttons) base.options.closeOnSelfClick = base.options.closeOnSelfOver = false;
|
|
||||||
// Close on self click
|
|
||||||
if (base.options.closeOnSelfClick) $noty.bind('click', function() { $noty.trigger('noty.close'); }).css('cursor', 'pointer');
|
|
||||||
// Close on self mouseover
|
|
||||||
if (base.options.closeOnSelfOver) $noty.bind('mouseover', function() { $noty.trigger('noty.close'); }).css('cursor', 'pointer');
|
|
||||||
|
|
||||||
// Set buttons if available
|
|
||||||
if (base.options.buttons) {
|
|
||||||
$buttons = $('<div/>').addClass('noty_buttons');
|
|
||||||
$noty.find('.noty_message').append($buttons);
|
|
||||||
$.each(base.options.buttons, function(i, button) {
|
|
||||||
bclass = (button.type) ? button.type : 'gray';
|
|
||||||
$button = $('<button/>').addClass(bclass).html(button.text).appendTo($noty.find('.noty_buttons'))
|
|
||||||
.bind('click', function() {
|
|
||||||
if ($.isFunction(button.click)) {
|
|
||||||
button.click.call($button, $noty);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.show(isGrowl);
|
|
||||||
};
|
|
||||||
|
|
||||||
base.show = function(isGrowl) {
|
|
||||||
|
|
||||||
// is Modal?
|
|
||||||
if (base.options.modal) $('<div/>').addClass('noty_modal').addClass(base.options.theme).prependTo($('body')).fadeIn('fast');
|
|
||||||
|
|
||||||
$noty.close = function() { return this.trigger('noty.close'); };
|
|
||||||
|
|
||||||
// Prepend noty to container
|
|
||||||
(isGrowl) ? base.container.prepend($('<li/>').append($noty)) : base.container.prepend($noty);
|
|
||||||
|
|
||||||
// topCenter and center specific options
|
|
||||||
if (base.options.layout == 'noty_layout_topCenter' || base.options.layout == 'noty_layout_center') {
|
|
||||||
$.noty.reCenter($noty);
|
|
||||||
}
|
|
||||||
|
|
||||||
$noty.bind('noty.setText', function(event, text) {
|
|
||||||
$noty.find('.noty_text').html(text); $.noty.reCenter($noty);
|
|
||||||
});
|
|
||||||
|
|
||||||
$noty.bind('noty.getId', function(event) {
|
|
||||||
return $noty.data('noty_options').id;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Bind close event
|
|
||||||
$noty.one('noty.close', function(event) {
|
|
||||||
var options = $noty.data('noty_options');
|
|
||||||
|
|
||||||
// Modal Cleaning
|
|
||||||
if (options.modal) $('.noty_modal').fadeOut('fast', function() { $(this).remove(); });
|
|
||||||
|
|
||||||
$noty.clearQueue().stop().animate(
|
|
||||||
$noty.data('noty_options').animateClose,
|
|
||||||
$noty.data('noty_options').speed,
|
|
||||||
$noty.data('noty_options').easing,
|
|
||||||
$noty.data('noty_options').onClose)
|
|
||||||
.promise().done(function() {
|
|
||||||
|
|
||||||
// Layout spesific cleaning
|
|
||||||
if ($.inArray($noty.data('noty_options').layout, $.noty.growls) > -1) {
|
|
||||||
$noty.parent().remove();
|
|
||||||
} else {
|
|
||||||
$noty.remove();
|
|
||||||
|
|
||||||
// queue render
|
|
||||||
$.noty.available = true;
|
|
||||||
base.render(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Start the show
|
|
||||||
$noty.animate(base.options.animateOpen, base.options.speed, base.options.easing, base.options.onShow);
|
|
||||||
|
|
||||||
// If noty is have a timeout option
|
|
||||||
if (base.options.timeout) $noty.delay(base.options.timeout).promise().done(function() { $noty.trigger('noty.close'); });
|
|
||||||
return base.options.id;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Run initializer
|
|
||||||
return base.init(options);
|
|
||||||
};
|
|
||||||
|
|
||||||
// API
|
|
||||||
$.noty.get = function(id) { return $('#'+id); };
|
|
||||||
$.noty.close = function(id) {
|
|
||||||
$.noty.get(id).trigger('noty.close');
|
|
||||||
};
|
|
||||||
$.noty.setText = function(id, text) {
|
|
||||||
$.noty.get(id).trigger('noty.setText', text);
|
|
||||||
};
|
|
||||||
$.noty.closeAll = function() {
|
|
||||||
$.noty.clearQueue();
|
|
||||||
$('.noty_bar').trigger('noty.close');
|
|
||||||
};
|
|
||||||
$.noty.reCenter = function(noty) {
|
|
||||||
noty.css({'left': ($(window).width() - noty.outerWidth()) / 2 + 'px'});
|
|
||||||
};
|
|
||||||
$.noty.clearQueue = function() {
|
|
||||||
$.noty.queue = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
$.noty.queue = [];
|
|
||||||
$.noty.growls = ['noty_layout_topLeft', 'noty_layout_topRight', 'noty_layout_bottomLeft', 'noty_layout_bottomRight'];
|
|
||||||
$.noty.available = true;
|
|
||||||
$.noty.defaultOptions = {
|
|
||||||
layout: 'top',
|
|
||||||
theme: 'noty_theme_default',
|
|
||||||
animateOpen: {height: 'toggle'},
|
|
||||||
animateClose: {height: 'toggle'},
|
|
||||||
easing: 'swing',
|
|
||||||
text: '',
|
|
||||||
type: 'alert',
|
|
||||||
speed: 500,
|
|
||||||
timeout: 5000,
|
|
||||||
closeButton: false,
|
|
||||||
closeOnSelfClick: true,
|
|
||||||
closeOnSelfOver: false,
|
|
||||||
force: false,
|
|
||||||
onShow: false,
|
|
||||||
onClose: false,
|
|
||||||
buttons: false,
|
|
||||||
modal: false,
|
|
||||||
template: '<div class="noty_message"><span class="noty_text"></span><div class="noty_close"></div></div>',
|
|
||||||
cssPrefix: 'noty_',
|
|
||||||
custom: {
|
|
||||||
container: null
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$.fn.noty = function(options) {
|
|
||||||
return this.each(function() {
|
|
||||||
(new $.noty(options, $(this)));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
})(jQuery);
|
|
||||||
|
|
||||||
//Helper
|
|
||||||
function noty(options) {
|
|
||||||
return jQuery.noty(options); // returns an id
|
|
||||||
}
|
|
|
@ -1,353 +0,0 @@
|
||||||
/*
|
|
||||||
|
|
||||||
jQuery Tags Input Plugin 1.3.3
|
|
||||||
|
|
||||||
Copyright (c) 2011 XOXCO, Inc
|
|
||||||
|
|
||||||
Documentation for this plugin lives here:
|
|
||||||
http://xoxco.com/clickable/jquery-tags-input
|
|
||||||
|
|
||||||
Licensed under the MIT license:
|
|
||||||
http://www.opensource.org/licenses/mit-license.php
|
|
||||||
|
|
||||||
ben@xoxco.com
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function($) {
|
|
||||||
|
|
||||||
var delimiter = new Array();
|
|
||||||
var tags_callbacks = new Array();
|
|
||||||
$.fn.doAutosize = function(o){
|
|
||||||
var minWidth = $(this).data('minwidth'),
|
|
||||||
maxWidth = $(this).data('maxwidth'),
|
|
||||||
val = '',
|
|
||||||
input = $(this),
|
|
||||||
testSubject = $('#'+$(this).data('tester_id'));
|
|
||||||
|
|
||||||
if (val === (val = input.val())) {return;}
|
|
||||||
|
|
||||||
// Enter new content into testSubject
|
|
||||||
var escaped = val.replace(/&/g, '&').replace(/\s/g,' ').replace(/</g, '<').replace(/>/g, '>');
|
|
||||||
testSubject.html(escaped);
|
|
||||||
// Calculate new width + whether to change
|
|
||||||
var testerWidth = testSubject.width(),
|
|
||||||
newWidth = (testerWidth + o.comfortZone) >= minWidth ? testerWidth + o.comfortZone : minWidth,
|
|
||||||
currentWidth = input.width(),
|
|
||||||
isValidWidthChange = (newWidth < currentWidth && newWidth >= minWidth)
|
|
||||||
|| (newWidth > minWidth && newWidth < maxWidth);
|
|
||||||
|
|
||||||
// Animate width
|
|
||||||
if (isValidWidthChange) {
|
|
||||||
input.width(newWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
$.fn.resetAutosize = function(options){
|
|
||||||
// alert(JSON.stringify(options));
|
|
||||||
var minWidth = $(this).data('minwidth') || options.minInputWidth || $(this).width(),
|
|
||||||
maxWidth = $(this).data('maxwidth') || options.maxInputWidth || ($(this).closest('.tagsinput').width() - options.inputPadding),
|
|
||||||
val = '',
|
|
||||||
input = $(this),
|
|
||||||
testSubject = $('<tester/>').css({
|
|
||||||
position: 'absolute',
|
|
||||||
top: -9999,
|
|
||||||
left: -9999,
|
|
||||||
width: 'auto',
|
|
||||||
fontSize: input.css('fontSize'),
|
|
||||||
fontFamily: input.css('fontFamily'),
|
|
||||||
fontWeight: input.css('fontWeight'),
|
|
||||||
letterSpacing: input.css('letterSpacing'),
|
|
||||||
whiteSpace: 'nowrap'
|
|
||||||
}),
|
|
||||||
testerId = $(this).attr('id')+'_autosize_tester';
|
|
||||||
if(! $('#'+testerId).length > 0){
|
|
||||||
testSubject.attr('id', testerId);
|
|
||||||
testSubject.appendTo('body');
|
|
||||||
}
|
|
||||||
|
|
||||||
input.data('minwidth', minWidth);
|
|
||||||
input.data('maxwidth', maxWidth);
|
|
||||||
input.data('tester_id', testerId);
|
|
||||||
input.css('width', minWidth);
|
|
||||||
};
|
|
||||||
|
|
||||||
$.fn.addTag = function(value,options) {
|
|
||||||
options = jQuery.extend({focus:false,callback:true},options);
|
|
||||||
this.each(function() {
|
|
||||||
var id = $(this).attr('id');
|
|
||||||
|
|
||||||
var tagslist = $(this).val().split(delimiter[id]);
|
|
||||||
if (tagslist[0] == '') {
|
|
||||||
tagslist = new Array();
|
|
||||||
}
|
|
||||||
|
|
||||||
value = jQuery.trim(value);
|
|
||||||
|
|
||||||
if (options.unique) {
|
|
||||||
var skipTag = $(tagslist).tagExist(value);
|
|
||||||
if(skipTag == true) {
|
|
||||||
//Marks fake input as not_valid to let styling it
|
|
||||||
$('#'+id+'_tag').addClass('not_valid');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var skipTag = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value !='' && skipTag != true) {
|
|
||||||
$('<span>').addClass('tag').append(
|
|
||||||
$('<span>').text(value).append(' '),
|
|
||||||
$('<a>', {
|
|
||||||
href : '#',
|
|
||||||
title : 'Removing tag',
|
|
||||||
text : 'x'
|
|
||||||
}).click(function () {
|
|
||||||
return $('#' + id).removeTag(escape(value));
|
|
||||||
})
|
|
||||||
).insertBefore('#' + id + '_addTag');
|
|
||||||
|
|
||||||
tagslist.push(value);
|
|
||||||
|
|
||||||
$('#'+id+'_tag').val('');
|
|
||||||
if (options.focus) {
|
|
||||||
$('#'+id+'_tag').focus();
|
|
||||||
} else {
|
|
||||||
$('#'+id+'_tag').blur();
|
|
||||||
}
|
|
||||||
|
|
||||||
$.fn.tagsInput.updateTagsField(this,tagslist);
|
|
||||||
|
|
||||||
if (options.callback && tags_callbacks[id] && tags_callbacks[id]['onAddTag']) {
|
|
||||||
var f = tags_callbacks[id]['onAddTag'];
|
|
||||||
f.call(this, value);
|
|
||||||
}
|
|
||||||
if(tags_callbacks[id] && tags_callbacks[id]['onChange'])
|
|
||||||
{
|
|
||||||
var i = tagslist.length;
|
|
||||||
var f = tags_callbacks[id]['onChange'];
|
|
||||||
f.call(this, $(this), tagslist[i-1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
$.fn.removeTag = function(value) {
|
|
||||||
value = unescape(value);
|
|
||||||
this.each(function() {
|
|
||||||
var id = $(this).attr('id');
|
|
||||||
|
|
||||||
var old = $(this).val().split(delimiter[id]);
|
|
||||||
|
|
||||||
$('#'+id+'_tagsinput .tag').remove();
|
|
||||||
str = '';
|
|
||||||
for (i=0; i< old.length; i++) {
|
|
||||||
if (old[i]!=value) {
|
|
||||||
str = str + delimiter[id] +old[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$.fn.tagsInput.importTags(this,str);
|
|
||||||
|
|
||||||
if (tags_callbacks[id] && tags_callbacks[id]['onRemoveTag']) {
|
|
||||||
var f = tags_callbacks[id]['onRemoveTag'];
|
|
||||||
f.call(this, value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
$.fn.tagExist = function(val) {
|
|
||||||
return (jQuery.inArray(val, $(this)) >= 0); //true when tag exists, false when not
|
|
||||||
};
|
|
||||||
|
|
||||||
// clear all existing tags and import new ones from a string
|
|
||||||
$.fn.importTags = function(str) {
|
|
||||||
id = $(this).attr('id');
|
|
||||||
$('#'+id+'_tagsinput .tag').remove();
|
|
||||||
$.fn.tagsInput.importTags(this,str);
|
|
||||||
}
|
|
||||||
|
|
||||||
$.fn.tagsInput = function(options) {
|
|
||||||
var settings = jQuery.extend({
|
|
||||||
interactive:true,
|
|
||||||
defaultText:'add a tag',
|
|
||||||
minChars:0,
|
|
||||||
width:'300px',
|
|
||||||
height:'100px',
|
|
||||||
autocomplete: {selectFirst: false },
|
|
||||||
'hide':true,
|
|
||||||
'delimiter':',',
|
|
||||||
'unique':true,
|
|
||||||
removeWithBackspace:true,
|
|
||||||
placeholderColor:'#666666',
|
|
||||||
autosize: true,
|
|
||||||
comfortZone: 20,
|
|
||||||
inputPadding: 6*2
|
|
||||||
},options);
|
|
||||||
|
|
||||||
this.each(function() {
|
|
||||||
if (settings.hide) {
|
|
||||||
$(this).hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
var id = $(this).attr('id')
|
|
||||||
|
|
||||||
var data = jQuery.extend({
|
|
||||||
pid:id,
|
|
||||||
real_input: '#'+id,
|
|
||||||
holder: '#'+id+'_tagsinput',
|
|
||||||
input_wrapper: '#'+id+'_addTag',
|
|
||||||
fake_input: '#'+id+'_tag'
|
|
||||||
},settings);
|
|
||||||
|
|
||||||
delimiter[id] = data.delimiter;
|
|
||||||
|
|
||||||
if (settings.onAddTag || settings.onRemoveTag || settings.onChange) {
|
|
||||||
tags_callbacks[id] = new Array();
|
|
||||||
tags_callbacks[id]['onAddTag'] = settings.onAddTag;
|
|
||||||
tags_callbacks[id]['onRemoveTag'] = settings.onRemoveTag;
|
|
||||||
tags_callbacks[id]['onChange'] = settings.onChange;
|
|
||||||
}
|
|
||||||
|
|
||||||
var markup = '<div id="'+id+'_tagsinput" class="tagsinput"><div id="'+id+'_addTag">';
|
|
||||||
|
|
||||||
if (settings.interactive) {
|
|
||||||
markup = markup + '<input id="'+id+'_tag" value="" data-default="'+settings.defaultText+'" />';
|
|
||||||
}
|
|
||||||
|
|
||||||
markup = markup + '</div><div class="tags_clear"></div></div>';
|
|
||||||
|
|
||||||
$(markup).insertAfter(this);
|
|
||||||
|
|
||||||
$(data.holder).css('width',settings.width);
|
|
||||||
$(data.holder).css('height',settings.height);
|
|
||||||
|
|
||||||
if ($(data.real_input).val()!='') {
|
|
||||||
$.fn.tagsInput.importTags($(data.real_input),$(data.real_input).val());
|
|
||||||
}
|
|
||||||
if (settings.interactive) {
|
|
||||||
$(data.fake_input).val($(data.fake_input).attr('data-default'));
|
|
||||||
$(data.fake_input).css('color',settings.placeholderColor);
|
|
||||||
$(data.fake_input).resetAutosize(settings);
|
|
||||||
|
|
||||||
$(data.holder).bind('click',data,function(event) {
|
|
||||||
$(event.data.fake_input).focus();
|
|
||||||
});
|
|
||||||
|
|
||||||
$(data.fake_input).bind('focus',data,function(event) {
|
|
||||||
if ($(event.data.fake_input).val()==$(event.data.fake_input).attr('data-default')) {
|
|
||||||
$(event.data.fake_input).val('');
|
|
||||||
}
|
|
||||||
$(event.data.fake_input).css('color','#000000');
|
|
||||||
});
|
|
||||||
|
|
||||||
if (settings.autocomplete_url != undefined) {
|
|
||||||
// 2012-02-23 me
|
|
||||||
// autocomplete_options = {source: settings.autocomplete_url};
|
|
||||||
autocomplete_options = settings.auto;
|
|
||||||
// 2012-02-23 me
|
|
||||||
for (attrname in settings.autocomplete) {
|
|
||||||
autocomplete_options[attrname] = settings.autocomplete[attrname];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jQuery.Autocompleter !== undefined) {
|
|
||||||
$(data.fake_input).autocomplete(settings.autocomplete_url, settings.autocomplete);
|
|
||||||
$(data.fake_input).bind('result',data,function(event,data,formatted) {
|
|
||||||
if (data) {
|
|
||||||
$('#'+id).addTag(data[0] + "",{focus:true,unique:(settings.unique)});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (jQuery.ui.autocomplete !== undefined) {
|
|
||||||
$(data.fake_input).autocomplete(autocomplete_options);
|
|
||||||
$(data.fake_input).bind('autocompleteselect',data,function(event,ui) {
|
|
||||||
$(event.data.real_input).addTag(ui.item.value,{focus:true,unique:(settings.unique)});
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// if a user tabs out of the field, create a new tag
|
|
||||||
// this is only available if autocomplete is not used.
|
|
||||||
$(data.fake_input).bind('blur',data,function(event) {
|
|
||||||
var d = $(this).attr('data-default');
|
|
||||||
if ($(event.data.fake_input).val()!='' && $(event.data.fake_input).val()!=d) {
|
|
||||||
if( (event.data.minChars <= $(event.data.fake_input).val().length) && (!event.data.maxChars || (event.data.maxChars >= $(event.data.fake_input).val().length)) )
|
|
||||||
$(event.data.real_input).addTag($(event.data.fake_input).val(),{focus:true,unique:(settings.unique)});
|
|
||||||
} else {
|
|
||||||
$(event.data.fake_input).val($(event.data.fake_input).attr('data-default'));
|
|
||||||
$(event.data.fake_input).css('color',settings.placeholderColor);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
// if user types a comma, create a new tag
|
|
||||||
$(data.fake_input).bind('keypress',data,function(event) {
|
|
||||||
if (event.which==event.data.delimiter.charCodeAt(0) || event.which==13 ) {
|
|
||||||
event.preventDefault();
|
|
||||||
if( (event.data.minChars <= $(event.data.fake_input).val().length) && (!event.data.maxChars || (event.data.maxChars >= $(event.data.fake_input).val().length)) )
|
|
||||||
$(event.data.real_input).addTag($(event.data.fake_input).val(),{focus:true,unique:(settings.unique)});
|
|
||||||
$(event.data.fake_input).resetAutosize(settings);
|
|
||||||
return false;
|
|
||||||
} else if (event.data.autosize) {
|
|
||||||
$(event.data.fake_input).doAutosize(settings);
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
//Delete last tag on backspace
|
|
||||||
data.removeWithBackspace && $(data.fake_input).bind('keydown', function(event)
|
|
||||||
{
|
|
||||||
if(event.keyCode == 8 && $(this).val() == '')
|
|
||||||
{
|
|
||||||
event.preventDefault();
|
|
||||||
var last_tag = $(this).closest('.tagsinput').find('.tag:last').text();
|
|
||||||
var id = $(this).attr('id').replace(/_tag$/, '');
|
|
||||||
last_tag = last_tag.replace(/[\s]+x$/, '');
|
|
||||||
$('#' + id).removeTag(escape(last_tag));
|
|
||||||
$(this).trigger('focus');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$(data.fake_input).blur();
|
|
||||||
|
|
||||||
//Removes the not_valid class when user changes the value of the fake input
|
|
||||||
if(data.unique) {
|
|
||||||
$(data.fake_input).keydown(function(event){
|
|
||||||
if(event.keyCode == 8 || String.fromCharCode(event.which).match(/\w+|[áéíóúÁÉÍÓÚñÑ,/]+/)) {
|
|
||||||
$(this).removeClass('not_valid');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} // if settings.interactive
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
return this;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
$.fn.tagsInput.updateTagsField = function(obj,tagslist) {
|
|
||||||
var id = $(obj).attr('id');
|
|
||||||
$(obj).val(tagslist.join(delimiter[id]));
|
|
||||||
};
|
|
||||||
|
|
||||||
$.fn.tagsInput.importTags = function(obj,val) {
|
|
||||||
$(obj).val('');
|
|
||||||
var id = $(obj).attr('id');
|
|
||||||
var tags = val.split(delimiter[id]);
|
|
||||||
for (i=0; i<tags.length; i++) {
|
|
||||||
$(obj).addTag(tags[i],{focus:false,callback:false});
|
|
||||||
}
|
|
||||||
if(tags_callbacks[id] && tags_callbacks[id]['onChange'])
|
|
||||||
{
|
|
||||||
var f = tags_callbacks[id]['onChange'];
|
|
||||||
f.call(obj, obj, tags[i]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
})(jQuery);
|
|
|
@ -1,61 +0,0 @@
|
||||||
class App.Store
|
|
||||||
_instance = undefined # Must be declared here to force the closure on the class
|
|
||||||
@renew: ->
|
|
||||||
_instance = new _Singleton
|
|
||||||
|
|
||||||
@write: (key, value) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.write(key, value)
|
|
||||||
|
|
||||||
@get: (args) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.get(args)
|
|
||||||
|
|
||||||
@delete: (args) ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.delete(args)
|
|
||||||
|
|
||||||
@clear: ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.clear()
|
|
||||||
|
|
||||||
@list: () ->
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance.list()
|
|
||||||
|
|
||||||
# The actual Singleton class
|
|
||||||
class _Singleton
|
|
||||||
|
|
||||||
# write to local storage
|
|
||||||
write: (key, value) ->
|
|
||||||
localStorage.setItem( key, JSON.stringify( value ) )
|
|
||||||
|
|
||||||
# get item
|
|
||||||
get: (key) ->
|
|
||||||
value = localStorage.getItem( key )
|
|
||||||
return if !value
|
|
||||||
object = JSON.parse( value )
|
|
||||||
return object
|
|
||||||
|
|
||||||
# delete item
|
|
||||||
delete: (key) ->
|
|
||||||
localStorage.removeItem( key )
|
|
||||||
|
|
||||||
# clear local storage
|
|
||||||
clear: ->
|
|
||||||
localStorage.clear()
|
|
||||||
|
|
||||||
# return list of all keys
|
|
||||||
list: ->
|
|
||||||
list = []
|
|
||||||
logLength = localStorage.length-1;
|
|
||||||
for count in [0..logLength]
|
|
||||||
key = localStorage.key( count )
|
|
||||||
if key
|
|
||||||
list.push key
|
|
||||||
list
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,674 +0,0 @@
|
||||||
/*!
|
|
||||||
jQuery Waypoints - v1.1.6
|
|
||||||
Copyright (c) 2011-2012 Caleb Troughton
|
|
||||||
Dual licensed under the MIT license and GPL license.
|
|
||||||
https://github.com/imakewebthings/jquery-waypoints/blob/master/MIT-license.txt
|
|
||||||
https://github.com/imakewebthings/jquery-waypoints/blob/master/GPL-license.txt
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Waypoints is a small jQuery plugin that makes it easy to execute a function
|
|
||||||
whenever you scroll to an element.
|
|
||||||
|
|
||||||
GitHub Repository: https://github.com/imakewebthings/jquery-waypoints
|
|
||||||
Documentation and Examples: http://imakewebthings.github.com/jquery-waypoints
|
|
||||||
|
|
||||||
Changelog:
|
|
||||||
v1.1.6
|
|
||||||
- Fix potential memory leak by unbinding events on empty context elements.
|
|
||||||
v1.1.5
|
|
||||||
- Make plugin compatible with Browserify/RequireJS. (Thanks @cjroebuck)
|
|
||||||
v1.1.4
|
|
||||||
- Add handler option to give alternate binding method. (Issue #34)
|
|
||||||
v1.1.3
|
|
||||||
- Fix cases where waypoints are added post-load and should be triggered
|
|
||||||
immediately. (Issue #28)
|
|
||||||
v1.1.2
|
|
||||||
- Fixed error thrown by waypoints with triggerOnce option that were
|
|
||||||
triggered via resize refresh.
|
|
||||||
v1.1.1
|
|
||||||
- Fixed bug in initialization where all offsets were being calculated
|
|
||||||
as if set to 0 initially, causing unwarranted triggers during the
|
|
||||||
subsequent refresh.
|
|
||||||
- Added onlyOnScroll, an option for individual waypoints that disables
|
|
||||||
triggers due to an offset refresh that crosses the current scroll
|
|
||||||
point. (All credit to @knuton on this one.)
|
|
||||||
v1.1
|
|
||||||
- Moved the continuous option out of global settings and into the options
|
|
||||||
object for individual waypoints.
|
|
||||||
- Added the context option, which allows for using waypoints within any
|
|
||||||
scrollable element, not just the window.
|
|
||||||
v1.0.2
|
|
||||||
- Moved scroll and resize handler bindings out of load. Should play nicer
|
|
||||||
with async loaders like Head JS and LABjs.
|
|
||||||
- Fixed a 1px off error when using certain % offsets.
|
|
||||||
- Added unit tests.
|
|
||||||
v1.0.1
|
|
||||||
- Added $.waypoints('viewportHeight').
|
|
||||||
- Fixed iOS bug (using the new viewportHeight method).
|
|
||||||
- Added offset function alias: 'bottom-in-view'.
|
|
||||||
v1.0
|
|
||||||
- Initial release.
|
|
||||||
|
|
||||||
Support:
|
|
||||||
- jQuery versions 1.4.3+
|
|
||||||
- IE6+, FF3+, Chrome 6+, Safari 4+, Opera 11
|
|
||||||
- Other versions and browsers may work, these are just the ones I've looked at.
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function($, wp, wps, window, undefined){
|
|
||||||
'$:nomunge';
|
|
||||||
|
|
||||||
var $w = $(window),
|
|
||||||
|
|
||||||
// Keeping common strings as variables = better minification
|
|
||||||
eventName = 'waypoint.reached',
|
|
||||||
|
|
||||||
/*
|
|
||||||
For the waypoint and direction passed in, trigger the waypoint.reached
|
|
||||||
event and deal with the triggerOnce option.
|
|
||||||
*/
|
|
||||||
triggerWaypoint = function(way, dir) {
|
|
||||||
way.element.trigger(eventName, dir);
|
|
||||||
if (way.options.triggerOnce) {
|
|
||||||
way.element[wp]('destroy');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/*
|
|
||||||
Given a jQuery element and Context, returns the index of that element in the waypoints
|
|
||||||
array. Returns the index, or -1 if the element is not a waypoint.
|
|
||||||
*/
|
|
||||||
waypointIndex = function(el, context) {
|
|
||||||
if (!context) return -1;
|
|
||||||
var i = context.waypoints.length - 1;
|
|
||||||
while (i >= 0 && context.waypoints[i].element[0] !== el[0]) {
|
|
||||||
i -= 1;
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Private list of all elements used as scrolling contexts for waypoints.
|
|
||||||
contexts = [],
|
|
||||||
|
|
||||||
/*
|
|
||||||
Context Class - represents a scrolling context. Properties include:
|
|
||||||
element: jQuery object containing a single HTML element.
|
|
||||||
waypoints: Array of waypoints operating under this scroll context.
|
|
||||||
oldScroll: Keeps the previous scroll position to determine scroll direction.
|
|
||||||
didScroll: Flag used in scrolling the context's scroll event.
|
|
||||||
didResize: Flag used in scrolling the context's resize event.
|
|
||||||
doScroll: Function that checks for crossed waypoints. Called from throttler.
|
|
||||||
*/
|
|
||||||
Context = function(context) {
|
|
||||||
$.extend(this, {
|
|
||||||
element: $(context),
|
|
||||||
oldScroll: 0,
|
|
||||||
|
|
||||||
/*
|
|
||||||
List of all elements that have been registered as waypoints.
|
|
||||||
Each object in the array contains:
|
|
||||||
element: jQuery object containing a single HTML element.
|
|
||||||
offset: The window scroll offset, in px, that triggers the waypoint event.
|
|
||||||
options: Options object that was passed to the waypoint fn function.
|
|
||||||
*/
|
|
||||||
'waypoints': [],
|
|
||||||
|
|
||||||
didScroll: false,
|
|
||||||
didResize: false,
|
|
||||||
|
|
||||||
doScroll: $.proxy(function() {
|
|
||||||
var newScroll = this.element.scrollTop(),
|
|
||||||
|
|
||||||
// Are we scrolling up or down? Used for direction argument in callback.
|
|
||||||
isDown = newScroll > this.oldScroll,
|
|
||||||
that = this,
|
|
||||||
|
|
||||||
// Get a list of all waypoints that were crossed since last scroll move.
|
|
||||||
pointsHit = $.grep(this.waypoints, function(el, i) {
|
|
||||||
return isDown ?
|
|
||||||
(el.offset > that.oldScroll && el.offset <= newScroll) :
|
|
||||||
(el.offset <= that.oldScroll && el.offset > newScroll);
|
|
||||||
}),
|
|
||||||
len = pointsHit.length;
|
|
||||||
|
|
||||||
// iOS adjustment
|
|
||||||
if (!this.oldScroll || !newScroll) {
|
|
||||||
$[wps]('refresh');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Done with scroll comparisons, store new scroll before ejection
|
|
||||||
this.oldScroll = newScroll;
|
|
||||||
|
|
||||||
// No waypoints crossed? Eject.
|
|
||||||
if (!len) return;
|
|
||||||
|
|
||||||
// If several waypoints triggered, need to do so in reverse order going up
|
|
||||||
if (!isDown) pointsHit.reverse();
|
|
||||||
|
|
||||||
/*
|
|
||||||
One scroll move may cross several waypoints. If the waypoint's continuous
|
|
||||||
option is true it should fire even if it isn't the last waypoint. If false,
|
|
||||||
it will only fire if it's the last one.
|
|
||||||
*/
|
|
||||||
$.each(pointsHit, function(i, point) {
|
|
||||||
if (point.options.continuous || i === len - 1) {
|
|
||||||
triggerWaypoint(point, [isDown ? 'down' : 'up']);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, this)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Setup scroll and resize handlers. Throttled at the settings-defined rate limits.
|
|
||||||
$(context).bind('scroll.waypoints', $.proxy(function() {
|
|
||||||
if (!this.didScroll) {
|
|
||||||
this.didScroll = true;
|
|
||||||
window.setTimeout($.proxy(function() {
|
|
||||||
this.doScroll();
|
|
||||||
this.didScroll = false;
|
|
||||||
}, this), $[wps].settings.scrollThrottle);
|
|
||||||
}
|
|
||||||
}, this)).bind('resize.waypoints', $.proxy(function() {
|
|
||||||
if (!this.didResize) {
|
|
||||||
this.didResize = true;
|
|
||||||
window.setTimeout($.proxy(function() {
|
|
||||||
$[wps]('refresh');
|
|
||||||
this.didResize = false;
|
|
||||||
}, this), $[wps].settings.resizeThrottle);
|
|
||||||
}
|
|
||||||
}, this));
|
|
||||||
|
|
||||||
$w.load($.proxy(function() {
|
|
||||||
/*
|
|
||||||
Fire a scroll check, should the page be loaded at a non-zero scroll value,
|
|
||||||
as with a fragment id link or a page refresh.
|
|
||||||
*/
|
|
||||||
this.doScroll();
|
|
||||||
}, this));
|
|
||||||
},
|
|
||||||
|
|
||||||
/* Returns a Context object from the contexts array, given the raw HTML element
|
|
||||||
for that context. */
|
|
||||||
getContextByElement = function(element) {
|
|
||||||
var found = null;
|
|
||||||
|
|
||||||
$.each(contexts, function(i, c) {
|
|
||||||
if (c.element[0] === element) {
|
|
||||||
found = c;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return found;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Methods exposed to the effin' object
|
|
||||||
methods = {
|
|
||||||
/*
|
|
||||||
jQuery.fn.waypoint([handler], [options])
|
|
||||||
|
|
||||||
handler
|
|
||||||
function, optional
|
|
||||||
A callback function called when the user scrolls past the element.
|
|
||||||
The function signature is function(event, direction) where event is
|
|
||||||
a standard jQuery Event Object and direction is a string, either 'down'
|
|
||||||
or 'up' indicating which direction the user is scrolling.
|
|
||||||
|
|
||||||
options
|
|
||||||
object, optional
|
|
||||||
A map of options to apply to this set of waypoints, including where on
|
|
||||||
the browser window the waypoint is triggered. For a full list of
|
|
||||||
options and their defaults, see $.fn.waypoint.defaults.
|
|
||||||
|
|
||||||
This is how you register an element as a waypoint. When the user scrolls past
|
|
||||||
that element it triggers waypoint.reached, a custom event. Since the
|
|
||||||
parameters for creating a waypoint are optional, we have a few different
|
|
||||||
possible signatures. Let’s look at each of them.
|
|
||||||
|
|
||||||
someElements.waypoint();
|
|
||||||
|
|
||||||
Calling .waypoint with no parameters will register the elements as waypoints
|
|
||||||
using the default options. The elements will fire the waypoint.reached event,
|
|
||||||
but calling it in this way does not bind any handler to the event. You can
|
|
||||||
bind to the event yourself, as with any other event, like so:
|
|
||||||
|
|
||||||
someElements.bind('waypoint.reached', function(event, direction) {
|
|
||||||
// make it rain
|
|
||||||
});
|
|
||||||
|
|
||||||
You will usually want to create a waypoint and immediately bind a function to
|
|
||||||
waypoint.reached, and can do so by passing a handler as the first argument to
|
|
||||||
.waypoint:
|
|
||||||
|
|
||||||
someElements.waypoint(function(event, direction) {
|
|
||||||
if (direction === 'down') {
|
|
||||||
// do this on the way down
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// do this on the way back up through the waypoint
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
This will still use the default options, which will trigger the waypoint when
|
|
||||||
the top of the element hits the top of the window. We can pass .waypoint an
|
|
||||||
options object to customize things:
|
|
||||||
|
|
||||||
someElements.waypoint(function(event, direction) {
|
|
||||||
// do something amazing
|
|
||||||
}, {
|
|
||||||
offset: '50%' // middle of the page
|
|
||||||
});
|
|
||||||
|
|
||||||
You can also pass just an options object.
|
|
||||||
|
|
||||||
someElements.waypoint({
|
|
||||||
offset: 100 // 100px from the top
|
|
||||||
});
|
|
||||||
|
|
||||||
This behaves like .waypoint(), in that it registers the elements as waypoints
|
|
||||||
but binds no event handlers.
|
|
||||||
|
|
||||||
Calling .waypoint on an existing waypoint will extend the previous options.
|
|
||||||
If the call includes a handler, it will be bound to waypoint.reached without
|
|
||||||
unbinding any other handlers.
|
|
||||||
*/
|
|
||||||
init: function(f, options) {
|
|
||||||
// Register each element as a waypoint, add to array.
|
|
||||||
this.each(function() {
|
|
||||||
var cElement = $.fn[wp].defaults.context,
|
|
||||||
context,
|
|
||||||
$this = $(this);
|
|
||||||
|
|
||||||
// Default window context or a specific element?
|
|
||||||
if (options && options.context) {
|
|
||||||
cElement = options.context;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the closest element that matches the context
|
|
||||||
if (!$.isWindow(cElement)) {
|
|
||||||
cElement = $this.closest(cElement)[0];
|
|
||||||
}
|
|
||||||
context = getContextByElement(cElement);
|
|
||||||
|
|
||||||
// Not a context yet? Create and push.
|
|
||||||
if (!context) {
|
|
||||||
context = new Context(cElement);
|
|
||||||
contexts.push(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extend default and preexisting options
|
|
||||||
var ndx = waypointIndex($this, context),
|
|
||||||
base = ndx < 0 ? $.fn[wp].defaults : context.waypoints[ndx].options,
|
|
||||||
opts = $.extend({}, base, options);
|
|
||||||
|
|
||||||
// Offset aliases
|
|
||||||
opts.offset = opts.offset === "bottom-in-view" ?
|
|
||||||
function() {
|
|
||||||
var cHeight = $.isWindow(cElement) ? $[wps]('viewportHeight')
|
|
||||||
: $(cElement).height();
|
|
||||||
return cHeight - $(this).outerHeight();
|
|
||||||
} : opts.offset;
|
|
||||||
|
|
||||||
// Update, or create new waypoint
|
|
||||||
if (ndx < 0) {
|
|
||||||
context.waypoints.push({
|
|
||||||
'element': $this,
|
|
||||||
'offset': null,
|
|
||||||
'options': opts
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
context.waypoints[ndx].options = opts;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind the function if it was passed in.
|
|
||||||
if (f) {
|
|
||||||
$this.bind(eventName, f);
|
|
||||||
}
|
|
||||||
// Bind the function in the handler option if it exists.
|
|
||||||
if (options && options.handler) {
|
|
||||||
$this.bind(eventName, options.handler);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Need to re-sort+refresh the waypoints array after new elements are added.
|
|
||||||
$[wps]('refresh');
|
|
||||||
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
jQuery.fn.waypoint('remove')
|
|
||||||
|
|
||||||
Passing the string 'remove' to .waypoint unregisters the elements as waypoints
|
|
||||||
and wipes any custom options, but leaves the waypoint.reached events bound.
|
|
||||||
Calling .waypoint again in the future would reregister the waypoint and the old
|
|
||||||
handlers would continue to work.
|
|
||||||
*/
|
|
||||||
remove: function() {
|
|
||||||
return this.each(function(i, el) {
|
|
||||||
var $el = $(el);
|
|
||||||
|
|
||||||
$.each(contexts, function(i, c) {
|
|
||||||
var ndx = waypointIndex($el, c);
|
|
||||||
|
|
||||||
if (ndx >= 0) {
|
|
||||||
c.waypoints.splice(ndx, 1);
|
|
||||||
|
|
||||||
if (!c.waypoints.length) {
|
|
||||||
c.element.unbind('scroll.waypoints resize.waypoints');
|
|
||||||
contexts.splice(i, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/*
|
|
||||||
jQuery.fn.waypoint('destroy')
|
|
||||||
|
|
||||||
Passing the string 'destroy' to .waypoint will unbind all waypoint.reached
|
|
||||||
event handlers on those elements and unregisters them as waypoints.
|
|
||||||
*/
|
|
||||||
destroy: function() {
|
|
||||||
return this.unbind(eventName)[wp]('remove');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/*
|
|
||||||
Methods used by the jQuery object extension.
|
|
||||||
*/
|
|
||||||
jQMethods = {
|
|
||||||
|
|
||||||
/*
|
|
||||||
jQuery.waypoints('refresh')
|
|
||||||
|
|
||||||
This will force a recalculation of each waypoint’s trigger point based on
|
|
||||||
its offset option and context. This is called automatically whenever the window
|
|
||||||
(or other defined context) is resized, new waypoints are added, or a waypoint’s
|
|
||||||
options are modified. If your project is changing the DOM or page layout without
|
|
||||||
doing one of these things, you may want to manually call this refresh.
|
|
||||||
*/
|
|
||||||
refresh: function() {
|
|
||||||
$.each(contexts, function(i, c) {
|
|
||||||
var isWin = $.isWindow(c.element[0]),
|
|
||||||
contextOffset = isWin ? 0 : c.element.offset().top,
|
|
||||||
contextHeight = isWin ? $[wps]('viewportHeight') : c.element.height(),
|
|
||||||
contextScroll = isWin ? 0 : c.element.scrollTop();
|
|
||||||
|
|
||||||
$.each(c.waypoints, function(j, o) {
|
|
||||||
/* $.each isn't safe from element removal due to triggerOnce.
|
|
||||||
Should rewrite the loop but this is way easier. */
|
|
||||||
if (!o) return;
|
|
||||||
|
|
||||||
// Adjustment is just the offset if it's a px value
|
|
||||||
var adjustment = o.options.offset,
|
|
||||||
oldOffset = o.offset;
|
|
||||||
|
|
||||||
// Set adjustment to the return value if offset is a function.
|
|
||||||
if (typeof o.options.offset === "function") {
|
|
||||||
adjustment = o.options.offset.apply(o.element);
|
|
||||||
}
|
|
||||||
// Calculate the adjustment if offset is a percentage.
|
|
||||||
else if (typeof o.options.offset === "string") {
|
|
||||||
var amount = parseFloat(o.options.offset);
|
|
||||||
adjustment = o.options.offset.indexOf("%") ?
|
|
||||||
Math.ceil(contextHeight * (amount / 100)) : amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Set the element offset to the window scroll offset, less
|
|
||||||
all our adjustments.
|
|
||||||
*/
|
|
||||||
o.offset = o.element.offset().top - contextOffset
|
|
||||||
+ contextScroll - adjustment;
|
|
||||||
|
|
||||||
/*
|
|
||||||
An element offset change across the current scroll point triggers
|
|
||||||
the event, just as if we scrolled past it unless prevented by an
|
|
||||||
optional flag.
|
|
||||||
*/
|
|
||||||
if (o.options.onlyOnScroll) return;
|
|
||||||
|
|
||||||
if (oldOffset !== null && c.oldScroll > oldOffset && c.oldScroll <= o.offset) {
|
|
||||||
triggerWaypoint(o, ['up']);
|
|
||||||
}
|
|
||||||
else if (oldOffset !== null && c.oldScroll < oldOffset && c.oldScroll >= o.offset) {
|
|
||||||
triggerWaypoint(o, ['down']);
|
|
||||||
}
|
|
||||||
/* For new waypoints added after load, check that down should have
|
|
||||||
already been triggered */
|
|
||||||
else if (!oldOffset && c.element.scrollTop() > o.offset) {
|
|
||||||
triggerWaypoint(o, ['down']);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Keep waypoints sorted by offset value.
|
|
||||||
c.waypoints.sort(function(a, b) {
|
|
||||||
return a.offset - b.offset;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
jQuery.waypoints('viewportHeight')
|
|
||||||
|
|
||||||
This will return the height of the viewport, adjusting for inconsistencies
|
|
||||||
that come with calling $(window).height() in iOS. Recommended for use
|
|
||||||
within any offset functions.
|
|
||||||
*/
|
|
||||||
viewportHeight: function() {
|
|
||||||
return (window.innerHeight ? window.innerHeight : $w.height());
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
jQuery.waypoints()
|
|
||||||
|
|
||||||
This will return a jQuery object with a collection of all registered waypoint
|
|
||||||
elements.
|
|
||||||
|
|
||||||
$('.post').waypoint();
|
|
||||||
$('.ad-unit').waypoint(function(event, direction) {
|
|
||||||
// Passed an ad unit
|
|
||||||
});
|
|
||||||
console.log($.waypoints());
|
|
||||||
|
|
||||||
The example above would log a jQuery object containing all .post and .ad-unit
|
|
||||||
elements.
|
|
||||||
*/
|
|
||||||
aggregate: function() {
|
|
||||||
var points = $();
|
|
||||||
$.each(contexts, function(i, c) {
|
|
||||||
$.each(c.waypoints, function(i, e) {
|
|
||||||
points = points.add(e.element);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return points;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
fn extension. Delegates to appropriate method.
|
|
||||||
*/
|
|
||||||
$.fn[wp] = function(method) {
|
|
||||||
|
|
||||||
if (methods[method]) {
|
|
||||||
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
|
|
||||||
}
|
|
||||||
else if (typeof method === "function" || !method) {
|
|
||||||
return methods.init.apply(this, arguments);
|
|
||||||
}
|
|
||||||
else if (typeof method === "object") {
|
|
||||||
return methods.init.apply(this, [null, method]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$.error( 'Method ' + method + ' does not exist on jQuery ' + wp );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
The default options object that is extended when calling .waypoint. It has the
|
|
||||||
following properties:
|
|
||||||
|
|
||||||
context
|
|
||||||
string | element | jQuery*
|
|
||||||
default: window
|
|
||||||
The context defines which scrollable element the waypoint belongs to and acts
|
|
||||||
within. The default, window, means the waypoint offset is calculated with relation
|
|
||||||
to the whole viewport. You can set this to another element to use the waypoints
|
|
||||||
within that element. Accepts a selector string, *but if you use jQuery 1.6+ it
|
|
||||||
also accepts a raw HTML element or jQuery object.
|
|
||||||
|
|
||||||
continuous
|
|
||||||
boolean
|
|
||||||
default: true
|
|
||||||
If true, and multiple waypoints are triggered in one scroll, this waypoint will
|
|
||||||
trigger even if it is not the last waypoint reached. If false, it will only
|
|
||||||
trigger if it is the last waypoint.
|
|
||||||
|
|
||||||
handler
|
|
||||||
function
|
|
||||||
default: undefined
|
|
||||||
An alternative way to bind functions to the waypoint, without using the function
|
|
||||||
as the first argument to the waypoint function.
|
|
||||||
|
|
||||||
offset
|
|
||||||
number | string | function
|
|
||||||
default: 0
|
|
||||||
Determines how far the top of the element must be from the top of the browser
|
|
||||||
window to trigger a waypoint. It can be a number, which is taken as a number
|
|
||||||
of pixels, a string representing a percentage of the viewport height, or a
|
|
||||||
function that will return a number of pixels.
|
|
||||||
|
|
||||||
onlyOnScroll
|
|
||||||
boolean
|
|
||||||
default: false
|
|
||||||
If true, this waypoint will not trigger if an offset change during a refresh
|
|
||||||
causes it to pass the current scroll point.
|
|
||||||
|
|
||||||
triggerOnce
|
|
||||||
boolean
|
|
||||||
default: false
|
|
||||||
If true, the waypoint will be destroyed when triggered.
|
|
||||||
|
|
||||||
An offset of 250 would trigger the waypoint when the top of the element is 250px
|
|
||||||
from the top of the viewport. Negative values for any offset work as you might
|
|
||||||
expect. A value of -100 would trigger the waypoint when the element is 100px above
|
|
||||||
the top of the window.
|
|
||||||
|
|
||||||
offset: '100%'
|
|
||||||
|
|
||||||
A string percentage will determine the pixel offset based on the height of the
|
|
||||||
window. When resizing the window, this offset will automatically be recalculated
|
|
||||||
without needing to call $.waypoints('refresh').
|
|
||||||
|
|
||||||
// The bottom of the element is in view
|
|
||||||
offset: function() {
|
|
||||||
return $.waypoints('viewportHeight') - $(this).outerHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
Offset can take a function, which must return a number of pixels from the top of
|
|
||||||
the window. The this value will always refer to the raw HTML element of the
|
|
||||||
waypoint. As with % values, functions are recalculated automatically when the
|
|
||||||
window resizes. For more on recalculating offsets, see $.waypoints('refresh').
|
|
||||||
|
|
||||||
An offset value of 'bottom-in-view' will act as an alias for the function in the
|
|
||||||
example above, as this is a common usage.
|
|
||||||
|
|
||||||
offset: 'bottom-in-view'
|
|
||||||
|
|
||||||
You can see this alias in use on the Scroll Analytics example page.
|
|
||||||
|
|
||||||
The triggerOnce flag, if true, will destroy the waypoint after the first trigger.
|
|
||||||
This is just a shortcut for calling .waypoint('destroy') within the waypoint
|
|
||||||
handler. This is useful in situations such as scroll analytics, where you only
|
|
||||||
want to record an event once for each page visit.
|
|
||||||
|
|
||||||
The context option lets you use Waypoints within an element other than the window.
|
|
||||||
You can define the context with a selector string and the waypoint will act within
|
|
||||||
the nearest ancestor that matches this selector.
|
|
||||||
|
|
||||||
$('.something-scrollable .waypoint').waypoint({
|
|
||||||
context: '.something-scrollable'
|
|
||||||
});
|
|
||||||
|
|
||||||
You can see this in action on the Dial Controls example.
|
|
||||||
|
|
||||||
The handler option gives authors an alternative way to bind functions when
|
|
||||||
creating a waypoint. In place of:
|
|
||||||
|
|
||||||
$('.item').waypoint(function(event, direction) {
|
|
||||||
// make things happen
|
|
||||||
});
|
|
||||||
|
|
||||||
You may instead write:
|
|
||||||
|
|
||||||
$('.item').waypoint({
|
|
||||||
handler: function(event, direction) {
|
|
||||||
// make things happen
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
*/
|
|
||||||
$.fn[wp].defaults = {
|
|
||||||
continuous: true,
|
|
||||||
offset: 0,
|
|
||||||
triggerOnce: false,
|
|
||||||
context: window
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
jQuery object extension. Delegates to appropriate methods above.
|
|
||||||
*/
|
|
||||||
$[wps] = function(method) {
|
|
||||||
if (jQMethods[method]) {
|
|
||||||
return jQMethods[method].apply(this);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return jQMethods['aggregate']();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
$.waypoints.settings
|
|
||||||
|
|
||||||
Settings object that determines some of the plugin’s behavior.
|
|
||||||
|
|
||||||
resizeThrottle
|
|
||||||
number
|
|
||||||
default: 200
|
|
||||||
For performance reasons, the refresh performed during resizes is
|
|
||||||
throttled. This value is the rate-limit in milliseconds between resize
|
|
||||||
refreshes. For more information on throttling, check out Ben Alman’s
|
|
||||||
throttle / debounce plugin.
|
|
||||||
http://benalman.com/projects/jquery-throttle-debounce-plugin/
|
|
||||||
|
|
||||||
scrollThrottle
|
|
||||||
number
|
|
||||||
default: 100
|
|
||||||
For performance reasons, checking for any crossed waypoints during a
|
|
||||||
scroll event is throttled. This value is the rate-limit in milliseconds
|
|
||||||
between scroll checks. For more information on throttling, check out Ben
|
|
||||||
Alman’s throttle / debounce plugin.
|
|
||||||
http://benalman.com/projects/jquery-throttle-debounce-plugin/
|
|
||||||
*/
|
|
||||||
$[wps].settings = {
|
|
||||||
resizeThrottle: 200,
|
|
||||||
scrollThrottle: 100
|
|
||||||
};
|
|
||||||
|
|
||||||
$w.load(function() {
|
|
||||||
// Calculate everything once on load.
|
|
||||||
$[wps]('refresh');
|
|
||||||
});
|
|
||||||
})(jQuery, 'waypoint', 'waypoints', window);
|
|
|
@ -1,163 +0,0 @@
|
||||||
$ = jQuery.sub()
|
|
||||||
|
|
||||||
class App.WebSocket
|
|
||||||
_instance = undefined # Must be declared here to force the closure on the class
|
|
||||||
@connect: (args) -> # Must be a static method
|
|
||||||
if _instance == undefined
|
|
||||||
_instance ?= new _Singleton
|
|
||||||
_instance
|
|
||||||
|
|
||||||
@close: (args) -> # Must be a static method
|
|
||||||
if _instance isnt undefined
|
|
||||||
_instance.close()
|
|
||||||
|
|
||||||
@send: (args) -> # Must be a static method
|
|
||||||
@connect()
|
|
||||||
_instance.send(args)
|
|
||||||
|
|
||||||
@auth: (args) -> # Must be a static method
|
|
||||||
@connect()
|
|
||||||
_instance.auth(args)
|
|
||||||
|
|
||||||
# The actual Singleton class
|
|
||||||
class _Singleton extends App.Controller
|
|
||||||
queue: []
|
|
||||||
supported: true
|
|
||||||
|
|
||||||
constructor: (@args) ->
|
|
||||||
@connect()
|
|
||||||
|
|
||||||
send: (data) =>
|
|
||||||
return if !@supported
|
|
||||||
# console.log 'ws:send trying', data, @ws, @ws.readyState
|
|
||||||
|
|
||||||
# A value of 0 indicates that the connection has not yet been established.
|
|
||||||
# A value of 1 indicates that the connection is established and communication is possible.
|
|
||||||
# A value of 2 indicates that the connection is going through the closing handshake.
|
|
||||||
# A value of 3 indicates that the connection has been closed or could not be opened.
|
|
||||||
if @ws.readyState is 0
|
|
||||||
@queue.push data
|
|
||||||
else
|
|
||||||
# console.log( 'ws:send', data )
|
|
||||||
string = JSON.stringify( data )
|
|
||||||
@ws.send(string)
|
|
||||||
|
|
||||||
auth: (data) =>
|
|
||||||
return if !@supported
|
|
||||||
|
|
||||||
# logon websocket
|
|
||||||
data = {
|
|
||||||
action: 'login',
|
|
||||||
session: window.Session
|
|
||||||
}
|
|
||||||
@send(data)
|
|
||||||
|
|
||||||
close: =>
|
|
||||||
return if !@supported
|
|
||||||
|
|
||||||
@ws.close()
|
|
||||||
|
|
||||||
ping: =>
|
|
||||||
return if !@supported
|
|
||||||
|
|
||||||
# console.log 'send websockend ping'
|
|
||||||
@send( { action: 'ping' } )
|
|
||||||
|
|
||||||
# check if ping is back within 2 min
|
|
||||||
@clearDelay('websocket-ping-check')
|
|
||||||
check = =>
|
|
||||||
console.log 'no websockend ping response, reconnect...'
|
|
||||||
@close()
|
|
||||||
@delay check, 120000, 'websocket-ping-check'
|
|
||||||
|
|
||||||
pong: ->
|
|
||||||
return if !@supported
|
|
||||||
# console.log 'received websockend ping'
|
|
||||||
|
|
||||||
# test again after 1 min
|
|
||||||
@delay @ping, 60000
|
|
||||||
|
|
||||||
connect: =>
|
|
||||||
# console.log '------------ws connect....--------------'
|
|
||||||
|
|
||||||
if !window.WebSocket
|
|
||||||
@error = new App.ErrorModal(
|
|
||||||
message: 'Sorry, no websocket support!'
|
|
||||||
)
|
|
||||||
@supported = false
|
|
||||||
return
|
|
||||||
|
|
||||||
protocol = 'ws://'
|
|
||||||
if window.location.protocol is 'https:'
|
|
||||||
protocol = 'wss://'
|
|
||||||
|
|
||||||
@ws = new window.WebSocket( protocol + window.location.hostname + ":6042/" )
|
|
||||||
|
|
||||||
# Set event handlers.
|
|
||||||
@ws.onopen = =>
|
|
||||||
console.log( 'onopen' )
|
|
||||||
|
|
||||||
# close error message show up (because try so connect again) if exists
|
|
||||||
@clearDelay('websocket-no-connection-try-reconnect')
|
|
||||||
if @error
|
|
||||||
@error.modalHide()
|
|
||||||
@error = undefined
|
|
||||||
|
|
||||||
@auth()
|
|
||||||
|
|
||||||
# empty queue
|
|
||||||
for item in @queue
|
|
||||||
# console.log( 'ws:send queue', item )
|
|
||||||
@send(item)
|
|
||||||
@queue = []
|
|
||||||
|
|
||||||
# send ping to check connection
|
|
||||||
@delay @ping, 60000
|
|
||||||
|
|
||||||
@ws.onmessage = (e) =>
|
|
||||||
pipe = JSON.parse( e.data )
|
|
||||||
console.log( 'ws:onmessage', pipe )
|
|
||||||
|
|
||||||
# go through all blocks
|
|
||||||
for item in pipe
|
|
||||||
|
|
||||||
# reset reconnect loop
|
|
||||||
if item['action'] is 'pong'
|
|
||||||
@pong()
|
|
||||||
|
|
||||||
# fill collection
|
|
||||||
if item['collection']
|
|
||||||
console.log( "ws:onmessage collection:" + item['collection'] )
|
|
||||||
App.Store.write( item['collection'], item['data'] )
|
|
||||||
|
|
||||||
# fire event
|
|
||||||
if item['event']
|
|
||||||
if typeof item['event'] is 'object'
|
|
||||||
for event in item['event']
|
|
||||||
console.log( "ws:onmessage event:" + event )
|
|
||||||
App.Event.trigger( event, item['data'] )
|
|
||||||
else
|
|
||||||
console.log( "ws:onmessage event:" + item['event'] )
|
|
||||||
App.Event.trigger( item['event'], item['data'] )
|
|
||||||
|
|
||||||
# bind to send messages
|
|
||||||
App.Event.bind 'ws:send', (data) =>
|
|
||||||
@send(data)
|
|
||||||
|
|
||||||
@ws.onclose = (e) =>
|
|
||||||
console.log( 'onclose', e )
|
|
||||||
|
|
||||||
# show error message, first try to reconnect
|
|
||||||
if !@error
|
|
||||||
message = =>
|
|
||||||
@error = new App.ErrorModal(
|
|
||||||
message: 'No connection to websocket, trying to reconnect...'
|
|
||||||
)
|
|
||||||
@delay message, 7000, 'websocket-no-connection-try-reconnect'
|
|
||||||
|
|
||||||
# try reconnect after 4.5 sec.
|
|
||||||
@delay @connect, 4500
|
|
||||||
|
|
||||||
@ws.onerror = ->
|
|
||||||
console.log( 'onerror' )
|
|
||||||
|
|
Loading…
Reference in a new issue