Mostly working ;)

This commit is contained in:
Fergal Moran
2014-05-25 15:47:50 +01:00
parent 1d21509cd8
commit ca0f683980
61 changed files with 61107 additions and 0 deletions

139
static/js/app/appv2.js Normal file
View File

@@ -0,0 +1,139 @@
// Generated by CoffeeScript 1.4.0
(function() {
this.DssApplication = (function(Backbone, Marionette) {
var App, sidebarView;
App = new Marionette.Application();
App.vent.on("routing:started", function() {
var enablePushState, pushState;
console.log("App(vent): routing:started");
enablePushState = true;
pushState = !!(enablePushState && window.history && window.history.pushState);
Backbone.history.start({
pushState: pushState,
hashChange: true
});
return true;
});
App.addRegions({
headerRegion: "#header",
fullContentRegion: "#full-content",
contentRegion: {
selector: "#content"
},
footerRegion: "#footer",
sidebarRegion: "#sidebar"
});
App.addInitializer(function() {
console.log("App: routing starting");
App.Router = new DssRouter();
return App.vent.trigger("routing:started");
});
App.addInitializer(function() {
$(document).on("click", "a[href]:not([data-bypass])", function(evt) {
var href, root;
href = {
prop: $(this).prop("href"),
attr: $(this).attr("href")
};
root = location.protocol + "//" + location.host + (App.root || '/');
if (href.prop.slice(0, root.length) === root) {
evt.preventDefault();
App.Router.navigate(href.attr, true);
return true;
}
});
return true;
});
App.addInitializer(function() {
this.listenTo(vent, "app:login", function() {
console.log("App(vent): app:login");
utils.modal("/dlg/LoginView");
return true;
});
this.listenTo(vent, "app:donate", function() {
console.log("App: donate");
utils.modal("/dlg/Donate");
return true;
});
this.listenTo(vent, "mix:favourite", function(model) {
console.log("App(vent): mix:favourite");
model.save('favourited', !model.get('favourited'), {
patch: true
});
return true;
});
this.listenTo(vent, "mix:like", function(model, id, success, favourite) {
console.log("App(vent): mix:like");
model.save('liked', !model.get('liked'), {
patch: true
});
return true;
});
this.listenTo(vent, "mix:delete", function(model) {
console.log("App(vent): mix:like");
return utils.messageBox("/dlg/DeleteMixConfirm", {
yes: function() {
console.log("Controller: mixDeleteYES!!");
mix.destroy();
return Backbone.history.navigate("/", {
trigger: true
});
},
no: function() {
return console.log("Controller: mixDeleteNO!!");
}
});
});
this.listenTo(vent, "user:follow", function(model) {
var target, user,
_this = this;
console.log("App(vent): user:follow");
user = new UserItem({
id: com.podnoms.settings.currentUser
});
target = com.podnoms.settings.urlRoot + "user/" + model.get("id") + "/";
user.fetch({
success: function() {
var f, newFollowers;
if (!model.get("is_following")) {
newFollowers = user.get("following").concat([target]);
user.save({
"following": newFollowers,
"is_following": true,
patch: true
});
model.set("is_following", true);
} else {
f = user.get("following");
f.splice(f.indexOf(target), 1);
user.save({
"following": f,
"is_following": false,
patch: true
});
model.set("is_following", false);
}
}
});
return true;
});
return this.listenTo(vent, "mix:share", function(mode, model) {
console.log("App(vent): mix:share (" + mode + ")");
if (mode === "facebook") {
social.sharePageToFacebook(model);
} else if (mode === "twitter") {
social.sharePageToTwitter(model);
} else if (mode === "embed") {
social.generateEmbedCode(model);
}
return true;
});
});
App.headerRegion.show(new HeaderView());
sidebarView = new SidebarView();
App.sidebarRegion.show(sidebarView);
return App;
})(Backbone, Marionette);
}).call(this);

View File

@@ -0,0 +1,17 @@
/**
<b>Auto Container</b> Adds .container when window size is above 1140px.
In Bootstrap you should stick with fixed width breakpoints.
You can use this feature to enable fixed container only when window size is above 1140px
*/
ace.auto_container = function($) {
$(window).on('resize.auto_container', function() {
var enable = ace.vars.window['width'] > 1140 ? true : false;
try {
ace.settings.main_container_fixed(enable, false, false);
} catch(e) {
if(enable) $('.main-container,.navbar-container').addClass('container');
else $('.main-container,.navbar-container').removeClass('container');
$(document).trigger('settings.ace', ['main_container_fixed' , enable]);
}
}).triggerHandler('resize.auto_container');
}

View File

@@ -0,0 +1,80 @@
/**
<b>Auto content padding on fixed navbar &amp; breadcrumbs</b>.
Navbar's content and height is often predictable and when navbar is fixed we can add appropriate padding to content area using CSS.
But when navbar is fixed and its content size and height is not predictable we may need to add the necessary padding to content area dynamically using Javascript.
It's not often needed and you can have good results using CSS3 media queries to add necessary paddings based on window size.
*/
ace.auto_padding = function($) {
var navbar = $('.navbar').eq(0);
var navbar_container = $('.navbar-container').eq(0);
var sidebar = $('.sidebar').eq(0);
var main_container = $('.main-container').get(0);
var breadcrumbs = $('.breadcrumbs').eq(0);
var page_content = $('.page-content').get(0);
var default_padding = 8
if(navbar.length > 0) {
$(window).on('resize.padding', function() {
if( navbar.css('position') == 'fixed' ) {
var padding1 = !ace.vars['nav_collapse'] ? navbar.outerHeight() : navbar_container.outerHeight();
padding1 = parseInt(padding1);
main_container.style.paddingTop = padding1 + 'px';
if(ace.vars['non_auto_fixed'] && sidebar.length > 0) {
if(sidebar.css('position') == 'fixed') {
sidebar.get(0).style.top = padding1 + 'px';
}
else sidebar.get(0).style.top = '';
}
if( breadcrumbs.length > 0 ) {
if(breadcrumbs.css('position') == 'fixed') {
var padding2 = default_padding + breadcrumbs.outerHeight() + parseInt(breadcrumbs.css('margin-top'));
padding2 = parseInt(padding2);
page_content.style['paddingTop'] = padding2 + 'px';
if(ace.vars['non_auto_fixed']) breadcrumbs.get(0).style.top = padding1 + 'px';
} else {
page_content.style.paddingTop = '';
if(ace.vars['non_auto_fixed']) breadcrumbs.get(0).style.top = '';
}
}
}
else {
main_container.style.paddingTop = '';
page_content.style.paddingTop = '';
if(ace.vars['non_auto_fixed']) {
if(sidebar.length > 0) {
sidebar.get(0).style.top = '';
}
if(breadcrumbs.length > 0) {
breadcrumbs.get(0).style.top = '';
}
}
}
}).triggerHandler('resize.padding');
$(document).on('settings.ace', function(ev, event_name, event_val) {
if(event_name == 'navbar_fixed' || event_name == 'breadcrumbs_fixed') {
if(ace.vars['webkit']) {
//force new 'css position' values to kick in
navbar.get(0).offsetHeight;
if(breadcrumbs.length > 0) breadcrumbs.get(0).offsetHeight;
}
$(window).triggerHandler('resize.padding');
}
});
/**$('#skin-colorpicker').on('change', function() {
$(window).triggerHandler('resize.padding');
});*/
}
}

View File

@@ -0,0 +1,19 @@
/**
<b>Autohide mobile view menu</b>. Automatically hide the sidebar in mobile view (default style) when clicked/tapped outside of it.
*/
ace.auto_hide_sidebar = function($) {
$(document).on(ace.click_event+'.ace.hide', function(e) {
var toggler = $('#menu-toggler');
if( toggler.length == 0 || toggler[0].scrollHeight == 0 || !toggler.hasClass('display') ) return;
//toggle button is not visible, so we are not in mobile view, or the sidebar is not displayed, so return
var sidebar = $('#sidebar');
if( $.contains(sidebar[0], e.target) ) {
e.stopPropagation();
return;
}
sidebar.removeClass('display');
toggler.removeClass('display');
})
}

View File

@@ -0,0 +1,301 @@
/**
Required. Ace's Basic File to Initiliaze Different Parts & Some Variables.
*/
if( !('ace' in window) ) window['ace'] = {}
if( !('helper' in window['ace']) ) window['ace'].helper = {}
if( !('vars' in window['ace']) ) {
window['ace'].vars = {
'icon' : ' ace-icon ',
'.icon' : '.ace-icon'
}
}
ace.vars['touch'] = 'ontouchstart' in document.documentElement;
jQuery(function($) {
//sometimes we try to use 'tap' event instead of 'click' if jquery mobile plugin is available
ace.click_event = ace.vars['touch'] && $.fn.tap ? 'tap' : 'click';
//sometimes the only good way to work around browser's pecularities is to detect them using user-agents
//though it's not accurate
var agent = navigator.userAgent
ace.vars['webkit'] = !!agent.match(/AppleWebKit/i)
ace.vars['safari'] = !!agent.match(/Safari/i) && !agent.match(/Chrome/i);
ace.vars['android'] = ace.vars['safari'] && !!agent.match(/Android/i)
ace.vars['ios_safari'] = !!agent.match(/OS ([4-8])(_\d)+ like Mac OS X/i) && !agent.match(/CriOS/i)
ace.vars['non_auto_fixed'] = ace.vars['android'] || ace.vars['ios_safari'];
// for android and ios we don't use "top:auto" when breadcrumbs is fixed
if(ace.vars['non_auto_fixed']) {
$('body').addClass('mob-safari');
}
ace.vars['transition'] = 'transition' in document.body.style || 'WebkitTransition' in document.body.style || 'MozTransition' in document.body.style || 'OTransition' in document.body.style
/////////////////////////////
//a list of available functions with their arguments
// >>> null means enable
// >>> false means disable
// >>> array means function arguments
var available_functions = {
'general_vars' : null,//general_vars should come first
'handle_side_menu' : null,
'add_touch_drag' : null,
'sidebar_scrollable' : [
//true, //enable only if sidebar is fixed , for 2nd approach only
true //scroll to selected item? (one time only on page load)
,true //true = include shortcut buttons in the scrollbars
,false || ace.vars['safari'] || ace.vars['ios_safari'] //true = include toggle button in the scrollbars
,200 //> 0 means smooth_scroll, time in ms, used in first approach only, better to be almost the same amount as submenu transition time
,false//true && ace.vars['touch'] //used in first approach only, true means the scrollbars should be outside of the sidebar
],
'sidebar_hoverable' : null,//automatically move up a submenu, if some part of it goes out of window
'general_things' : null,
'widget_boxes' : null,
'widget_reload_handler' : null,
'settings_box' : null,//settings box
'settings_rtl' : null,
'settings_skin' : null,
'enable_searchbox_autocomplete' : null,
'auto_hide_sidebar' : null,//disable?
'auto_padding' : null,//disable
'auto_container' : null//disable
};
//enable these functions with related params
for(var func_name in available_functions) {
if(!(func_name in ace)) continue;
var args = available_functions[func_name];
if(args === false) continue;//don't run this function
else if(args == null) args = [jQuery];
else if(args instanceof String) args = [jQuery, args];
else if(args instanceof Array) args.unshift(jQuery);//prepend jQuery
ace[func_name].apply(null, args);
}
})
ace.general_vars = function($) {
var minimized_menu_class = 'menu-min';
var responsive_min_class = 'responsive-min';
var horizontal_menu_class = 'h-sidebar';
var sidebar = $('#sidebar').eq(0);
//differnet mobile menu styles
ace.vars['mobile_style'] = 1;//default responsive mode with toggle button inside navbar
if(sidebar.hasClass('responsive') && !$('#menu-toggler').hasClass('navbar-toggle')) ace.vars['mobile_style'] = 2;//toggle button behind sidebar
else if(sidebar.hasClass(responsive_min_class)) ace.vars['mobile_style'] = 3;//minimized menu
else if(sidebar.hasClass('navbar-collapse')) ace.vars['mobile_style'] = 4;//collapsible (bootstrap style)
//update some basic variables
$(window).on('resize.ace.vars' , function(){
ace.vars['window'] = {width: parseInt($(this).width()), height: parseInt($(this).height())}
ace.vars['mobile_view'] = ace.vars['mobile_style'] < 4 && ace.helper.mobile_view();
ace.vars['collapsible'] = !ace.vars['mobile_view'] && ace.helper.collapsible();
ace.vars['nav_collapse'] = (ace.vars['collapsible'] || ace.vars['mobile_view']) && $('#navbar').hasClass('navbar-collapse');
var sidebar = $(document.getElementById('sidebar'));
ace.vars['minimized'] =
(!ace.vars['collapsible'] && sidebar.hasClass(minimized_menu_class))
||
(ace.vars['mobile_style'] == 3 && ace.vars['mobile_view'] && sidebar.hasClass(responsive_min_class))
ace.vars['horizontal'] = !(ace.vars['mobile_view'] || ace.vars['collapsible']) && sidebar.hasClass(horizontal_menu_class)
}).triggerHandler('resize.ace.vars');
}
//
ace.general_things = function($) {
//add scrollbars for user dropdowns
var has_scroll = !!$.fn.ace_scroll;
if(has_scroll) $('.dropdown-content').ace_scroll({reset: false, mouseWheelLock: true})
/**
//add scrollbars to body
if(has_scroll) $('body').ace_scroll({size: ace.helper.winHeight()})
$('body').css('position', 'static')
*/
//reset scrolls bars on window resize
$(window).on('resize.reset_scroll', function() {
/**
//reset body scrollbars
if(has_scroll) $('body').ace_scroll('update', {size : ace.helper.winHeight()})
*/
if(has_scroll) $('.ace-scroll').ace_scroll('reset');
});
$(document).on('settings.ace.reset_scroll', function(e, name) {
if(name == 'sidebar_collapsed' && has_scroll) $('.ace-scroll').ace_scroll('reset');
});
//change a dropdown to "dropup" depending on its position
$(document).on('click.dropdown.pos', '.dropdown-toggle[data-position="auto"]', function() {
var offset = $(this).offset();
var parent = $(this.parentNode);
if ( parseInt(offset.top + $(this).height()) + 50
>
(ace.helper.scrollTop() + ace.helper.winHeight() - parent.find('.dropdown-menu').eq(0).height())
) parent.addClass('dropup');
else parent.removeClass('dropup');
});
//prevent dropdowns from hiding when a tab is selected
$(document).on('click', '.dropdown-navbar .nav-tabs', function(e){
e.stopPropagation();
var $this , href
var that = e.target
if( ($this = $(e.target).closest('[data-toggle=tab]')) && $this.length > 0) {
$this.tab('show');
e.preventDefault();
}
});
//prevent dropdowns from hiding when a from is clicked
/**$(document).on('click', '.dropdown-navbar form', function(e){
e.stopPropagation();
});*/
//disable navbar icon animation upon click
$('.ace-nav [class*="icon-animated-"]').closest('a').one('click', function(){
var icon = $(this).find('[class*="icon-animated-"]').eq(0);
var $match = icon.attr('class').match(/icon\-animated\-([\d\w]+)/);
icon.removeClass($match[0]);
});
//tooltip in sidebar items
$('.sidebar .nav-list .badge[title],.sidebar .nav-list .badge[title]').each(function() {
var tooltip_class = $(this).attr('class').match(/tooltip\-(?:\w+)/);
tooltip_class = tooltip_class ? tooltip_class[0] : 'tooltip-error';
$(this).tooltip({
'placement': function (context, source) {
var offset = $(source).offset();
if( parseInt(offset.left) < parseInt(document.body.scrollWidth / 2) ) return 'right';
return 'left';
},
container: 'body',
template: '<div class="tooltip '+tooltip_class+'"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
});
});
//or something like this if items are dynamically inserted
/**$('.sidebar').tooltip({
'placement': function (context, source) {
var offset = $(source).offset();
if( parseInt(offset.left) < parseInt(document.body.scrollWidth / 2) ) return 'right';
return 'left';
},
selector: '.nav-list .badge[title],.nav-list .label[title]',
container: 'body',
template: '<div class="tooltip tooltip-error"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
});*/
//the scroll to top button
var scroll_btn = $('.btn-scroll-up');
if(scroll_btn.length > 0) {
var is_visible = false;
$(window).on('scroll.scroll_btn', function() {
if(ace.helper.scrollTop() > parseInt(ace.helper.winHeight() / 4)) {
if(!is_visible) {
scroll_btn.addClass('display');
is_visible = true;
}
} else {
if(is_visible) {
scroll_btn.removeClass('display');
is_visible = false;
}
}
}).triggerHandler('scroll.scroll_btn');
scroll_btn.on(ace.click_event, function(){
var duration = Math.min(500, Math.max(100, parseInt(ace.helper.scrollTop() / 3)));
$('html,body').animate({scrollTop: 0}, duration);
return false;
});
}
//chrome and webkit have a problem here when resizing from 460px to more
//we should force them redraw the navbar!
if( ace.vars['webkit'] ) {
var ace_nav = $('.ace-nav').get(0);
if( ace_nav ) $(window).on('resize.webkit' , function(){
ace.helper.redraw(ace_nav);
});
}
}
//some functions
ace.helper.collapsible = function() {
var toggle
return (document.querySelector('#sidebar.navbar-collapse') != null)
&& ((toggle = document.querySelector('.navbar-toggle[data-target*=".sidebar"]')) != null)
&& toggle.scrollHeight > 0
//sidebar is collapsible and collapse button is visible?
}
ace.helper.mobile_view = function() {
var toggle
return ((toggle = document.getElementById('menu-toggler')) != null && toggle.scrollHeight > 0)
}
ace.helper.redraw = function(elem) {
var saved_val = elem.style['display'];
elem.style.display = 'none';
elem.offsetHeight;
elem.style.display = saved_val;
}
ace.helper.scrollTop = function() {
return document.scrollTop || document.documentElement.scrollTop || document.body.scrollTop
//return $(window).scrollTop();
}
ace.helper.winHeight = function() {
return window.innerHeight || document.documentElement.clientHeight;
//return $(window).innerHeight();
}
ace.helper.camelCase = function(str) {
return str.replace(/-([\da-z])/gi, function(match, chr) {
return chr ? chr.toUpperCase() : '';
});
}
ace.helper.removeStyle =
'removeProperty' in document.body.style
?
function(elem, prop) { elem.style.removeProperty(prop) }
:
function(elem, prop) { elem.style[ace.helper.camelCase(prop)] = '' }
ace.helper.hasClass =
'classList' in document.documentElement
?
function(elem, className) { return elem.classList.contains(className); }
:
function(elem, className) { return elem.className.indexOf(className) > -1; }

View File

@@ -0,0 +1,592 @@
jQuery(function($) {
var help = null;
$(window).on('hashchange.start_help', function(e) {
if(help == null && window.location.hash == '#help') {
help = new ace.Onpage_Help($)
help.init()
help.disable();
//add #help tag to links to enable help
$(document).on('click.start_help', '.sidebar .nav-list a', function() {
var href = $(this).attr('href');
if( !href.match(/\#help$/) ) $(this).attr('href', href+'#help');
});
}
}).triggerHandler('hashchange.start_help');
//some buttons inside demo pages to launch help
$(document).on(ace.click_event, '.btn-display-help', function(e) {
e.preventDefault();
if(help == null) {
help = new ace.Onpage_Help($)
help.init()
help.disable();
//
$('#ace-toggle-onpage-help').trigger('click');
}
var section = $(this).attr('href');
help.show_help(section);
});
});
ace.Onpage_Help = function($) {
if( !window.Node ) window.Node = {
ELEMENT_NODE: 1,
ATTRIBUTE_NODE: 2,
TEXT_NODE: 3,
COMMENT_NODE: 8
};
var $base = ace.vars['base'] || '../..';
var section_start = {};
var section_end = {};
var rects = {};
var created = false;
var active = false;
var self = this;
var settings = {}
var ovfx = '';
var container = null;
var body_h, body_w;
var captureFocus = function() {
if(!container) return;
var scroll = -1;
//like bootstrap modal
$(document)
.off('focusin.ace.help') //remove any previously attached handler
.on('focusin.ace.help', function (e) {
if (!( container[0] == e.target || $.contains(container[0], e.target) )) {
container.focus();
}
if(e.target == document && scroll > -1) {
//when window regains focus and container is focused, it scrolls to bottom
//so we put it back to its place
$('body,html').scrollTop(scroll);
scroll = -1;
}
})
$(window).on('blur.ace.help', function(){
scroll = $(window).scrollTop();
});
}
var releaseFocus = function() {
$(document).off('focusin.ace.help');
$(window).off('blur.ace.help');
}
this.enable = function() {
if(active) return;
active = true;
settings['navbar'] = ace.settings.is('navbar', 'fixed')
settings['sidebar'] = ace.settings.is('sidebar', 'fixed')
settings['breadcrumbs'] = ace.settings.is('breadcrumbs', 'fixed')
ace.settings.navbar_fixed(false , false);//disable fixed navbar, sidebar, etc
if( !created ) {
this.init();
created = true;
}
$('.ace-onpage-help-backdrop, .ace-onpage-help').removeClass('hidden');
ovfx = document.body.style.overflowX;
document.body.style.overflowX = 'hidden';//hide body:overflow-x
$('#btn-scroll-up').css('z-index', 1000000);
$(window).triggerHandler('resize.onpage_help');
captureFocus();
}
this.disable = function() {
active = false;
$('.ace-onpage-help-backdrop, .ace-onpage-help').addClass('hidden');
document.body.style.overflowX = ovfx;//restore body:overflow-x
$('#btn-scroll-up').css('z-index', '');
//restore fixed state of navbar, sidebar, etc
if( settings['breadcrumbs'] ) {
ace.settings.breadcrumbs_fixed(true, false, false);
}
if( settings['sidebar'] ) {
ace.settings.sidebar_fixed(true, false, false);
}
if( settings['navbar'] ) {
ace.settings.navbar_fixed(true, false, false);
}
releaseFocus();
}
this.is_active = function() {
return active;
}
this.show_help = function(section) {
launch_help_modal(section, true);
}
this.init = function() {
container = $('<div class="ace-onpage-help-container" tabindex="-1" />').appendTo('body');
container
.append('<div class="ace-onpage-help-backdrop" />')
.append('\<div class="ace-settings-container ace-help-container">\
<div id="ace-toggle-onpage-help" class="btn btn-app btn-xs btn-info ace-settings-btn ace-toggle-onpage-help">\
<i class="ace-toggle-help-text ace-icon fa fa-question bigger-150"></i>\
</div>\
</div>');
$(document).on('settings.ace.help', function(ev, event_name, event_val) {
if(event_name == 'main_container_fixed') {
if(event_val) container.addClass('container');
else container.removeClass('container');
}
}).triggerHandler('settings.ace.help', ['main_container_fixed', $('.main-container').hasClass('container')])
$('#ace-toggle-onpage-help').on('click', function(e) {
if(active) {
self.disable();
}
else {
self.enable();
}
$(this).find('.ace-toggle-help-text').removeClass('ace-toggle-help-text');
$(this).toggleClass('btn-grey btn-info').parent().toggleClass('active');
e.preventDefault();
})
//find all comments
var comments = $('*').contents().filter(function(){ return this.nodeType == Node.COMMENT_NODE; })
$(comments).each(function() {
var match
if( (match = $.trim(this.data).match(/#section\s*:\s*([\w\-\.\/]+)/i)) ) {
var section_name = match[1];
if( !(section_name in section_start) ) section_start[ section_name ] = this;
}
if( (match = $.trim(this.data).match(/\/section\s*:\s*([\w\-\.\/]+)/i)) ) {
var section_name = match[1];
if( !(section_name in section_end) ) section_end[ section_name ] = this;
}
})
//update to correct position and size
$(window).on('resize.onpage_help', function() {
if(!active) return;
body_h = document.body.scrollHeight - 2;
body_w = document.body.scrollWidth - 2;
//we first calculate all positions
//because if we calculate one position and then change DOM,
//next position calculation will become slow on Webkit, because it tries to re-calculate things
//i.e. batch call all and save offsets and scrollWidth, etc and then use them later in highlight_section
//Firefox doesn't have such issue
for(var name in section_start) {
if(section_start.hasOwnProperty(name)) {
save_section_position(name);
}
}
for(var name in section_start) {
if(section_start.hasOwnProperty(name)) {
highlight_section(name);
}
}
})
//$('.alert').on('closed.bs.alert', function() {
//$(window).triggerHandler('resize.onpage_help');
//});
created = true;
}
function save_section_position(name) {
if( !(name in section_start) || !(name in section_end) ) return;
var node = section_start[name];
var start = $(node).next().eq(0);
var end = $(section_end[name]).prev().eq(0);
var start_hidden = start.is(':hidden');
var end_hidden = end.is(':hidden');
if( start_hidden && end_hidden ) {
rects[name] = {is_hidden: true}
return;
}
if(start_hidden) start = end;
else if(end_hidden) end = start;
//get the start and end position of our rectangle to be drawn!
var off1 = start.offset();
var off2 = end.offset();
if( !off1 || !off2 ) {
rects[name] = {is_hidden: true}
return;
}
var x1, y1, x2, y2, w2, h2;
if(off1.left < off2.left) {
x1 = parseInt(off1.left);
x2 = parseInt(off2.left);
w2 = parseInt(end.outerWidth());
} else {
x1 = parseInt(off2.left);
x2 = parseInt(off1.left);
w2 = parseInt(start.outerWidth());
}
if(off1.top < off2.top) {
y1 = parseInt(off1.top);
y2 = parseInt(off2.top);
h2 = parseInt(end.outerHeight());
} else {
y1 = parseInt(off2.top);
y2 = parseInt(off1.top);
h2 = parseInt(start.outerHeight());
}
x1 -= 1;
y1 -= 1;
x2 += 1;
y2 += 1;
var width = x2 + w2 - x1, height = y2 + h2 - y1;
//if out of window rect
if(x1 + width < 2 || x1 > body_w || y1 + height < 2 || y1 > body_h ) {
rects[name] = {is_hidden: true}
return;
}
rects[name] = {
left: x1,
top: y1,
width: width,
height: height
}
}
function highlight_section(name) {
if( !(name in rects) || !container ) return;
var div = container.find('.ace-onpage-help[data-section="'+name+'"]').eq(0);
if(div.length == 0) {
div = $('<a class="ace-onpage-help" href="#" />').appendTo(container);
div.attr('data-section', name);
div.on(ace.click_event, function(e) {
e.preventDefault();
launch_help_modal(name);
});
}
var rect = rects[name];
if(rect.is_hidden) {
div.addClass('hidden');
return;
}
div.css({
left: rect.left,
top: rect.top,
width: rect.width,
height: rect.height
});
div.removeClass('hidden');
div.removeClass('smaller smallest');
if(rect.height < 55 || rect.width < 55) {
div.addClass('smallest');
}
else if(rect.height < 75 || rect.width < 75) {
div.addClass('smaller');
}
}
var nav_list = [];
var nav_pos = -1;
var mbody = null, mbody_scroll = null;
function launch_help_modal(name, save_to_list) {
name = name.replace(/^#/g, '');
var modal = $('#onpage-help-modal');
if(modal.length == 0) {
modal = $('<div id="onpage-help-modal" class="modal onpage-help-modal" tabindex="-1" role="dialog" aria-labelledby="HelpModalDialog" aria-hidden="true">\
<div class="modal-dialog modal-lg">\
<div class="modal-content">\
<div class="modal-header">\
<div class="pull-right modal-buttons">\
<button aria-hidden="true" data-goup="modal" type="button" class="disabled btn btn-white btn-success btn-sm"><i class="ace-icon fa fa-level-up fa-flip-horizontal bigger-125 icon-only"></i></button>\
&nbsp;\
<button aria-hidden="true" data-goback="modal" type="button" class="disabled btn btn-white btn-info btn-sm"><i class="ace-icon fa fa-arrow-left icon-only"></i></button>\
<button aria-hidden="true" data-goforward="modal" type="button" class="disabled btn btn-white btn-info btn-sm"><i class="ace-icon fa fa-arrow-right icon-only"></i></button>\
&nbsp;\
<button aria-hidden="true" data-dismiss="modal" class="btn btn-white btn-danger btn-sm" type="button"><i class="ace-icon fa fa-times icon-only"></i></button>\
</div>\
<h4 class="modal-title">Help Dialog/ <small></small></h4>\
</div>\
<div class="modal-body"> <div class="onpage-help-content"></div> </div>\
</div>\
</div>\
</div>').appendTo('body');
mbody = modal.find('.modal-body');
modal.css({'overflow' : 'hidden'})
mbody.ace_scroll({hoverReset: false, size: $(window).innerHeight() - 150, lockAnyway: true, styleClass: 'scroll-margin scroll-dark'})
$('#onpage-help-modal')
.on('show.bs.modal', function() {
releaseFocus();
})
.on('hidden.bs.modal', function() {
captureFocus();
});
$(document).on('shown.ace.widget hidden.ace.widget', '.help-content .widget-box', function() {
mbody.ace_scroll('reset');
});
}
if( !modal.hasClass('in') ) {
if(document.body.lastChild != modal.get(0)) $(document.body).append(modal);//move it to become the last element of body
modal.modal('show');
var diff = parseInt(modal.find('.modal-dialog').css('margin-top'));
diff = diff + 110 + parseInt(diff / 2);
mbody.ace_scroll('update', { size: $(window).innerHeight() - diff });
}
modal.find('.modal-title').wrapInner("<span class='hidden' />").append('<i class="fa fa-spinner fa-spin blue bigger-125"></i>');
var content = $('.onpage-help-content');
content.addClass('hidden')
$(document.body).removeClass('modal-open');
if(name.indexOf('file:') >= 0) {
var parts = name.match(/file\:(.*)\:(.+)/i);
if(parts.length == 3) display_codeview(parts[2], parts[1], false);
return;
}
var url = name.replace(/\..*$/g, '')
var parts = url.split('/');
if(parts.length == 1) {
if(url.length == 0) url = 'intro';
url = url+'/index.html';
}
else if(parts.length > 1) {
url = url+'.html';
}
$.ajax({url: $base+"/docs/sections/" + url, dataType: 'text'})
.done(function(result) {
var find1 = 'data-id="#'+name+'"';
var pos1 = result.indexOf(find1);
var tname = name;
if(pos1 == -1) {
//if no data-id="#something.part" go for data-id="#something" instead
var tpos
var tfind1
if((tpos = tname.lastIndexOf('.')) > -1) {
tname = tname.substr(0, tpos);
tfind1 = 'data-id="#'+tname+'"';
pos1 = result.indexOf(tfind1);
pos1 += tfind1.length + 1
}
}
else pos1 += find1.length + 1
var pos2 = result.indexOf("</h", pos1);
modal.find('.modal-title').addClass('blue').html( result.substring(pos1, pos2) );
find1 = '<!-- #section:'+name+' -->';
pos1 = result.indexOf(find1);
pos2 = result.indexOf('<!-- /section:'+name+' -->', pos1);
result = result.substring(pos1 + find1.length + 1, pos2);
result = result.replace(/\<pre(?:\s+)data\-language=["'](?:html|javascript|php)["']\>([\S|\s]+?)\<\/pre\>/ig, function(a, b){
return a.replace(b , b.replace(/\</g , '&lt;').replace(/\>/g , '&gt;'));
});
content.empty().append(result);
content
.find('.info-section').each(function() {
var header = $(this).prevAll('.info-title').eq(0);
if(header.length == 0) return false;
header = header.addClass('widget-title').wrap('<div class="widget-header" />')
.parent().append('<div class="widget-toolbar no-border">\
<a href="#" data-action="collapse">\
<i data-icon-hide="fa-minus" data-icon-show="fa-plus" class="ace-icon fa fa-plus"></i>\
</a>\
</div>').closest('.widget-header');
$(this).wrap('<div class="widget-box transparent collapsed"><div class="widget-body"><div class="widget-main"></div></div></div>');
$(this).closest('.widget-box').prepend(header);
});
content.removeClass('hidden');
content.find('span.thumbnail img').each(function() {
var src = $(this).attr('src');
$(this)
.attr('src', $base+"/docs/" + src)
.one('load', function() {
mbody.ace_scroll('reset');
});
});
Rainbow.color(content.get(0), function(){
mbody.ace_scroll('reset');
});
//save history list
add_to_nav_list(name, save_to_list);
var pos = -1;
if((pos = name.lastIndexOf('.')) > -1) {
name = name.substr(0, pos);
modal.find('button[data-goup=modal]').removeClass('disabled').attr('data-url', name);
}
else {
modal.find('button[data-goup=modal]').addClass('disabled').blur();
}
})
.fail(function() {
modal.find('.modal-title').find('.fa-spin').remove().end().find('.hidden').children().unwrap();
mbody.ace_scroll('reset');
});
}//launch_help_modal
$(document).on(ace.click_event, '.help-content > .widget-box > .widget-header > .info-title', function(e) {
var widget_box = $(this).closest('.widget-box').widget_box('toggle');
});
$(document).on(ace.click_event, '.help-more', function(e) {
e.preventDefault();
var href = $(this).attr('href');
launch_help_modal(href);
});
function add_to_nav_list(name, save_to_list) {
if(save_to_list !== false) {
if(nav_list.length > 0) {
nav_list = nav_list.slice(0, nav_pos + 1);
}
if(nav_list[nav_list.length - 1] != name) {
nav_list.push(name);
nav_pos = nav_list.length - 1;
}
}
var modal = $('#onpage-help-modal');
if(nav_pos == 0){
modal.find('button[data-goback=modal]').addClass('disabled').blur();
}
else {
modal.find('button[data-goback=modal]').removeClass('disabled');
}
if(nav_pos == nav_list.length - 1){
modal.find('button[data-goforward=modal]').addClass('disabled').blur();
}
else {
modal.find('button[data-goforward=modal]').removeClass('disabled');
}
}
$(document).on(ace.click_event, 'button[data-goforward=modal]', function() {
if(nav_pos < nav_list.length - 1) {
nav_pos++;
launch_help_modal(nav_list[nav_pos], false);
}
});
$(document).on(ace.click_event, 'button[data-goback=modal]', function() {
if(nav_pos > 0) {
nav_pos--;
launch_help_modal(nav_list[nav_pos], false);
}
});
$(document).on(ace.click_event, 'button[data-goup=modal]', function() {
var $this = $(this), url;
if( $this.hasClass('disabled') || !(url = $this.attr('data-url')) ) return;
launch_help_modal(url , true)
});
$(document).on(ace.click_event, '.open-file[data-open-file]', function() {
$('#onpage-help-modal').find('.modal-title').wrapInner("<span class='hidden' />").append('<i class="fa fa-spinner fa-spin blue bigger-125"></i>');
$('.onpage-help-content').addClass('hidden')
var url = $(this).text();
var language = $(this).attr('data-open-file');
display_codeview(url, language, true);
});
function display_codeview(url, language, save_to_list) {
$.ajax({url: $base+'/'+url, dataType:'text'})
.done(function(content) {
if(language != 'json') {
if(language != 'css') {
//replace each tab character with two spaces (only those that start at a new line)
content = content.replace(/\n[\t]{1,}/g, function(p, q) {
return p.replace(/\t/g, " ");
});
} else {
content = content.replace(/\t/g , " ")
}
}
else {
language = '';
content = JSON.stringify(JSON.parse(content), null, 2);
}
var modal = $('#onpage-help-modal');
add_to_nav_list('file:'+language+':'+url, save_to_list);
modal.find('button[data-goup=modal]').addClass('disabled').blur();
content = content.replace(/\>/g, '&gt;').replace(/\</g, '&lt;')
Rainbow.color(content, language, function(highlighted_code) {
modal.find('.modal-title').html(url).wrapInner('<code />');;
$('.onpage-help-content').removeClass('hidden').empty().html(highlighted_code).wrapInner('<pre data-language="'+language+'" />');
modal.find('.modal-body').ace_scroll('reset');
});
});
}
}

View File

@@ -0,0 +1,17 @@
/**
The autocomplete dropdown when typing inside search box.
<u><i class="glyphicon glyphicon-flash"></i> You don't need this. Used for demo only</u>
*/
ace.enable_searchbox_autocomplete = function($) {
ace.vars['US_STATES'] = ["Alabama","Alaska","Arizona","Arkansas","California","Colorado","Connecticut","Delaware","Florida","Georgia","Hawaii","Idaho","Illinois","Indiana","Iowa","Kansas","Kentucky","Louisiana","Maine","Maryland","Massachusetts","Michigan","Minnesota","Mississippi","Missouri","Montana","Nebraska","Nevada","New Hampshire","New Jersey","New Mexico","New York","North Dakota","North Carolina","Ohio","Oklahoma","Oregon","Pennsylvania","Rhode Island","South Carolina","South Dakota","Tennessee","Texas","Utah","Vermont","Virginia","Washington","West Virginia","Wisconsin","Wyoming"]
try {
$('#nav-search-input').typeahead({
source: ace.vars['US_STATES'],
updater:function (item) {
//when an item is selected from dropdown menu, focus back to input element
$('#nav-search-input').focus();
return item;
}
});
} catch(e) {}
}

View File

@@ -0,0 +1,101 @@
/**
<b>RTL</b> (right-to-left direction for Arabic, Hebrew, Persian languages).
It's good for demo only.
You should hard code RTL-specific changes inside your HTML/server-side code.
Dynamically switching to RTL using Javascript is not a good idea.
Please refer to documentation for more info.
*/
ace.settings_rtl = function($) {
//Switching to RTL (right to left) Mode
$('#ace-settings-rtl').removeAttr('checked').on('click', function(){
ace.switch_direction(jQuery);
});
}
//>>> you should hard code changes inside HTML for RTL direction
//you shouldn't use this function to switch direction
//this is only for dynamically switching for demonstration
//take a look at this function to see what changes should be made
//also take a look at docs for some tips
ace.switch_direction = function($) {
var $body = $(document.body);
$body
.toggleClass('rtl')
//toggle pull-right class on dropdown-menu
.find('.dropdown-menu:not(.datepicker-dropdown,.colorpicker)').toggleClass('dropdown-menu-right')
.end()
//swap pull-left & pull-right
.find('.pull-right:not(.dropdown-menu,blockquote,.profile-skills .pull-right)').removeClass('pull-right').addClass('tmp-rtl-pull-right')
.end()
.find('.pull-left:not(.dropdown-submenu,.profile-skills .pull-left)').removeClass('pull-left').addClass('pull-right')
.end()
.find('.tmp-rtl-pull-right').removeClass('tmp-rtl-pull-right').addClass('pull-left')
.end()
.find('.chosen-select').toggleClass('chosen-rtl').next().toggleClass('chosen-rtl');
function swap_classes(class1, class2) {
$body
.find('.'+class1).removeClass(class1).addClass('tmp-rtl-'+class1)
.end()
.find('.'+class2).removeClass(class2).addClass(class1)
.end()
.find('.tmp-rtl-'+class1).removeClass('tmp-rtl-'+class1).addClass(class2)
}
swap_classes('align-left', 'align-right');
swap_classes('no-padding-left', 'no-padding-right');
swap_classes('arrowed', 'arrowed-right');
swap_classes('arrowed-in', 'arrowed-in-right');
swap_classes('tabs-left', 'tabs-right');
swap_classes('messagebar-item-left', 'messagebar-item-right');//for inbox page
//mirror all icons and attributes that have a "fa-*-right|left" attrobute
$('.fa').each(function() {
if(this.className.match(/ui-icon/) || $(this).closest('.fc-button').length > 0) return;
//skip mirroring icons of plugins that have built in RTL support
var l = this.attributes.length;
for(var i = 0 ; i < l ; i++) {
var val = this.attributes[i].value;
if(val.match(/fa\-(?:[\w\-]+)\-left/))
this.attributes[i].value = val.replace(/fa\-([\w\-]+)\-(left)/i , 'fa-$1-right')
else if(val.match(/fa\-(?:[\w\-]+)\-right/))
this.attributes[i].value = val.replace(/fa\-([\w\-]+)\-(right)/i , 'fa-$1-left')
}
});
//browsers are incosistent with horizontal scroll and RTL
//so let's make our scrollbars LTR and wrap the content inside RTL
var rtl = $body.hasClass('rtl');
if(rtl) {
$('.scroll-hz').addClass('make-ltr')
.find('.scroll-content')
.wrapInner('<div class="make-rtl" />');
}
else {
//remove the wrap
$('.scroll-hz').removeClass('make-ltr')
.find('.make-rtl').children().unwrap();
}
if($.fn.ace_scroll) $('.scroll-hz').ace_scroll('reset') //to reset scrollLeft
//redraw the traffic pie chart on homepage with a different parameter
try {
var placeholder = $('#piechart-placeholder');
if(placeholder.length > 0) {
var pos = $(document.body).hasClass('rtl') ? 'nw' : 'ne';//draw on north-west or north-east?
placeholder.data('draw').call(placeholder.get(0) , placeholder, placeholder.data('chart'), pos);
}
}catch(e) {}
//force redraw(because of webkit)
/**setTimeout(function() {
ace.helper.redraw(document.body);
ace.helper.redraw($('.main-content').get(0));
}, 10);*/
}

View File

@@ -0,0 +1,94 @@
/**
<b>Select a different skin</b>. It's good for demo only.
You should hard code skin-specific changes inside your HTML/server-side code.
Please refer to documentation for more info.
*/
ace.settings_skin = function($) {
try {
$('#skin-colorpicker').ace_colorpicker();
} catch(e) {}
$('#skin-colorpicker').on('change', function(){
var skin_class = $(this).find('option:selected').data('skin');
//skin cookie tip
var body = $(document.body);
body.removeClass('no-skin skin-1 skin-2 skin-3');
//if(skin_class != 'skin-0') {
body.addClass(skin_class);
ace.data.set('skin', skin_class);
//save the selected skin to cookies
//which can later be used by your server side app to set the skin
//for example: <body class="<?php echo $_COOKIE['ace.skin']; ?>"
//} else ace.data.remove('skin');
var skin3_colors = ['red', 'blue', 'green', ''];
//undo skin-1
$('.ace-nav > li.grey').removeClass('dark');
//undo skin-2
$('.ace-nav > li').removeClass('no-border margin-1');
$('.ace-nav > li:not(:last-child)').removeClass('light-pink').find('> a > '+ace.vars['.icon']).removeClass('pink').end().eq(0).find('.badge').removeClass('badge-warning');
$('.sidebar-shortcuts .btn')
.removeClass('btn-pink btn-white')
.find(ace.vars['.icon']).removeClass('white');
//undo skin-3
$('.ace-nav > li.grey').removeClass('red').find('.badge').removeClass('badge-yellow');
$('.sidebar-shortcuts .btn').removeClass('btn-primary btn-white')
var i = 0;
$('.sidebar-shortcuts .btn').each(function() {
$(this).find(ace.vars['.icon']).removeClass(skin3_colors[i++]);
})
var skin0_buttons = ['btn-success', 'btn-info', 'btn-warning', 'btn-danger'];
if(skin_class == 'no-skin') {
var i = 0;
$('.sidebar-shortcuts .btn').each(function() {
$(this).attr('class', 'btn ' + skin0_buttons[i++%4]);
})
}
else if(skin_class == 'skin-1') {
$('.ace-nav > li.grey').addClass('dark');
var i = 0;
$('.sidebar-shortcuts')
.find('.btn').each(function() {
$(this).attr('class', 'btn ' + skin0_buttons[i++%4]);
})
}
else if(skin_class == 'skin-2') {
$('.ace-nav > li').addClass('no-border margin-1');
$('.ace-nav > li:not(:last-child)').addClass('light-pink').find('> a > '+ace.vars['.icon']).addClass('pink').end().eq(0).find('.badge').addClass('badge-warning');
$('.sidebar-shortcuts .btn').attr('class', 'btn btn-white btn-pink')
.find(ace.vars['.icon']).addClass('white');
}
//skin-3
//change shortcut buttons classes, this should be hard-coded if you want to choose this skin
else if(skin_class == 'skin-3') {
body.addClass('no-skin');//because skin-3 has many parts of no-skin as well
$('.ace-nav > li.grey').addClass('red').find('.badge').addClass('badge-yellow');
var i = 0;
$('.sidebar-shortcuts .btn').each(function() {
$(this).attr('class', 'btn btn-primary btn-white');
$(this).find(ace.vars['.icon']).addClass(skin3_colors[i++]);
})
}
//some sizing differences may be there in skins, so reset scrollbar size
if('sidebar_scroll' in ace.helper) ace.helper.sidebar_scroll.reset();
});
}

View File

@@ -0,0 +1,85 @@
/**
<b>Settings box</b>. It's good for demo only. You don't need this.
*/
ace.settings_box = function($) {
$('#ace-settings-btn').on(ace.click_event, function(e){
e.preventDefault();
$(this).toggleClass('open');
$('#ace-settings-box').toggleClass('open');
});
$('#ace-settings-navbar').on('click', function(){
ace.settings.navbar_fixed(this.checked);//@ ace-extra.js
//$(window).triggerHandler('resize.navbar');
//force redraw?
//if(ace.vars['webkit']) ace.helper.redraw(document.body);
}).each(function(){this.checked = ace.settings.is('navbar', 'fixed')})
$('#ace-settings-sidebar').on('click', function(){
ace.settings.sidebar_fixed(this.checked);//@ ace-extra.js
//if(ace.vars['webkit']) ace.helper.redraw(document.body);
}).each(function(){this.checked = ace.settings.is('sidebar', 'fixed')})
$('#ace-settings-breadcrumbs').on('click', function(){
ace.settings.breadcrumbs_fixed(this.checked);//@ ace-extra.js
//if(ace.vars['webkit']) ace.helper.redraw(document.body);
}).each(function(){this.checked = ace.settings.is('breadcrumbs', 'fixed')})
$('#ace-settings-add-container').on('click', function(){
ace.settings.main_container_fixed(this.checked);//@ ace-extra.js
//if(ace.vars['webkit']) ace.helper.redraw(document.body);
}).each(function(){this.checked = ace.settings.is('main-container', 'fixed')})
$('#ace-settings-compact').removeAttr('checked').on('click', function(){
if(this.checked) {
$('#sidebar').addClass('compact');
var hover = $('#ace-settings-hover');
if( hover.length > 0 && !hover.get(0).checked ) {
hover.removeAttr('checked').trigger('click');
}
}
else {
$('#sidebar').removeClass('compact');
if('sidebar_scroll' in ace.helper) ace.helper.sidebar_scroll.reset();
}
});
$('#ace-settings-highlight').removeAttr('checked').on('click', function(){
if(this.checked) $('#sidebar .nav-list > li').addClass('highlight');
else $('#sidebar .nav-list > li').removeClass('highlight');
});
$('#ace-settings-hover').removeAttr('checked').on('click', function(){
if($('.sidebar').hasClass('h-sidebar')) return;
if(this.checked) {
ace.vars['no-scroll'] = true;
$('#sidebar li').addClass('hover')
.filter('.open').removeClass('open').find('> .submenu').css('display', 'none');
//and remove .open items
}
else {
ace.vars['no-scroll'] = false;
$('#sidebar li.hover').removeClass('hover');
var compact = $('#ace-settings-compact');
if( compact.length > 0 && compact.get(0).checked ) {
compact.trigger('click');
}
if('sidebar_hover' in ace.helper) ace.helper.sidebar_hover.reset();
}
if('sidebar_scroll' in ace.helper) ace.helper.sidebar_scroll.reset();
});
}

View File

@@ -0,0 +1,355 @@
/**
<b>Scrollbars for sidebar</b>. This approach can <span class="text-danger">only</span> be used on <u>fixed</u> sidebar.
It doesn't use <u>"overflow:hidden"</u> CSS property and therefore can be used with <u>.hover</u> submenus and minimized sidebar.
Except when in mobile view and menu toggle button is not in the navbar.
*/
ace.sidebar_scrollable = function($ , scroll_to_active, include_shortcuts, include_toggle, smooth_scroll, scrollbars_outside) {
if( !$.fn.ace_scroll ) return;
var old_safari = ace.vars['safari'] && navigator.userAgent.match(/version\/[1-5]/i)
//NOTE
//Safari on windows has not been updated for a long time.
//And it has a problem when sidebar is fixed&scrollable and there is a CSS3 animation inside page content.
//Very probably windows users of safari have migrated to another browser by now!
var $sidebar = $('.sidebar'),
$navbar = $('.navbar'),
$nav = $sidebar.find('.nav-list'),
$toggle = $sidebar.find('.sidebar-toggle'),
$shortcuts = $sidebar.find('.sidebar-shortcuts'),
$window = $(window),
sidebar = $sidebar.get(0),
nav = $nav.get(0);
if(!sidebar || !nav) return;
var scroll_div = null,
scroll_content = null,
scroll_content_div = null,
bar = null,
ace_scroll = null;
var is_scrolling = false,
_initiated = false;
var scroll_to_active = scroll_to_active || false,
include_shortcuts = include_shortcuts || false,
include_toggle = include_toggle || false,
only_if_fixed = true;
var is_sidebar_fixed =
'getComputedStyle' in window ?
//sidebar.offsetHeight is used to force redraw and recalculate 'sidebar.style.position' esp for webkit!
function() { sidebar.offsetHeight; return window.getComputedStyle(sidebar).position == 'fixed' }
:
function() { sidebar.offsetHeight; return $sidebar.css('position') == 'fixed' }
//sometimes when navbar is fixed, sidebar automatically becomes fixed without needing ".sidebar-fixed" class
//currently when mobile_style == 1
var $avail_height, $content_height;
var sidebar_fixed = is_sidebar_fixed(),
horizontal = $sidebar.hasClass('h-sidebar');
var scrollbars = ace.helper.sidebar_scroll = {
available_height: function() {
//available window space
var offset = $nav.parent().offset();//because `$nav.offset()` considers the "scrolled top" amount as well
if(sidebar_fixed) offset.top -= ace.helper.scrollTop();
return $window.innerHeight() - offset.top - ( include_toggle ? 0 : $toggle.outerHeight() );
},
content_height: function() {
return nav.scrollHeight;
},
initiate: function(on_page_load) {
if( _initiated ) return;
if( !sidebar_fixed ) return;//eligible??
//return if we want scrollbars only on "fixed" sidebar and sidebar is not "fixed" yet!
//initiate once
$nav.wrap('<div style="position: relative;" />');
$nav.after('<div><div></div></div>');
$nav.wrap('<div class="nav-wrap" />');
if(!include_toggle) $toggle.css({'z-index': 1});
if(!include_shortcuts) $shortcuts.css({'z-index': 99});
scroll_div = $nav.parent().next()
.ace_scroll({
size: scrollbars.available_height(),
reset: true,
mouseWheelLock: true,
hoverReset: false,
dragEvent: true,
touchDrag: false//disable touch drag event on scrollbars, we'll add a custom one later
})
.closest('.ace-scroll').addClass('nav-scroll');
ace_scroll = scroll_div.data('ace_scroll');
scroll_content = scroll_div.find('.scroll-content').eq(0);
scroll_content_div = scroll_content.find(' > div').eq(0);
bar = scroll_div.find('.scroll-bar').eq(0);
if(include_shortcuts) {
$nav.parent().prepend($shortcuts).wrapInner('<div />');
$nav = $nav.parent();
}
if(include_toggle) {
$nav.append($toggle);
$nav.closest('.nav-wrap').addClass('nav-wrap-t');//it just helps to remove toggle button's top border and restore li:last-child's bottom border
}
$nav.css({position: 'relative'});
if( scrollbars_outside === true ) scroll_div.addClass('scrollout');
nav = $nav.get(0);
nav.style.top = 0;
scroll_content.on('scroll.nav', function() {
nav.style.top = (-1 * this.scrollTop) + 'px';
});
$nav.on('mousewheel.ace_scroll DOMMouseScroll.ace_scroll', function(event){
//transfer $nav's mousewheel event to scrollbars
return scroll_div.trigger(event);
});
//you can also use swipe event in a similar way //swipe.nav
var content = scroll_content.get(0);
$nav.on('ace_drag.nav', function(event) {
if(!is_scrolling) return;
if(event.direction == 'up' || event.direction == 'down') {
//event.stopPropagation();
ace_scroll.move_bar(true);
move_nav = false;//update "nav.style.top" here no need to do this on('scroll.nav')!
var distance = event.dy;
//distance = parseInt(Math.min($avail_height, distance))
if(Math.abs(distance) > 20) distance = distance * 2;
if(distance != 0) {
content.scrollTop = content.scrollTop + distance;
nav.style.top = (-1 * content.scrollTop) + 'px';
}
}
});
//for drag only
if(smooth_scroll) {
$nav.on('ace_dragStart.nav', function(event) {
event.stopPropagation();
$nav.css('transition-property', 'none');
bar.css('transition-property', 'none');
}).on('ace_dragEnd.nav', function(event) {
event.stopPropagation();
$nav.css('transition-property', 'top');
bar.css('transition-property', 'top');
});
}
if(old_safari && !include_toggle) {
var toggle = $toggle.get(0);
if(toggle) scroll_content.on('scroll.safari', function() {
ace.helper.redraw(toggle);
});
}
_initiated = true;
//if the active item is not visible, scroll down so that it becomes visible
//only the first time, on page load
if(on_page_load == true) {
scrollbars.reset();//try resetting at first
if( scroll_to_active && ace_scroll.is_active() ) {
var $active;
var nav_list = $sidebar.find('.nav-list')
if(ace.vars['minimized'] && !ace.vars['collapsible']) {
$active = nav_list.find('> .active')
}
else {
$active = $nav.find('> .active.hover')
if($active.length == 0) $active = $nav.find('.active:not(.open)')
}
var top = $active.outerHeight();
nav_list = nav_list.get(0);
var active = $active.get(0);
while(active != nav_list) {
top += active.offsetTop;
active = active.parentNode;
}
var scroll_amount = top - scroll_div.height();
if(scroll_amount > 0) {
nav.style.top = -scroll_amount + 'px';
scroll_content.scrollTop(scroll_amount);
}
}
scroll_to_active = false;
}
if( typeof smooth_scroll === 'number' && smooth_scroll > 0) {
$nav.css({'transition-property': 'top', 'transition-duration': (smooth_scroll / 1000).toFixed(2)+'s'})
bar.css({'transition-property': 'top', 'transition-duration': (smooth_scroll / 1500).toFixed(2)+'s'})
scroll_div
.on('drag.start', function(e) {
e.stopPropagation();
$nav.css('transition-property', 'none')
})
.on('drag.end', function(e) {
e.stopPropagation();
$nav.css('transition-property', 'top')
});
}
if(ace.vars['android']) {
//force hide address bar, because its changes don't trigger window resize and become kinda ugly
var val = ace.helper.scrollTop();
if(val < 2) {
window.scrollTo( val, 0 );
setTimeout( function() {
scrollbars.reset();
}, 20 );
}
var last_height = ace.helper.winHeight() , new_height;
$(window).on('scroll.ace_scroll', function() {
if(is_scrolling && ace_scroll.is_active()) {
new_height = ace.helper.winHeight();
if(new_height != last_height) {
last_height = new_height;
scrollbars.reset();
}
}
});
}
},
reset: function() {
if( !sidebar_fixed ) {
scrollbars.disable();
return;//eligible??
}
//return if we want scrollbars only on "fixed" sidebar and sidebar is not "fixed" yet!
if( !_initiated ) scrollbars.initiate();
//initiate scrollbars if not yet
//enable if:
//menu is not collapsible mode (responsive navbar-collapse mode which has default browser scrollbar)
//menu is not horizontal or horizontal but mobile view (which is not navbar-collapse)
//and available height is less than nav's height
var enable_scroll = !ace.vars['collapsible']
&& (!horizontal || (horizontal && ace.vars['mobile_view']))
&& ($avail_height = scrollbars.available_height()) < ($content_height = nav.scrollHeight);
is_scrolling = true;
if( enable_scroll ) {
scroll_content_div.css({height: $content_height, width: 8});
scroll_div.prev().css({'max-height' : $avail_height})
ace_scroll.update({size: $avail_height}).enable().reset();
}
if( !enable_scroll || !ace_scroll.is_active() ) {
if(is_scrolling) scrollbars.disable();
}
else $sidebar.addClass('sidebar-scroll');
//return is_scrolling;
},
disable : function() {
is_scrolling = false;
if(scroll_div) {
scroll_div.css({'height' : '', 'max-height' : ''});
scroll_content_div.css({height: '', width: ''});//otherwise it will have height and takes up some space even when invisible
scroll_div.prev().css({'max-height' : ''})
ace_scroll.disable();
}
if(parseInt(nav.style.top) < 0 && smooth_scroll && ace.vars['transition']) {
$nav.one('transitionend.trans webkitTransitionEnd.trans mozTransitionEnd.trans oTransitionEnd.trans', function() {
$sidebar.removeClass('sidebar-scroll');
$nav.off('.trans');
});
} else {
$sidebar.removeClass('sidebar-scroll');
}
nav.style.top = 0;
},
prehide: function(height_change) {
if(!is_scrolling || ace.vars['minimized']) return;
if(scrollbars.content_height() + height_change < scrollbars.available_height()) {
scrollbars.disable();
}
else if(height_change < 0) {
//if content height is decreasing
//let's move nav down while a submenu is being hidden
var scroll_top = scroll_content.scrollTop() + height_change
if(scroll_top < 0) return;
nav.style.top = (-1 * scroll_top) + 'px';
}
}
}
scrollbars.initiate(true);//true = on_page_load
//reset on document and window changes
$(document).on('settings.ace.scroll', function(ev, event_name, event_val){
if( event_name == 'sidebar_collapsed' && sidebar_fixed ) {
scrollbars.reset();
}
else if( event_name === 'sidebar_fixed' || event_name === 'navbar_fixed' ) {
//sidebar_fixed = event_val;
sidebar_fixed = is_sidebar_fixed()
if(sidebar_fixed && !is_scrolling) {
scrollbars.reset();
}
else if( !sidebar_fixed ) {
scrollbars.disable();
}
}
});
$window.on('resize.ace.scroll', function(){
sidebar_fixed = is_sidebar_fixed()
scrollbars.reset();
})
//change scrollbar size after a submenu is hidden/shown
//but don't change if sidebar is minimized
$sidebar.on('hidden.ace.submenu shown.ace.submenu', '.submenu', function(e) {
e.stopPropagation();
if(!ace.vars['minimized']) {
//webkit has a little bit of a glitch!!!
if(ace.vars['webkit']) setTimeout(function() { scrollbars.reset() } , 0);
else scrollbars.reset();
}
});
}

View File

@@ -0,0 +1,229 @@
/**
<b>Scrollbars for sidebar</b>. This approach can be used on fixed or normal sidebar.
It uses <u>"overflow:hidden"</u> so you can't use <u>.hover</u> submenus and it will be disabled when sidebar is minimized.
It may also be marginally (negligibily) faster especially when resizing browser window.
*/
ace.sidebar_scrollable = function($ , only_if_fixed, scroll_to_active, include_shortcuts, include_toggle) {
if( !$.fn.ace_scroll ) return;
var old_safari = ace.vars['safari'] && navigator.userAgent.match(/version\/[1-5]/i)
//NOTE
//Safari on windows has not been updated for a long time.
//And it has a problem when sidebar is fixed&scrollable and there is a CSS3 animation inside page content.
//Very probably windows users of safari have migrated to another browser by now!
var $sidebar = $('.sidebar'),
$navbar = $('.navbar'),
$nav = $sidebar.find('.nav-list'),
$toggle = $sidebar.find('.sidebar-toggle'),
$shortcuts = $sidebar.find('.sidebar-shortcuts'),
$window = $(window),
sidebar = $sidebar.get(0),
nav = $nav.get(0);
if(!sidebar || !nav) return;
if( $sidebar.find('li.hover').length > 0 ) ace.vars['no-scroll'] = true;
var scroll_div = null,
scroll_content = null,
scroll_content_div = null,
bar = null,
ace_scroll = null;
var is_scrolling = false,
_initiated = false;
var scroll_to_active = scroll_to_active || false,
include_shortcuts = include_shortcuts || false,
include_toggle = include_toggle || false,
only_if_fixed = only_if_fixed && true;
var is_sidebar_fixed =
'getComputedStyle' in window ?
//sidebar.offsetHeight is used to force redraw and recalculate 'sidebar.style.position' esp for webkit!
function() { sidebar.offsetHeight; return window.getComputedStyle(sidebar).position == 'fixed' }
:
function() { sidebar.offsetHeight; return $sidebar.css('position') == 'fixed' }
//sometimes when navbar is fixed, sidebar automatically becomes fixed without needing ".sidebar-fixed" class
//currently when mobile_style == 1
var $avail_height, $content_height;
var sidebar_fixed = is_sidebar_fixed(),
horizontal = $sidebar.hasClass('h-sidebar');
var scrollbars = ace.helper.sidebar_scroll = {
available_height: function() {
//available window space
var offset = $nav.parent().offset();//because `$nav.offset()` considers the "scrolled top" amount as well
if(sidebar_fixed) offset.top -= ace.helper.scrollTop();
return $window.innerHeight() - offset.top - ( include_toggle ? 0 : $toggle.outerHeight() );
},
content_height: function() {
return nav.scrollHeight;
},
initiate: function(on_page_load) {
if( _initiated ) return;
if( (only_if_fixed && !sidebar_fixed) || ace.vars['no-scroll'] === true ) return;//eligible??
//return if we want scrollbars only on "fixed" sidebar and sidebar is not "fixed" yet!
//initiate once
$nav.wrap('<div />');
if(include_shortcuts) $nav.parent().prepend($shortcuts);
if(include_toggle) $nav.parent().append($toggle);
scroll_div = $nav.parent()
.ace_scroll({
size: scrollbars.available_height(),
reset: true,
mouseWheelLock: true,
hoverReset: false
})
.closest('.ace-scroll').addClass('nav-scroll');
ace_scroll = scroll_div.data('ace_scroll');
scroll_content = scroll_div.find('.scroll-content').eq(0);
if(old_safari && !include_toggle) {
var toggle = $toggle.get(0);
if(toggle) scroll_content.on('scroll.safari', function() {
ace.helper.redraw(toggle);
});
}
_initiated = true;
//if the active item is not visible, scroll down so that it becomes visible
//only the first time, on page load
if(on_page_load == true) {
scrollbars.reset();//try resetting at first
if( scroll_to_active && ace_scroll.is_active() ) {
var $active;
var nav_list = $sidebar.find('.nav-list')
if(ace.vars['minimized'] && !ace.vars['collapsible']) {
$active = nav_list.find('> .active')
}
else {
$active = $nav.find('> .active.hover')
if($active.length == 0) $active = $nav.find('.active:not(.open)')
}
var top = $active.outerHeight();
nav_list = nav_list.get(0);
var active = $active.get(0);
while(active != nav_list) {
top += active.offsetTop;
active = active.parentNode;
}
var scroll_amount = top - scroll_div.height();
if(scroll_amount > 0) {
scroll_content.scrollTop(scroll_amount);
}
}
scroll_to_active = false;
}
},
reset: function() {
if( (only_if_fixed && !sidebar_fixed) || ace.vars['no-scroll'] === true ) {
scrollbars.disable();
return;//eligible??
}
//return if we want scrollbars only on "fixed" sidebar and sidebar is not "fixed" yet!
if( !_initiated ) scrollbars.initiate();
//initiate scrollbars if not yet
$sidebar.addClass('sidebar-scroll');
//enable if:
//menu is not minimized
//menu is not collapsible mode (responsive navbar-collapse mode which has default browser scroller)
//menu is not horizontal or horizontal but mobile view (which is not navbar-collapse)
//and available height is less than nav's height
var enable_scroll = !ace.vars['minimized'] && !ace.vars['collapsible']
&& (!horizontal || (horizontal && ace.vars['mobile_view']))
&& ($avail_height = scrollbars.available_height()) < ($content_height = nav.parentNode.scrollHeight);
is_scrolling = true;
if( enable_scroll && ace_scroll ) {
//scroll_content_div.css({height: $content_height, width: 8});
//scroll_div.prev().css({'max-height' : $avail_height})
ace_scroll.update({size: $avail_height}).enable().reset();
}
if( !enable_scroll || !ace_scroll.is_active() ) {
if(is_scrolling) scrollbars.disable();
}
//return is_scrolling;
},
disable : function() {
is_scrolling = false;
if(ace_scroll) ace_scroll.disable();
$sidebar.removeClass('sidebar-scroll');
},
prehide: function(height_change) {
if( !is_scrolling || ace.vars['minimized'] ) return;
if(scrollbars.content_height() + height_change < scrollbars.available_height()) {
scrollbars.disable();
}
else if(height_change < 0) {
//if content height is decreasing
//let's move nav down while a submenu is being hidden
var scroll_top = scroll_content.scrollTop() + height_change
if(scroll_top < 0) return;
scroll_content.scrollTop(scroll_top);
}
}
}
scrollbars.initiate(true);//true = on_page_load
//reset on document and window changes
$(document).on('settings.ace.scroll', function(ev, event_name, event_val){
if( event_name == 'sidebar_collapsed' ) {
if(event_val == true) scrollbars.disable();//disable scroll if collapsed
else scrollbars.reset();
}
else if( event_name === 'sidebar_fixed' || event_name === 'navbar_fixed' ) {
//sidebar_fixed = event_val;
sidebar_fixed = is_sidebar_fixed()
if(sidebar_fixed && !is_scrolling) {
scrollbars.reset();
}
else if(!sidebar_fixed && only_if_fixed) {
scrollbars.disable();
}
}
});
$window.on('resize.ace.scroll', function(){
sidebar_fixed = is_sidebar_fixed()
scrollbars.reset();
})
//change scrollbar size after a submenu is hidden/shown
//but don't change if sidebar is minimized
$sidebar.on('hidden.ace.submenu shown.ace.submenu', '.submenu', function(e) {
e.stopPropagation();
if(!ace.vars['minimized']) {
//webkit has a little bit of a glitch!!!
if(ace.vars['webkit']) setTimeout(function() { scrollbars.reset() } , 0);
else scrollbars.reset();
}
});
}

View File

@@ -0,0 +1,155 @@
/**
<b>Sidebar functions</b>. Collapsing/expanding, toggling mobile view menu and other sidebar functions.
*/
ace.handle_side_menu = function($) {
var sidebar = $('.sidebar').eq(0);
$(document).on(ace.click_event+'.ace.menu', '#menu-toggler', function(){
sidebar.toggleClass('display');
$(this).toggleClass('display');
if( $(this).hasClass('display') && 'sidebar_scroll' in ace.helper )
{
ace.helper.sidebar_scroll.reset();
}
return false;
})
//sidebar collapse/expand button
.on(ace.click_event+'.ace.menu', '.sidebar-collapse', function(){
if(ace.vars['collapsible'] || ace.vars['horizontal']) return;
//var minimized = sidebar.hasClass('menu-min');
ace.vars['minimized'] = !ace.vars['minimized'];
ace.settings.sidebar_collapsed.call(this, ace.vars['minimized']);//@ ace-extra.js
//ace.settings.sidebar_collapsed(ace.vars['minimized']);
})
//this button is used in `mobile_style = 3` responsive menu style to expand minimized sidebar
.on(ace.click_event+'.ace.menu', '.sidebar-expand', function(){
if( ace.vars['minimized'] /**sidebar.hasClass('menu-min')*/ ) {
ace.settings.sidebar_collapsed.call(this, false , false);
//unminimize (remove .menu-min) but don't save changes to cookies
}
var icon = $(this).find(ace.vars['.icon']);
var $icon1 = icon.attr('data-icon1');//the icon for expanded state
var $icon2 = icon.attr('data-icon2');//the icon for collapsed state
if( sidebar.hasClass('responsive-min') ) {
icon.removeClass($icon1).addClass($icon2);
sidebar.removeClass('responsive-min');
sidebar.addClass('display responsive-max');
ace.vars['minimized'] = false
}
else {
icon.removeClass($icon2).addClass($icon1);
sidebar.removeClass('display responsive-max');
sidebar.addClass('responsive-min');
ace.vars['minimized'] = true
}
$(document).triggerHandler('settings.ace', ['sidebar_collapsed' , ace.vars['minimized']]);
});
//ios safari only has a bit of a problem not navigating to link address when scrolling down
var ios_fix = ace.vars['ios_safari'];//navigator.userAgent.match(/OS (5|6|7)(_\d)+ like Mac OS X/i);
//toggling submenu
$(document).on(ace.click_event+'.ace.submenu', '.sidebar .nav-list', function (ev) {
var nav_list = this;
//check to see if we have clicked on an element which is inside a .dropdown-toggle element?!
//if so, it means we should toggle a submenu
var link_element = $(ev.target).closest('a');
if(!link_element || link_element.length == 0) return;//return if not clicked inside a link element
var minimized = ace.vars['minimized'] && !ace.vars['collapsible'];
//if .sidebar is .navbar-collapse and in small device mode, then let minimized be uneffective
if( !link_element.hasClass('dropdown-toggle') ) {//it doesn't have a submenu return
//just one thing before we return
//if sidebar is collapsed(minimized) and we click on a first level menu item
//and the click is on the icon, not on the menu text then let's cancel event and cancel navigation
//Good for touch devices, that when the icon is tapped to see the menu text, navigation is cancelled
//navigation is only done when menu text is tapped
if( ace.click_event == "tap"
&&
minimized
&&
link_element.get(0).parentNode.parentNode == nav_list )//only level-1 links
{
var text = link_element.find('.menu-text').get(0);
if( ev.target != text && !$.contains(text , ev.target) ) {//not clicking on the text or its children
ev.preventDefault();
return false;
}
}
//some browsers need to be forced
if(ios_fix && link_element.attr('data-link') !== 'false') {//specify data-link attribute to ignore this
//ios safari only has a bit of a problem not navigating to link address when scrolling down
//please see issues section
document.location = link_element.attr('href');
ev.preventDefault();
return false;
}
return;
}
var sub = link_element.siblings('.submenu').get(0);
if(!sub) return false;
var height_change = 0;//the amount of height change in .nav-list
var duration = 250;//transition duration
var parent_ul = sub.parentNode.parentNode;
if
(
( minimized && parent_ul == nav_list )
||
( $(sub.parentNode).hasClass('hover') && !ace.vars['collapsible'] )
)
{
ev.preventDefault();
return false;
}
//if not open and visible, let's open it and make it visible
if( sub.scrollHeight == 0 ) {
$(parent_ul).find('> .open > .submenu').each(function() {
//close all other open submenus except for the active one
if(this != sub && !$(this.parentNode).hasClass('active')) {
height_change -= this.scrollHeight;
ace.submenu.hide(this, duration);
}
})
}
var toggle = 0;
if( (toggle = ace.submenu.toggle(sub , duration)) == 1 ) {
//== 1 means submenu is being shown
//if a submenu is being shown and another one previously started to hide, then we may need to update/hide scrollbars
//but if no previous submenu is being hidden, then no need to check if we need to hide the scrollbars in advance
if(height_change != 0) height_change += sub.scrollHeight;
} else if(toggle == -1) {
height_change -= sub.scrollHeight;
//== -1 means submenu is being hidden
}
//hide scrollbars if content is going to be small enough that scrollbars is not needed anymore
//do this almost before submenu hiding begins
if (height_change != 0 && 'sidebar_scroll' in ace.helper) {
ace.helper.sidebar_scroll.prehide(height_change);
}
ev.preventDefault();
return false;
})
}

View File

@@ -0,0 +1,111 @@
/**
<b>Toggle sidebar submenus</b>. This approach uses <u>CSS3</u> transitions.
It's a bit smoother but the transition does not work on IE9 and below and it is sometimes glitchy on Android's default browser.
*/
//CSS3 transition version, no animation on IE9 and below
ace.submenu = {
show : function(sub, duration) {
var $sub = $(sub);
var event;
$sub.trigger(event = $.Event('show.ace.submenu'))
if (event.isDefaultPrevented()) return false;
$sub
.css({
height: 0,
overflow: 'hidden',
display: 'block'
})
.removeClass('nav-hide').addClass('nav-show')//only for window < @grid-float-breakpoint and .navbar-collapse.menu-min
.parent().addClass('open');
if( duration > 0 ) {
$sub.css({height: sub.scrollHeight,
'transition-property': 'height',
'transition-duration': (duration/1000)+'s'})
}
var complete = function(ev) {
ev && ev.stopPropagation();
$sub
.css({'transition-property': '', 'transition-duration': '', overflow:'', height: ''})
//if(ace.vars['webkit']) ace.helper.redraw(sub);//little Chrome issue, force redraw ;)
if(ace.vars['transition']) $sub.off('.trans');
$sub.trigger($.Event('shown.ace.submenu'))
}
if( duration > 0 && ace.vars['transition'] ) {
$sub.one('transitionend.trans webkitTransitionEnd.trans mozTransitionEnd.trans oTransitionEnd.trans', complete);
}
else complete();
//there is sometimes a glitch, so maybe retry
if(ace.vars['android']) {
setTimeout(function() {
$sub.css({overflow:'', height: ''});
}, duration + 10);
}
return true;
}
,
hide : function(sub, duration) {
var $sub = $(sub);
var event;
$sub.trigger(event = $.Event('hide.ace.submenu'))
if (event.isDefaultPrevented()) return false;
$sub
.css({
height: sub.scrollHeight,
overflow: 'hidden'
})
.parent().removeClass('open');
sub.offsetHeight;
//forces the "sub" to re-consider the new 'height' before transition
if( duration > 0 ) {
$sub.css({'height': 0,
'transition-property': 'height',
'transition-duration': (duration/1000)+'s'});
}
var complete = function(ev) {
ev && ev.stopPropagation();
$sub
.css({display: 'none', overflow:'', height: '', 'transition-property': '', 'transition-duration': ''})
.removeClass('nav-show').addClass('nav-hide')//only for window < @grid-float-breakpoint and .navbar-collapse.menu-min
if(ace.vars['transition']) $sub.off('.trans');
$sub.trigger($.Event('hidden.ace.submenu'))
}
if( duration > 0 && ace.vars['transition'] ) {
$sub.one('transitionend.trans webkitTransitionEnd.trans mozTransitionEnd.trans oTransitionEnd.trans', complete);
}
else complete();
//there is sometimes a glitch, so maybe retry
if(ace.vars['android']) {
setTimeout(function() {
$sub.css({display: 'none', overflow:'', height: ''})
}, duration + 10);
}
return true;
}
,
toggle : function(element, duration) {
if( element.scrollHeight == 0 ) {//if an element is hidden scrollHeight becomes 0
if(ace.submenu.show(element, duration)) return 1;
} else {
if(ace.submenu.hide(element, duration)) return -1;
}
return 0;
}
}

View File

@@ -0,0 +1,74 @@
/**
<b>Toggle sidebar submenus</b>. This approach uses <u>jQuery</u> animation and works on all browsers.
*/
ace.submenu = {
show : function(sub, duration) {
var $sub = $(sub);
var event;
$sub.trigger(event = $.Event('show.ace.submenu'))
if (event.isDefaultPrevented()) return false;
$sub
.css({height:0, overflow:'hidden', display:'block'})
.removeClass('nav-hide').addClass('nav-show')//only for window < 992px and .sidebar.navbar-collapse.menu-min
var complete = function() {
$sub
.css({overflow:'', height:''})
if(ace.vars.webkit) ace.helper.redraw(sub);//little webkit issue, force redraw ;)
$sub.trigger($.Event('shown.ace.submenu'))
}
$sub.parent().addClass('open');
if(duration > 0) {
$sub.animate({height:sub.scrollHeight} , {
duration: duration,
complete: complete
})
} else complete();
return true;
}
,
hide : function(sub, duration) {
var $sub = $(sub);
var event;
$sub.trigger(event = $.Event('hide.ace.submenu'))
if (event.isDefaultPrevented()) return false;
var complete = function() {
$sub
.css({display:'none', overflow:'', height:''})
.removeClass('nav-show').addClass('nav-hide')//only for window < @grid-float-breakpoint and .navbar-collapse.menu-min
$sub.trigger($.Event('hidden.ace.submenu'))
}
$sub
.css({overflow:'hidden', height:sub.scrollHeight})
.parent().removeClass('open');
if(duration > 0) {
$sub.animate({height:0}, {
duration: duration,
complete: complete
})
} else complete();
return true;
}
,
toggle : function(element, duration) {
if( element.scrollHeight == 0 ) {//if an element is hidden scrollHeight is 0
if(ace.submenu.show(element, duration)) return 1;
} else {
if(ace.submenu.hide(element, duration)) return -1;
}
return 0;
}
}

View File

@@ -0,0 +1,173 @@
/**
<b>Submenu hover adjustment</b>. Automatically move up a submenu to fit into screen when some part of it goes beneath window.
*/
ace.sidebar_hoverable = function($) {
if( !('querySelector' in document) || !('removeProperty' in document.body.style) ) return;
//ignore IE8 & below
//on window resize or sidebar expand/collapse a previously "pulled up" submenu should be reset back to its default position
//for example if "pulled up" in "responsive-min" mode, in "fullmode" should not remain "pulled up"
ace.helper.sidebar_hover = {
reset : function() {
$sidebar.find('.submenu').each(function() {
var sub = this, li = this.parentNode;
if(sub) {
sub.style.removeProperty('top')
sub.style.removeProperty('bottom');
var menu_text = li.querySelector('.menu-text');
if(menu_text) {
menu_text.style.removeProperty('margin-top')
}
}
if( li.className.lastIndexOf('_up') >= 0 ) {//has .pull_up
$(li).removeClass('pull_up');
}
});
}
}
var is_navbar_fixed =
'getComputedStyle' in window ?
//navbar.offsetHeight is used to force redraw and recalculate 'sidebar.style.position' esp for webkit!
function() { navbar.offsetHeight; return window.getComputedStyle(navbar).position == 'fixed' }
:
function() { navbar.offsetHeight; return $navbar.css('position') == 'fixed' }
$(window).on('resize.ace_hover', function() {
navbar_fixed = is_navbar_fixed();
ace.helper.sidebar_hover.reset();
})
$(document).on('settings.ace.hover', function(e, event_name, event_val) {
if(event_name == 'sidebar_collapsed') ace.helper.sidebar_hover.reset();
else if(event_name == 'navbar_fixed') navbar_fixed = event_val;
})
///////////////////////////////////////////////
var $sidebar = $('.sidebar').eq(0),
sidebar = $sidebar.get(0),
nav_list = $sidebar.find('.nav-list').get(0);
var $navbar = $('.navbar').eq(0),
navbar = $navbar.get(0),
horizontal = $sidebar.hasClass('h-sidebar'),
navbar_fixed = $navbar.css('position') == 'fixed';
$sidebar.find('.submenu').parent().addClass('hsub');//add .hsub (has-sub) class
//some mobile browsers don't have mouseenter
$sidebar.on('mouseenter.ace_hover', '.nav-list li.hsub', function (e) {
//ignore if collapsible mode (mobile view .navbar-collapse) so it doesn't trigger submenu movements
//or return if horizontal but not mobile_view (style 1&3)
if( ace.vars['collapsible'] || (horizontal && !ace.vars['mobile_view']) ) return;
var sub = this.querySelector('.submenu');
if(sub) {
//try to move/adjust submenu if the parent is a li.hover
if( ace.helper.hasClass(this, 'hover') ) {
adjust_submenu.call(this, sub);
}
//or if submenu is minimized
else if( this.parentNode == nav_list && ace.vars['minimized'] ) {
adjust_submenu.call(this, sub);
}
}
})
var $diff = 50;
function adjust_submenu(sub) {
var $sub = $(sub);
sub.style.removeProperty('top')
sub.style.removeProperty('bottom');
var menu_text = null
if( ace.vars['minimized'] && (menu_text = sub.parentNode.querySelector('.menu-text')) ) {
//2nd level items don't have .menu-text
menu_text.style.removeProperty('margin-top')
}
var off = $sub.offset();
var scroll = ace.helper.scrollTop();
var pull_up = false;
var $scroll = scroll
if( navbar_fixed ) {
$scroll += navbar.clientHeight + 1;
//let's avoid our submenu from going below navbar
//because of chrome z-index stacking issue and firefox's normal .submenu over fixed .navbar flicker issue
}
var sub_h = sub.scrollHeight;
if(menu_text) {
sub_h += 40;
off.top -= 40;
}
var sub_bottom = parseInt(off.top + sub_h)
var diff
//if the bottom of menu is going to go below visible window
if( (diff = sub_bottom - (window.innerHeight + scroll - 50)) > 0 ) {
//if it needs to be moved top a lot! use bottom unless it makes it go out of window top
if(sub_h - diff < $diff && off.top - diff > $scroll ) {
sub.style.top = 'auto';
sub.style.bottom = '-10px';
if( menu_text ) {
//menu_text.style.marginTop = -(sub_h - 10)+'px';
menu_text.style.marginTop = -(sub_h - 50)+'px';// -10 - 40 for the above extra 40
pull_up = true;
}
}
else {
//when top of menu goes out of browser window's top or below fixed navbar
if( off.top - diff < $scroll ) {
diff = off.top - $scroll;
}
//when bottom of menu goes above bottom of parent LI
/** else */
if(sub_bottom - diff < off.top + $diff) {
diff -= $diff;
}
var at_least = menu_text ? 40 : 20;//it we are going to move up less than at_least, then ignore
if( diff > at_least ) {
sub.style.top = -(diff) + 'px';
if( menu_text ) {
menu_text.style.marginTop = -(diff) + 'px';
pull_up = true;
}
}
}
}
//pull_up means, pull the menu up a little bit, and some styling may need to change
var pos = this.className.lastIndexOf('pull_up');//pull_up
if (pull_up) {
if (pos == -1)
this.className = this.className + ' pull_up';
} else {
if (pos >= 0)
this.className = this.className.replace(/(^|\s)pull_up($|\s)/ , '');
}
//again force redraw for safari!
if( ace.vars['safari'] ) {
ace.helper.redraw(sub)
}
}
}

View File

@@ -0,0 +1,117 @@
/**
<b>Custom drag event for touch devices</b> used in scrollbars.
For better touch event handling and extra options a more advanced solution such as <u>Hammer.js</u> is recommended.
*/
//based on but not dependent on jQuery mobile
/*
* jQuery Mobile v1.3.2
* http://jquerymobile.com
*
* Copyright 2010, 2013 jQuery Foundation, Inc. and other contributors
* Released under the MIT license.
* http://jquery.org/license
*
*/
ace.add_touch_drag = function($) {
if(!ace.vars['touch']) return;
var touchStartEvent = "touchstart MSPointerDown pointerdown",// : "mousedown",
touchStopEvent = "touchend touchcancel MSPointerUp MSPointerCancel pointerup pointercancel",// : "mouseup",
touchMoveEvent = "touchmove MSPointerMove MSPointerHover pointermove";// : "mousemove";
$.event.special.ace_drag = {
setup: function() {
var min_threshold = 0;
var $this = $(this);
$this.on(touchStartEvent, function(event) {
var data = event.originalEvent.touches ?
event.originalEvent.touches[ 0 ] :
event,
start = {
//time: Date.now(),
coords: [ data.pageX, data.pageY ],
origin: $(event.target)
},
stop;
start.origin.trigger({'type' : 'ace_dragStart', 'start':(start || [-1,-1])});
var direction = false, dx = 0, dy = 0;
function moveHandler(event) {
if (!start) {
return;
}
var data = event.originalEvent.touches ?
event.originalEvent.touches[ 0 ] :
event;
stop = {
coords: [ data.pageX, data.pageY ]
};
// prevent scrolling
//if ( Math.abs(start.coords[1] - stop.coords[1]) > 0 || Math.abs(start.coords[0] - stop.coords[01]) > 0 ) {
//event.preventDefault();
//}
if (start && stop) {
dx = 0; dy = 0;
direction =
(
Math.abs(dy = start.coords[ 1 ] - stop.coords[ 1 ]) > min_threshold
&&
Math.abs(dx = start.coords[ 0 ] - stop.coords[ 0 ]) <= Math.abs(dy)
)
?
(dy > 0 ? 'up' : 'down')
:
(
Math.abs(dx = start.coords[ 0 ] - stop.coords[ 0 ]) > min_threshold
&&
Math.abs( dy ) <= Math.abs(dx)
)
?
(dx > 0 ? 'left' : 'right')
:
false;
if( direction !== false ) {
var retval = {}
start.origin.trigger({
'type': 'ace_drag',
//'start': start.coords,
//'stop': stop.coords,
'direction': direction,
'dx': dx,
'dy': dy,
'retval': retval
})
// prevent scrolling?
//if(retval.cancel === true || event.cancel === undefined) {
event.preventDefault();
//}
}
}
start.coords[0] = stop.coords[0];
start.coords[1] = stop.coords[1];
}
$this
.on(touchMoveEvent, moveHandler)
.one(touchStopEvent, function(event) {
$this.off(touchMoveEvent, moveHandler);
start.origin.trigger({'type' : 'ace_dragEnd', 'stop':(stop || [-1,-1])});
start = stop = undefined;
});
});
}
}
}

View File

@@ -0,0 +1,220 @@
/**
<b>Widget boxes</b>
*/
ace.widget_boxes = function($) {
//bootstrap collapse component icon toggle
$(document).on('hide.bs.collapse show.bs.collapse', function (ev) {
var hidden_id = ev.target.getAttribute('id')
$('[href*="#'+ hidden_id+'"]').find(ace.vars['.icon']).each(function(){
var $icon = $(this)
var $match
var $icon_down = null
var $icon_up = null
if( ($icon_down = $icon.attr('data-icon-show')) ) {
$icon_up = $icon.attr('data-icon-hide')
}
else if( $match = $icon.attr('class').match(/fa\-(.*)\-(up|down)/) ) {
$icon_down = 'fa-'+$match[1]+'-down'
$icon_up = 'fa-'+$match[1]+'-up'
}
if($icon_down) {
if(ev.type == 'show') $icon.removeClass($icon_down).addClass($icon_up)
else $icon.removeClass($icon_up).addClass($icon_down)
return false;//ignore other icons that match, one is enough
}
});
})
var Widget_Box = function(box, options) {
this.$box = $(box);
var that = this;
//this.options = $.extend({}, $.fn.widget_box.defaults, options);
this.reload = function() {
var $box = this.$box;
var $remove_position = false;
if($box.css('position') == 'static') {
$remove_position = true;
$box.addClass('position-relative');
}
$box.append('<div class="widget-box-overlay"><i class="'+ ace.vars['icon'] + 'loading-icon fa fa-spinner fa-spin fa-2x white"></i></div>');
$box.one('reloaded.ace.widget', function() {
$box.find('.widget-box-overlay').remove();
if($remove_position) $box.removeClass('position-relative');
});
}
this.close = function() {
var $box = this.$box;
var closeSpeed = 300;
$box.fadeOut(closeSpeed , function(){
$box.trigger('closed.ace.widget');
$box.remove();
}
)
}
this.toggle = function(type, button) {
var $box = this.$box;
var $body = $box.find('.widget-body');
var $icon = null;
var event_name = typeof type !== 'undefined' ? type : ($box.hasClass('collapsed') ? 'show' : 'hide');
var event_complete_name = event_name == 'show' ? 'shown' : 'hidden';
if(typeof button === 'undefined') {
button = $box.find('> .widget-header a[data-action=collapse]').eq(0);
if(button.length == 0) button = null;
}
if(button) {
$icon = button.find(ace.vars['.icon']).eq(0);
var $match
var $icon_down = null
var $icon_up = null
if( ($icon_down = $icon.attr('data-icon-show')) ) {
$icon_up = $icon.attr('data-icon-hide')
}
else if( $match = $icon.attr('class').match(/fa\-(.*)\-(up|down)/) ) {
$icon_down = 'fa-'+$match[1]+'-down'
$icon_up = 'fa-'+$match[1]+'-up'
}
}
var $body_inner = $body.find('.widget-body-inner')
if($body_inner.length == 0) {
$body = $body.wrapInner('<div class="widget-body-inner"></div>').find(':first-child').eq(0);
} else $body = $body_inner.eq(0);
var expandSpeed = 300;
var collapseSpeed = 200;
if( event_name == 'show' ) {
if($icon) $icon.removeClass($icon_down).addClass($icon_up);
$box.removeClass('collapsed');
$body.slideUp(0 , function(){//do it once
$body.slideDown(expandSpeed, function(){
$box.trigger(event_complete_name+'.ace.widget')})
}
)
}
else {
if($icon) $icon.removeClass($icon_up).addClass($icon_down);
$body.slideUp(collapseSpeed, function(){
$box.addClass('collapsed')
$box.trigger(event_complete_name+'.ace.widget')
}
);
}
}
this.hide = function() {
this.toggle('hide');
}
this.show = function() {
this.toggle('show');
}
this.fullscreen = function() {
var $icon = this.$box.find('> .widget-header a[data-action=fullscreen]').find(ace.vars['.icon']).eq(0);
var $icon_expand = null
var $icon_compress = null
if( ($icon_expand = $icon.attr('data-icon1')) ) {
$icon_compress = $icon.attr('data-icon2')
}
else {
$icon_expand = 'fa-expand';
$icon_compress = 'fa-compress';
}
if(!this.$box.hasClass('fullscreen')) {
$icon.removeClass($icon_expand).addClass($icon_compress);
this.$box.addClass('fullscreen');
}
else {
$icon.addClass($icon_expand).removeClass($icon_compress);
this.$box.removeClass('fullscreen');
}
this.$box.trigger('fullscreened.ace.widget')
}
}
$.fn.widget_box = function (option, value) {
var method_call;
var $set = this.each(function () {
var $this = $(this);
var data = $this.data('widget_box');
var options = typeof option === 'object' && option;
if (!data) $this.data('widget_box', (data = new Widget_Box(this, options)));
if (typeof option === 'string') method_call = data[option](value);
});
return (method_call === undefined) ? $set : method_call;
};
$(document).on('click.ace.widget', '.widget-header a[data-action]', function (ev) {
ev.preventDefault();
var $this = $(this);
var $box = $this.closest('.widget-box');
if( $box.length == 0 || $box.hasClass('ui-sortable-helper') ) return;
var $widget_box = $box.data('widget_box');
if (!$widget_box) {
$box.data('widget_box', ($widget_box = new Widget_Box($box.get(0))));
}
var $action = $this.data('action');
if($action == 'collapse') {
var event_name = $box.hasClass('collapsed') ? 'show' : 'hide';
var event
$box.trigger(event = $.Event(event_name+'.ace.widget'))
if (event.isDefaultPrevented()) return
$widget_box.toggle(event_name, $this);
}
else if($action == 'close') {
var event
$box.trigger(event = $.Event('close.ace.widget'))
if (event.isDefaultPrevented()) return
$widget_box.close();
}
else if($action == 'reload') {
$this.blur();
var event
$box.trigger(event = $.Event('reload.ace.widget'))
if (event.isDefaultPrevented()) return
$widget_box.reload();
}
else if($action == 'fullscreen') {
var event
$box.trigger(event = $.Event('fullscreen.ace.widget'))
if (event.isDefaultPrevented()) return
$widget_box.fullscreen();
}
else if($action == 'settings') {
$box.trigger('setting.ace.widget')
}
});
}

View File

@@ -0,0 +1,27 @@
/**
The widget box reload button/event handler. You should use your own handler. An example is available at <i class="text-info">examples/widgets.html</i>.
<u><i class="glyphicon glyphicon-flash"></i> You don't need this. Used for demo only</u>
*/
ace.widget_reload_handler = function($) {
//***default action for reload in this demo
//you should remove this and add your own handler for each specific .widget-box
//when data is finished loading or processing is done you can call $box.trigger('reloaded.ace.widget')
$(document).on('reload.ace.widget', '.widget-box', function (ev) {
var $box = $(this);
//trigger the reloaded event to remove the spinner icon after 1-2 seconds
setTimeout(function() {
$box.trigger('reloaded.ace.widget');
}, parseInt(Math.random() * 1000 + 1000));
});
//you may want to do something like this:
/**
$('#my-widget-box').on('reload.ace.widget', function(){
//load new data here
//and when finished trigger "reloaded" event
$(this).trigger('reloaded.ace.widget');
});
*/
}

View File

@@ -0,0 +1,109 @@
/**
<b>Custom color picker element</b>. Converts html select elements to a dropdown color picker.
*/
(function($ , undefined) {
var Ace_Colorpicker = function(element, option) {
var options = $.extend({}, $.fn.ace_colorpicker.defaults, option);
var $element = $(element);
var color_list = '';
var color_selected = '';
var selection = null;
var color_array = [];
$element.addClass('hide').find('option').each(function() {
var $class = 'colorpick-btn';
var color = this.value.replace(/[^\w\s,#\(\)\.]/g, '');
if(this.value != color) this.value = color;
if(this.selected) {
$class += ' selected';
color_selected = color;
}
color_array.push(color)
color_list += '<li><a class="'+$class+'" href="#" style="background-color:'+color+';" data-color="'+color+'"></a></li>';
}).
end()
.on('change.color', function(){
$element.next().find('.btn-colorpicker').css('background-color', this.value);
})
.after('<div class="dropdown dropdown-colorpicker">\
<a data-toggle="dropdown" class="dropdown-toggle" '+(options.auto_pos ? 'data-position="auto"' : '')+' href="#"><span class="btn-colorpicker" style="background-color:'+color_selected+'"></span></a><ul class="dropdown-menu'+(options.caret? ' dropdown-caret' : '')+(options.pull_right ? ' dropdown-menu-right' : '')+'">'+color_list+'</ul></div>')
var dropdown = $element.next().find('.dropdown-menu')
dropdown.on(ace.click_event, function(e) {
var a = $(e.target);
if(!a.is('.colorpick-btn')) return false;
if(selection) selection.removeClass('selected');
selection = a;
selection.addClass('selected');
var color = selection.data('color');
$element.val(color).trigger('change');
e.preventDefault();
return true;//to hide dropdown
})
selection = $element.next().find('a.selected');
this.pick = function(index, insert) {
if(typeof index === 'number') {
if(index >= color_array.length) return;
element.selectedIndex = index;
dropdown.find('a:eq('+index+')').trigger(ace.click_event);
}
else if(typeof index === 'string') {
var color = index.replace(/[^\w\s,#\(\)\.]/g, '');
index = color_array.indexOf(color);
//add this color if it doesn't exist
if(index == -1 && insert === true) {
color_array.push(color);
$('<option />')
.appendTo($element)
.val(color);
$('<li><a class="colorpick-btn" href="#"></a></li>')
.appendTo(dropdown)
.find('a')
.css('background-color', color)
.data('color', color);
index = color_array.length - 1;
}
if(index == -1) return;
dropdown.find('a:eq('+index+')').trigger(ace.click_event);
}
}
this.destroy = function() {
$element.removeClass('hide').off('change.color')
.next().remove();
color_array = [];
}
}
$.fn.ace_colorpicker = function(option, value) {
var retval;
var $set = this.each(function () {
var $this = $(this);
var data = $this.data('ace_colorpicker');
var options = typeof option === 'object' && option;
if (!data) $this.data('ace_colorpicker', (data = new Ace_Colorpicker(this, options)));
if (typeof option === 'string') retval = data[option](value);
});
return (retval === undefined) ? $set : retval;
}
$.fn.ace_colorpicker.defaults = {
'pull_right' : false,
'caret': true,
'auto_pos': true
}
})(window.jQuery);

View File

@@ -0,0 +1,553 @@
/**
<b>Ace file input element</b>. Custom, simple file input element to style browser's default file input.
*/
(function($ , undefined) {
var multiplible = 'multiple' in document.createElement('INPUT');
var hasFileList = 'FileList' in window;//file list enabled in modern browsers
var hasFileReader = 'FileReader' in window;
var hasFile = 'File' in window;
var Ace_File_Input = function(element , settings) {
var self = this;
this.settings = $.extend({}, $.fn.ace_file_input.defaults, settings);
this.$element = $(element);
this.element = element;
this.disabled = false;
this.can_reset = true;
this.$element
.off('change.ace_inner_call')
.on('change.ace_inner_call', function(e , ace_inner_call){
if(ace_inner_call === true) return;//this change event is called from above drop event and extra checkings are taken care of there
return handle_on_change.call(self);
//if(ret === false) e.preventDefault();
});
var parent_label = this.$element.closest('label').css({'display':'block'})
var tagName = parent_label.length == 0 ? 'label' : 'span';//if not inside a "LABEL" tag, use "LABEL" tag, otherwise use "SPAN"
this.$element.wrap('<'+tagName+' class="ace-file-input" />');
this.apply_settings();
this.reset_input_field();//for firefox as it keeps selected file after refresh
}
Ace_File_Input.error = {
'FILE_LOAD_FAILED' : 1,
'IMAGE_LOAD_FAILED' : 2,
'THUMBNAIL_FAILED' : 3
};
Ace_File_Input.prototype.apply_settings = function() {
var self = this;
this.multi = this.$element.attr('multiple') && multiplible;
this.well_style = this.settings.style == 'well';
if(this.well_style) this.$element.parent().addClass('ace-file-multiple');
else this.$element.parent().removeClass('ace-file-multiple');
this.$element.parent().find(':not(input[type=file])').remove();//remove all except our input, good for when changing settings
this.$element.after('<span class="ace-file-container" data-title="'+this.settings.btn_choose+'"><span class="ace-file-name" data-title="'+this.settings.no_file+'">'+(this.settings.no_icon ? '<i class="'+ ace.vars['icon'] + this.settings.no_icon+'"></i>' : '')+'</span></span>');
this.$label = this.$element.next();
this.$container = this.$element.closest('.ace-file-input');
var remove_btn = !!this.settings.icon_remove;
if(remove_btn) {
var btn =
$('<a class="remove" href="#"><i class="'+ ace.vars['icon'] + this.settings.icon_remove+'"></i></a>')
.appendTo(this.$element.parent());
btn.on(ace.click_event, function(e){
e.preventDefault();
if( !self.can_reset ) return false;
var ret = true;
if(self.settings.before_remove) ret = self.settings.before_remove.call(self.element);
if(!ret) return false;
var r = self.reset_input();
return false;
});
}
if(this.settings.droppable && hasFileList) {
enable_drop_functionality.call(this);
}
}
Ace_File_Input.prototype.show_file_list = function($files) {
var files = typeof $files === "undefined" ? this.$element.data('ace_input_files') : $files;
if(!files || files.length == 0) return;
//////////////////////////////////////////////////////////////////
if(this.well_style) {
this.$label.find('.ace-file-name').remove();
if(!this.settings.btn_change) this.$label.addClass('hide-placeholder');
}
this.$label.attr('data-title', this.settings.btn_change).addClass('selected');
for (var i = 0; i < files.length; i++) {
var filename = typeof files[i] === "string" ? files[i] : $.trim( files[i].name );
var index = filename.lastIndexOf("\\") + 1;
if(index == 0)index = filename.lastIndexOf("/") + 1;
filename = filename.substr(index);
var fileIcon = 'fa fa-file';
var format = 'file';
if((/\.(jpe?g|png|gif|svg|bmp|tiff?)$/i).test(filename)) {
fileIcon = 'fa fa-picture-o file-image';
format = 'image';
}
else if((/\.(mpe?g|flv|mov|avi|swf|mp4|mkv|webm|wmv|3gp)$/i).test(filename)) {
fileIcon = 'fa fa-film file-video';
format = 'video';
}
else if((/\.(mp3|ogg|wav|wma|amr|aac)$/i).test(filename)) {
fileIcon = 'fa fa-music file-audio';
format = 'audio';
}
if(!this.well_style) this.$label.find('.ace-file-name').attr({'data-title':filename}).find(ace.vars['.icon']).attr('class', ace.vars['icon'] + fileIcon);
else {
this.$label.append('<span class="ace-file-name" data-title="'+filename+'"><i class="'+ ace.vars['icon'] + fileIcon+'"></i></span>');
var type = $.trim(files[i].type);
var can_preview = hasFileReader && this.settings.thumbnail
&&
( (type.length > 0 && type.match('image')) || (type.length == 0 && format == 'image') )//the second one is for Android's default browser which gives an empty text for file.type
if(can_preview) {
var self = this;
$.when(preview_image.call(this, files[i])).fail(function(result){
//called on failure to load preview
if(self.settings.preview_error) self.settings.preview_error.call(self, filename, result.code);
});
}
}
}
return true;
}
Ace_File_Input.prototype.reset_input = function() {
this.reset_input_ui();
this.reset_input_field();
}
Ace_File_Input.prototype.reset_input_ui = function() {
this.$label.attr({'data-title':this.settings.btn_choose, 'class':'ace-file-container'})
.find('.ace-file-name:first').attr({'data-title':this.settings.no_file , 'class':'ace-file-name'})
.find(ace.vars['.icon']).attr('class', ace.vars['icon'] + this.settings.no_icon)
.prev('img').remove();
if(!this.settings.no_icon) this.$label.find(ace.vars['.icon']).remove();
this.$label.find('.ace-file-name').not(':first').remove();
this.reset_input_data();
}
Ace_File_Input.prototype.reset_input_field = function() {
//http://stackoverflow.com/questions/1043957/clearing-input-type-file-using-jquery/13351234#13351234
this.$element.wrap('<form>').parent().get(0).reset();
this.$element.unwrap();
//strangely when reset is called on this temporary inner form
//only **IE9/10** trigger 'reset' on the outer form as well
//and as we have mentioned to reset input on outer form reset
//it causes infinite recusrsion by coming back to reset_input_field
//thus calling reset again and again and again
//so because when "reset" button of outer form is hit, file input is automatically reset
//we just reset_input_ui to avoid recursion
}
Ace_File_Input.prototype.reset_input_data = function() {
if(this.$element.data('ace_input_files')) {
this.$element.removeData('ace_input_files');
this.$element.removeData('ace_input_method');
}
}
Ace_File_Input.prototype.enable_reset = function(can_reset) {
this.can_reset = can_reset;
}
Ace_File_Input.prototype.disable = function() {
this.disabled = true;
this.$element.attr('disabled', 'disabled').addClass('disabled');
}
Ace_File_Input.prototype.enable = function() {
this.disabled = false;
this.$element.removeAttr('disabled').removeClass('disabled');
}
Ace_File_Input.prototype.files = function() {
return $(this).data('ace_input_files') || null;
}
Ace_File_Input.prototype.method = function() {
return $(this).data('ace_input_method') || '';
}
Ace_File_Input.prototype.update_settings = function(new_settings) {
this.settings = $.extend({}, this.settings, new_settings);
this.apply_settings();
}
Ace_File_Input.prototype.loading = function(is_loading) {
if(is_loading === false) {
this.$container.find('.ace-file-overlay').remove();
this.element.removeAttribute('readonly');
}
else {
var inside = typeof is_loading === 'string' ? is_loading : '<i class="overlay-content fa fa-spin fa-spinner orange2 fa-2x"></i>';
var loader = this.$container.find('.ace-file-overlay');
if(loader.length == 0) {
loader = $('<div class="ace-file-overlay"></div>').appendTo(this.$container);
loader.on('click tap', function(e) {
e.stopImmediatePropagation();
e.preventDefault();
return false;
});
this.element.setAttribute('readonly' , 'true');//for IE
}
loader.empty().append(inside);
}
}
var enable_drop_functionality = function() {
var self = this;
var dropbox = this.$element.parent();
dropbox
.off('dragenter')
.on('dragenter', function(e){
e.preventDefault();
e.stopPropagation();
})
.off('dragover')
.on('dragover', function(e){
e.preventDefault();
e.stopPropagation();
})
.off('drop')
.on('drop', function(e){
e.preventDefault();
e.stopPropagation();
var dt = e.originalEvent.dataTransfer;
var file_list = dt.files;
if(!self.multi && file_list.length > 1) {//single file upload, but dragged multiple files
var tmpfiles = [];
tmpfiles.push(file_list[0]);
file_list = tmpfiles;//keep only first file
}
file_list = processFiles.call(self, file_list, true);//true means files have been selected, not dropped
if(file_list === false) return false;
self.$element.data('ace_input_method', 'drop');
self.$element.data('ace_input_files', file_list);//save files data to be used later by user
self.show_file_list(file_list);
self.$element.triggerHandler('change' , [true]);//true means ace_inner_call
return true;
});
}
var handle_on_change = function() {
var file_list = this.element.files || [this.element.value];/** make it an array */
file_list = processFiles.call(this, file_list, false);//false means files have been selected, not dropped
if(file_list === false) return false;
this.$element.data('ace_input_method', 'select');
this.$element.data('ace_input_files', file_list);
this.show_file_list(file_list);
return true;
}
var preview_image = function(file) {
var self = this;
var $span = self.$label.find('.ace-file-name:last');//it should be out of onload, otherwise all onloads may target the same span because of delays
var deferred = new $.Deferred
var reader = new FileReader();
reader.onload = function (e) {
$span.prepend("<img class='middle' style='display:none;' />");
var img = $span.find('img:last').get(0);
$(img).one('load', function() {
//if image loaded successfully
var size = 50;
if(self.settings.thumbnail == 'large') size = 150;
else if(self.settings.thumbnail == 'fit') size = $span.width();
$span.addClass(size > 50 ? 'large' : '');
var thumb = get_thumbnail(img, size, file.type);
if(thumb == null) {
//if making thumbnail fails
$(this).remove();
deferred.reject({code:Ace_File_Input.error['THUMBNAIL_FAILED']});
return;
}
var w = thumb.w, h = thumb.h;
if(self.settings.thumbnail == 'small') {w=h=size;};
$(img).css({'background-image':'url('+thumb.src+')' , width:w, height:h})
.data('thumb', thumb.src)
.attr({src:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg=='})
.show()
///////////////////
deferred.resolve();
}).one('error', function() {
//for example when a file has image extenstion, but format is something else
$span.find('img').remove();
deferred.reject({code:Ace_File_Input.error['IMAGE_LOAD_FAILED']});
});
img.src = e.target.result;
}
reader.onerror = function (e) {
deferred.reject({code:Ace_File_Input.error['FILE_LOAD_FAILED']});
}
reader.readAsDataURL(file);
return deferred.promise();
}
var get_thumbnail = function(img, size, type) {
var w = img.width, h = img.height;
//**IE10** is not giving correct width using img.width so we use $(img).width()
w = w > 0 ? w : $(img).width()
h = h > 0 ? h : $(img).height()
if(w > size || h > size) {
if(w > h) {
h = parseInt(size/w * h);
w = size;
} else {
w = parseInt(size/h * w);
h = size;
}
}
var dataURL
try {
var canvas = document.createElement('canvas');
canvas.width = w; canvas.height = h;
var context = canvas.getContext('2d');
context.drawImage(img, 0, 0, img.width, img.height, 0, 0, w, h);
dataURL = canvas.toDataURL(/*type == 'image/jpeg' ? type : 'image/png', 10*/)
} catch(e) {
dataURL = null;
}
if(! dataURL) return null;
//there was only one image that failed in firefox completely randomly! so let's double check things
if( !( /^data\:image\/(png|jpe?g|gif);base64,[0-9A-Za-z\+\/\=]+$/.test(dataURL)) ) dataURL = null;
if(! dataURL) return null;
return {src: dataURL, w:w, h:h};
}
var processFiles = function(file_list, dropped) {
var ret = checkFileList.call(this, file_list, dropped);
if(ret === -1) {
this.reset_input();
return false;
}
if( !ret || ret.length == 0 ) {
if( !this.$element.data('ace_input_files') ) this.reset_input();
//if nothing selected before, reset because of the newly unacceptable (ret=false||length=0) selection
//otherwise leave the previous selection intact?!!!
return false;
}
if (ret instanceof Array || (hasFileList && ret instanceof FileList)) file_list = ret;
ret = true;
if(this.settings.before_change) ret = this.settings.before_change.call(this.element, file_list, dropped);
if(ret === -1) {
this.reset_input();
return false;
}
if(!ret || ret.length == 0) {
if( !this.$element.data('ace_input_files') ) this.reset_input();
return false;
}
//inside before_change you can return a modified File Array as result
if (ret instanceof Array || (hasFileList && ret instanceof FileList)) file_list = ret;
return file_list;
}
var getExtRegex = function(ext) {
if(!ext) return null;
if(typeof ext === 'string') ext = [ext];
if(ext.length == 0) return null;
return new RegExp("\.(?:"+ext.join('|')+")$", "i");
}
var getMimeRegex = function(mime) {
if(!mime) return null;
if(typeof mime === 'string') mime = [mime];
if(mime.length == 0) return null;
return new RegExp("^(?:"+mime.join('|').replace(/\//g, "\\/")+")$", "i");
}
var checkFileList = function(files, dropped) {
var allowExt = getExtRegex(this.settings.allowExt);
var denyExt = getExtRegex(this.settings.denyExt);
var allowMime = getMimeRegex(this.settings.allowMime);
var denyMime = getMimeRegex(this.settings.denyMime);
var maxSize = this.settings.maxSize || false;
if( !(allowExt || denyExt || allowMime || denyMime || maxSize) ) return true;//no checking required
var safe_files = [];
var error_list = {}
for(var f = 0; f < files.length; f++) {
var file = files[f];
//file is either a string(file name) or a File object
var filename = !hasFile ? file : file.name;
if( allowExt && !allowExt.test(filename) ) {
//extension not matching whitelist, so drop it
if(!('ext' in error_list)) error_list['ext'] = [];
error_list['ext'].push(filename);
continue;
} else if( denyExt && denyExt.test(filename) ) {
//extension is matching blacklist, so drop it
if(!('ext' in error_list)) error_list['ext'] = [];
error_list['ext'].push(filename);
continue;
}
var type;
if( !hasFile ) {
//in browsers that don't support FileReader API
safe_files.push(file);
continue;
}
else if((type = $.trim(file.type)).length > 0) {
//there is a mimetype for file so let's check against are rules
if( allowMime && !allowMime.test(type) ) {
//mimeType is not matching whitelist, so drop it
if(!('mime' in error_list)) error_list['mime'] = [];
error_list['mime'].push(filename);
continue;
}
else if( denyMime && denyMime.test(type) ) {
//mimeType is matching blacklist, so drop it
if(!('mime' in error_list)) error_list['mime'] = [];
error_list['mime'].push(filename);
continue;
}
}
if( maxSize && file.size > maxSize ) {
//file size is not acceptable
if(!('size' in error_list)) error_list['size'] = [];
error_list['size'].push(filename);
continue;
}
safe_files.push(file)
}
if(safe_files.length == files.length) return files;//return original file list if all are valid
/////////
var error_count = {'ext': 0, 'mime': 0, 'size': 0}
if( 'ext' in error_list ) error_count['ext'] = error_list['ext'].length;
if( 'mime' in error_list ) error_count['mime'] = error_list['mime'].length;
if( 'size' in error_list ) error_count['size'] = error_list['size'].length;
var event
this.$element.trigger(
event = new $.Event('file.error.ace'),
{
'file_count': files.length,
'invalid_count' : files.length - safe_files.length,
'error_list' : error_list,
'error_count' : error_count,
'dropped': dropped
}
);
if ( event.isDefaultPrevented() ) return -1;//it will reset input
//////////
return safe_files;//return safe_files
}
///////////////////////////////////////////
$.fn.ace_file_input = function (option,value) {
var retval;
var $set = this.each(function () {
var $this = $(this);
var data = $this.data('ace_file_input');
var options = typeof option === 'object' && option;
if (!data) $this.data('ace_file_input', (data = new Ace_File_Input(this, options)));
if (typeof option === 'string') retval = data[option](value);
});
return (retval === undefined) ? $set : retval;
};
$.fn.ace_file_input.defaults = {
style: false,
no_file: 'No File ...',
no_icon: 'fa fa-upload',
btn_choose: 'Choose',
btn_change: 'Change',
icon_remove: 'fa fa-times',
droppable: false,
thumbnail: false,//large, fit, small
allowExt: null,
denyExt: null,
allowMime: null,
denyMime: null,
maxSize: false,
//callbacks
before_change: null,
before_remove: null,
preview_error: null
}
})(window.jQuery);

View File

@@ -0,0 +1,441 @@
/**
<b>Ace custom scroller</b>. It is not as feature-rich as plugins such as NiceScroll but it's good enough for most cases.
*/
(function($ , undefined) {
var Ace_Scroll = function(element , _settings) {
var self = this;
var settings = $.extend({}, $.fn.ace_scroll.defaults, _settings);
this.size = 0;
this.$element = $(element);
this.element = element;
var vertical = true;
var disabled = false;
var active = false;
var created = false;
var $content_wrap = null, content_wrap = null;
var $track = null, $bar = null, track = null, bar = null;
var bar_style = null;
var bar_size = 0, bar_pos = 0, bar_max_pos = 0, bar_size_2 = 0, move_bar = true;
var reset_once = false;
var css_pos,
css_size,
max_css_size,
client_size,
scroll_direction,
scroll_size;
var ratio = 1;
var inline_style = false;
var mouse_track = false;
var mouse_release_target = 'onmouseup' in window ? window : 'html';
var dragEvent = settings.dragEvent || false;
var trigger_scroll = _settings.scrollEvent || false;
this.create = function(_settings) {
if(created) return;
//if(disabled) return;
if(_settings) settings = $.extend({}, $.fn.ace_scroll.defaults, _settings);
this.size = parseInt(this.$element.attr('data-size')) || settings.size || 200;
vertical = !settings['horizontal'];
css_pos = vertical ? 'top' : 'left';//'left' for horizontal
css_size = vertical ? 'height' : 'width';//'width' for horizontal
max_css_size = vertical ? 'maxHeight' : 'maxWidth';
client_size = vertical ? 'clientHeight' : 'clientWidth';
scroll_direction = vertical ? 'scrollTop' : 'scrollLeft';
scroll_size = vertical ? 'scrollHeight' : 'scrollWidth';
this.$element.addClass('ace-scroll '+((vertical? '' : ' scroll-hz') + (settings.styleClass ? ' '+settings.styleClass : '')));
if(this.$element.css('position') == 'static') {
inline_style = this.element.style.position;
this.element.style.position = 'relative';
} else inline_style = false;
this.$element.wrapInner('<div class="scroll-content" />');
this.$element.prepend('<div class="scroll-track"><div class="scroll-bar"></div></div>');
$content_wrap = this.$element.find('.scroll-content').eq(0);
if(!vertical) $content_wrap.wrapInner('<div />');
content_wrap = $content_wrap.get(0);
$track = this.$element.find('.scroll-track').eq(0);
$bar = $track.find('.scroll-bar').eq(0);
track = $track.get(0);
bar = $bar.get(0);
bar_style = bar.style;
$track.hide();
//if(!touchDrag) {
$track.on('mousedown', mouse_down_track);
$bar.on('mousedown', mouse_down_bar);
//}
$content_wrap.on('scroll', function() {
if(move_bar) {
bar_pos = parseInt(Math.round(this[scroll_direction] * ratio));
bar_style[css_pos] = bar_pos + 'px';
}
move_bar = false;
if(trigger_scroll) this.$element.trigger('scroll', [content_wrap]);
})
if(settings.mouseWheel) {
var lock = settings.mouseWheelLock;
var lock_anyway = !settings.lockAnyway;
this.$element.on('mousewheel.ace_scroll DOMMouseScroll.ace_scroll', function(event) {
if(disabled) return;
if(!active) return lock_anyway;
if(mouse_track) {
mouse_track = false;
$('html').off('.ace_scroll')
$(mouse_release_target).off('.ace_scroll');
if(dragEvent) self.$element.trigger('drag.end');
}
var delta = event.originalEvent.detail < 0 || event.originalEvent.wheelDelta > 0 ? 1 : -1
var scrollEnd = false//have we reached the end of scrolling?
var clientSize = content_wrap[client_size], scrollAmount = content_wrap[scroll_direction];
if( !lock ) {
if(delta == -1) scrollEnd = (content_wrap[scroll_size] <= scrollAmount + clientSize);
else scrollEnd = (scrollAmount == 0);
}
self.move_bar(true);
var step = parseInt(Math.round(Math.min(Math.max(clientSize / 8 , 54)) , self.size )) + 1;
content_wrap[scroll_direction] = scrollAmount - (delta * step);
return scrollEnd && lock_anyway;
})
}
//swipe not available yet
var touchDrag = ace.vars['touch'] && 'ace_drag' in $.event.special && settings.touchDrag //&& !settings.touchSwipe;
//add drag event for touch devices to scroll
if(touchDrag/** || ($.fn.swipe && settings.touchSwipe)*/) {
var dir = '', event_name = touchDrag ? 'ace_drag' : 'swipe';
this.$element.on(event_name + '.ace_scroll', function(event) {
dir = event.direction;
if( (vertical && (dir == 'up' || dir == 'down'))
||
(!vertical && (dir == 'left' || dir == 'right'))
)
{
var distance = vertical ? event.dy : event.dx;
if(distance != 0) {
if(Math.abs(distance) > 20 && touchDrag) distance = distance * 2;
self.move_bar(true);
content_wrap[scroll_direction] = content_wrap[scroll_direction] + distance;
}
//if(event.retval) event.retval['cancel'] = true;//prevents document scroll
}
//else if(event.retval) event.retval['cancel'] = false;//allows document scroll
})
}
if(settings.hoverReset) {
//some mobile browsers don't have mouseenter
this.$element.on('mouseenter.ace_scroll touchstart.ace_scroll', function() {
self.reset();
})
}
if(!vertical) $content_wrap.children(0).css(css_size, this.size);//the extra wrapper
$content_wrap.css(max_css_size , this.size);
disabled = false;
created = true;
}
this.is_active = function() {
return active;
}
this.is_enabled = function() {
return !disabled;
}
this.move_bar = function($move) {
move_bar = $move;
}
this.reset = function() {
if(disabled) return;// this;
if(!created) this.create();
var content_size = vertical ? content_wrap[scroll_size] : this.size;
if( (vertical && content_size == 0) || (!vertical && this.element.scrollWidth == 0) ) {
//elemen is hidden
//this.$element.addClass('scroll-hidden');
this.$element.removeClass('scroll-active')
return;// this;
}
var available_space = vertical ? this.size : content_wrap.clientWidth;
if(!vertical) $content_wrap.children(0).css(css_size, this.size);//the extra wrapper
$content_wrap.css(max_css_size , this.size);
if(content_size > available_space) {
active = true;
$track.css(css_size, available_space).show();
ratio = parseFloat((available_space / content_size).toFixed(5))
bar_size = parseInt(Math.round(available_space * ratio));
bar_size_2 = parseInt(Math.round(bar_size / 2));
bar_max_pos = available_space - bar_size;
bar_pos = parseInt(Math.round(content_wrap[scroll_direction] * ratio));
bar_style[css_size] = bar_size + 'px';
bar_style[css_pos] = bar_pos + 'px';
this.$element.addClass('scroll-active')
if(!reset_once) {
//this.$element.removeClass('scroll-hidden');
if(settings.reset) {
//reset scrollbar to zero position at first
content_wrap[scroll_direction] = 0;
bar_style[css_pos] = 0;
}
reset_once = true;
}
} else {
active = false;
$track.hide();
this.$element.removeClass('scroll-active');
$content_wrap.css(max_css_size , '');
}
return;// this;
}
this.disable = function() {
content_wrap[scroll_direction] = 0;
bar_style[css_pos] = 0;
disabled = true;
active = false;
$track.hide();
this.$element.removeClass('scroll-active');
$content_wrap.css(max_css_size , '');
return this;
}
this.enable = function() {
disabled = false;
this.reset();
return this;
}
this.destroy = function() {
active = false;
disabled = false;
created = false;
this.$element.removeClass('ace-scroll scroll-hz'+(settings.extraClass ? ' '+settings.extraClass : ''));
this.$element.off('.ace_scroll')
if(!vertical) {
//remove the extra wrapping div
$content_wrap.find('> div').children().unwrap();
}
$content_wrap.children().unwrap();
$content_wrap.remove();
$track.remove();
if(inline_style !== false) this.element.style.position = inline_style;
return this;
}
this.modify = function(_settings) {
if(_settings) settings = $.extend({}, $.fn.ace_scroll.defaults, _settings);
this.destroy();
this.create();
this.reset();
return this;
}
this.update = function(_settings) {
//if(_settings) settings = $.extend({}, $.fn.ace_scroll.defaults, _settings);
this.size = _settings.size;
return this;
}
this.update_scroll = function() {
move_bar = false;
bar_style[css_pos] = bar_pos + 'px';
content_wrap[scroll_direction] = parseInt(Math.round(bar_pos / ratio));
}
function mouse_down_track(e) {
e.preventDefault();
e.stopPropagation();
var track_offset = $track.offset();
var track_pos = track_offset[css_pos];//top for vertical, left for horizontal
var mouse_pos = vertical ? e.pageY : e.pageX;
if(mouse_pos > track_pos + bar_pos) {
bar_pos = mouse_pos - track_pos - bar_size + bar_size_2;
if(bar_pos > bar_max_pos) {
bar_pos = bar_max_pos;
}
}
else {
bar_pos = mouse_pos - track_pos - bar_size_2;
if(bar_pos < 0) bar_pos = 0;
}
self.update_scroll()
}
var mouse_pos1 = -1, mouse_pos2 = -1;
function mouse_down_bar(e) {
e.preventDefault();
e.stopPropagation();
if(vertical) {
mouse_pos2 = mouse_pos1 = e.pageY;
} else {
mouse_pos2 = mouse_pos1 = e.pageX;
}
mouse_track = true;
$('html').off('mousemove.ace_scroll').on('mousemove.ace_scroll', mouse_move_bar)
$(mouse_release_target).off('mouseup.ace_scroll').on('mouseup.ace_scroll', mouse_up_bar);
$track.addClass('active');
if(dragEvent) self.$element.trigger('drag.start');
}
function mouse_move_bar(e) {
e.preventDefault();
e.stopPropagation();
if(vertical) {
mouse_pos2 = e.pageY;
} else {
mouse_pos2 = e.pageX;
}
if(mouse_pos2 - mouse_pos1 + bar_pos > bar_max_pos) {
mouse_pos2 = mouse_pos1 + bar_max_pos - bar_pos;
} else if(mouse_pos2 - mouse_pos1 + bar_pos < 0) {
mouse_pos2 = mouse_pos1 - bar_pos;
}
bar_pos = bar_pos + (mouse_pos2 - mouse_pos1);
mouse_pos1 = mouse_pos2;
if(bar_pos < 0) {
bar_pos = 0;
}
else if(bar_pos > bar_max_pos) {
bar_pos = bar_max_pos;
}
self.update_scroll()
}
function mouse_up_bar(e) {
e.preventDefault();
e.stopPropagation();
mouse_track = false;
$('html').off('.ace_scroll')
$(mouse_release_target).off('.ace_scroll');
$track.removeClass('active');
if(dragEvent) self.$element.trigger('drag.end');
}
this.create();
this.reset();
return this;
}
$.fn.ace_scroll = function (option,value) {
var retval;
var $set = this.each(function () {
var $this = $(this);
var data = $this.data('ace_scroll');
var options = typeof option === 'object' && option;
if (!data) $this.data('ace_scroll', (data = new Ace_Scroll(this, options)));
//else if(typeof options == 'object') data['modify'](options);
if (typeof option === 'string') retval = data[option](value);
});
return (retval === undefined) ? $set : retval;
};
$.fn.ace_scroll.defaults = {
'size' : 200,
'horizontal': false,
'mouseWheel': true,
'mouseWheelLock': false,
'lockAnyway': false,
'styleClass' : false,
'hoverReset': true //reset scrollbar sizes on mouse hover because of possible sizing changes
,
'reset': false //true= set scrollTop = 0
,
'dragEvent': false
,
'touchDrag': true
,
'touchSwipe': false
,
'scrollEvent': false //trigger scroll event
/**
,
'track' : true,
'show' : false,
'dark': false,
'alwaysVisible': false,
'margin': false,
'thin': false,
'position': 'right'
*/
}
/**
$(document).on('ace.settings.ace_scroll', function(e, name) {
if(name == 'sidebar_collapsed') $('.ace-scroll').scroller('reset');
});
$(window).on('resize.ace_scroll', function() {
$('.ace-scroll').scroller('reset');
});
*/
})(window.jQuery);

View File

@@ -0,0 +1,104 @@
/**
<b>Spinner</b>. A wrapper for FuelUX spinner element.
It's just a wrapper so you still need to include FuelUX spinner script first.
*/
(function($ , undefined) {
//a wrapper for fuelux spinner
function Ace_Spinner(element , options) {
var max = options.max
max = (''+max).length
var width = parseInt(Math.max((max * 20 + 40) , 90))
var $element = $(element);
$element.addClass('spinner-input form-control').wrap('<div class="ace-spinner">')
var $parent_div = $element.closest('.ace-spinner').spinner(options).wrapInner("<div class='input-group'></div>")
var $spinner = $parent_div.data('spinner');
if(options.on_sides)
{
$element
.before('<div class="spinner-buttons input-group-btn">\
<button type="button" class="btn spinner-down btn-xs '+options.btn_down_class+'">\
<i class="'+ ace.vars['icon'] + options.icon_down+'"></i>\
</button>\
</div>')
.after('<div class="spinner-buttons input-group-btn">\
<button type="button" class="btn spinner-up btn-xs '+options.btn_up_class+'">\
<i class="'+ ace.vars['icon'] + options.icon_up+'"></i>\
</button>\
</div>');
$parent_div.addClass('touch-spinner')
$parent_div.css('width' , width+'px')
}
else {
$element
.after('<div class="spinner-buttons input-group-btn">\
<button type="button" class="btn spinner-up btn-xs '+options.btn_up_class+'">\
<i class="'+ ace.vars['icon'] + options.icon_up+'"></i>\
</button>\
<button type="button" class="btn spinner-down btn-xs '+options.btn_down_class+'">\
<i class="'+ ace.vars['icon'] + options.icon_down+'"></i>\
</button>\
</div>')
if(ace.vars['touch'] || options.touch_spinner) {
$parent_div.addClass('touch-spinner')
$parent_div.css('width' , width+'px')
}
else {
$element.next().addClass('btn-group-vertical');
$parent_div.css('width' , width+'px')
}
}
$element.on('mousewheel.spinner DOMMouseScroll.spinner', function(event){
var delta = event.originalEvent.detail < 0 || event.originalEvent.wheelDelta > 0 ? 1 : -1
$spinner.step(delta > 0);
$spinner.triggerChangedEvent();
return false
})
$parent_div.on('changed', function(){
$element.trigger('change')//trigger the input's change event
});
this._call = function(name, arg) {
$spinner[name](arg);
}
}
$.fn.ace_spinner = function(option, value) {
var retval;
var $set = this.each(function() {
var $this = $(this);
var data = $this.data('ace_spinner');
var options = typeof option === 'object' && option;
if (!data) {
options = $.extend({}, $.fn.ace_spinner.defaults, option);
$this.data('ace_spinner', (data = new Ace_Spinner(this, options)));
}
if (typeof option === 'string') retval = data._call(option, value);
});
return (retval === undefined) ? $set : retval;
}
$.fn.ace_spinner.defaults = {
'icon_up' : 'fa fa-chevron-up',
'icon_down': 'fa fa-chevron-down',
'on_sides': false,
'btn_up_class': '',
'btn_down_class' : '',
'max' : 999,
'touch_spinner': false
}
})(window.jQuery);

View File

@@ -0,0 +1,38 @@
/**
<b>Treeview</b>. A wrapper for FuelUX treeview element.
It's just a wrapper so you still need to include FuelUX treeview script first.
*/
(function($ , undefined) {
var $options = {
'open-icon' : ace.vars['icon'] + 'fa fa-folder-open',
'close-icon' : ace.vars['icon'] + 'fa fa-folder',
'selectable' : true,
'selected-icon' : ace.vars['icon'] + 'fa fa-check',
'unselected-icon' : ace.vars['icon'] + 'fa fa-times'
}
$.fn.ace_tree = function(options) {
$options = $.extend({}, $options, options)
this.each(function() {
var $this = $(this);
$this.html('<div class="tree-folder" style="display:none;">\
<div class="tree-folder-header">\
<i class="'+ ace.vars['icon'] + $options['close-icon']+'"></i>\
<div class="tree-folder-name"></div>\
</div>\
<div class="tree-folder-content"></div>\
<div class="tree-loader" style="display:none"></div>\
</div>\
<div class="tree-item" style="display:none;">\
'+($options['unselected-icon'] == null ? '' : '<i class="'+ ace.vars['icon'] + $options['unselected-icon']+'"></i>')+'\
<div class="tree-item-name"></div>\
</div>');
$this.addClass($options['selectable'] == true ? 'tree-selectable' : 'tree-unselectable');
$this.tree($options);
});
return this;
}
})(window.jQuery);

View File

@@ -0,0 +1,340 @@
/**
<b>Bootstrap 2 typeahead plugin.</b> With Bootstrap <u>3</u> it's been dropped in favor of a more advanced separate plugin.
Pretty good for simple cases such as autocomplete feature of the search box and required for <u class="text-danger">Tag input</u> plugin.
*/
/* =============================================================
* bootstrap-typeahead.js v2.3.2
* http://twitter.github.com/bootstrap/javascript.html#typeahead
* =============================================================
* 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 ;_;
/* TYPEAHEAD PUBLIC CLASS DEFINITION
* ================================= */
var Typeahead = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, $.fn.typeahead.defaults, options)
this.matcher = this.options.matcher || this.matcher
this.sorter = this.options.sorter || this.sorter
this.highlighter = this.options.highlighter || this.highlighter
this.updater = this.options.updater || this.updater
this.source = this.options.source
this.$menu = $(this.options.menu)
this.shown = false
this.listen()
}
Typeahead.prototype = {
constructor: Typeahead
, select: function () {
var val = this.$menu.find('.active').attr('data-value')
this.$element
.val(this.updater(val))
.change()
return this.hide()
}
, updater: function (item) {
return item
}
, show: function () {
var pos = $.extend({}, this.$element.position(), {
height: this.$element[0].offsetHeight
})
this.$menu
.insertAfter(this.$element)
.css({
top: pos.top + pos.height
, left: pos.left
})
.show()
this.shown = true
return this
}
, hide: function () {
this.$menu.hide()
this.shown = false
return this
}
, lookup: function (event) {
var items
this.query = this.$element.val()
if (!this.query || this.query.length < this.options.minLength) {
return this.shown ? this.hide() : this
}
items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source
return items ? this.process(items) : this
}
, process: function (items) {
var that = this
items = $.grep(items, function (item) {
return that.matcher(item)
})
items = this.sorter(items)
if (!items.length) {
return this.shown ? this.hide() : this
}
return this.render(items.slice(0, this.options.items)).show()
}
, matcher: function (item) {
return ~item.toLowerCase().indexOf(this.query.toLowerCase())
}
, sorter: function (items) {
var beginswith = []
, caseSensitive = []
, caseInsensitive = []
, item
while (item = items.shift()) {
if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
else if (~item.indexOf(this.query)) caseSensitive.push(item)
else caseInsensitive.push(item)
}
return beginswith.concat(caseSensitive, caseInsensitive)
}
, highlighter: function (item) {
var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
return '<strong>' + match + '</strong>'
})
}
, render: function (items) {
var that = this
items = $(items).map(function (i, item) {
i = $(that.options.item).attr('data-value', item)
i.find('a').html(that.highlighter(item))
return i[0]
})
items.first().addClass('active')
this.$menu.html(items)
return this
}
, next: function (event) {
var active = this.$menu.find('.active').removeClass('active')
, next = active.next()
if (!next.length) {
next = $(this.$menu.find('li')[0])
}
next.addClass('active')
}
, prev: function (event) {
var active = this.$menu.find('.active').removeClass('active')
, prev = active.prev()
if (!prev.length) {
prev = this.$menu.find('li').last()
}
prev.addClass('active')
}
, listen: function () {
this.$element
.on('focus', $.proxy(this.focus, this))
.on('blur', $.proxy(this.blur, this))
.on('keypress', $.proxy(this.keypress, this))
.on('keyup', $.proxy(this.keyup, this))
if (this.eventSupported('keydown')) {
this.$element.on('keydown', $.proxy(this.keydown, this))
}
this.$menu
.on('click', $.proxy(this.click, this))
.on('mouseenter', 'li', $.proxy(this.mouseenter, this))
.on('mouseleave', 'li', $.proxy(this.mouseleave, this))
}
, eventSupported: function(eventName) {
var isSupported = eventName in this.$element
if (!isSupported) {
this.$element.setAttribute(eventName, 'return;')
isSupported = typeof this.$element[eventName] === 'function'
}
return isSupported
}
, move: function (e) {
if (!this.shown) return
switch(e.keyCode) {
case 9: // tab
case 13: // enter
case 27: // escape
e.preventDefault()
break
case 38: // up arrow
e.preventDefault()
this.prev()
break
case 40: // down arrow
e.preventDefault()
this.next()
break
}
e.stopPropagation()
}
, keydown: function (e) {
this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27])
this.move(e)
}
, keypress: function (e) {
if (this.suppressKeyPressRepeat) return
this.move(e)
}
, keyup: function (e) {
switch(e.keyCode) {
case 40: // down arrow
case 38: // up arrow
case 16: // shift
case 17: // ctrl
case 18: // alt
break
case 9: // tab
case 13: // enter
if (!this.shown) return
this.select()
break
case 27: // escape
if (!this.shown) return
this.hide()
break
default:
this.lookup()
}
e.stopPropagation()
e.preventDefault()
}
, focus: function (e) {
this.focused = true
}
, blur: function (e) {
this.focused = false
if (!this.mousedover && this.shown) this.hide()
}
, click: function (e) {
e.stopPropagation()
e.preventDefault()
this.select()
this.$element.focus()
}
, mouseenter: function (e) {
this.mousedover = true
this.$menu.find('.active').removeClass('active')
$(e.currentTarget).addClass('active')
}
, mouseleave: function (e) {
this.mousedover = false
if (!this.focused && this.shown) this.hide()
}
}
/* TYPEAHEAD PLUGIN DEFINITION
* =========================== */
var old = $.fn.typeahead
$.fn.typeahead = function (option) {
return this.each(function () {
var $this = $(this)
, data = $this.data('typeahead')
, options = typeof option == 'object' && option
if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))
if (typeof option == 'string') data[option]()
})
}
$.fn.typeahead.defaults = {
source: []
, items: 8
, menu: '<ul class="typeahead dropdown-menu"></ul>'
, item: '<li><a href="#"></a></li>'
, minLength: 1
}
$.fn.typeahead.Constructor = Typeahead
/* TYPEAHEAD NO CONFLICT
* =================== */
$.fn.typeahead.noConflict = function () {
$.fn.typeahead = old
return this
}
/* TYPEAHEAD DATA-API
* ================== */
$(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
var $this = $(this)
if ($this.data('typeahead')) return
$this.typeahead($this.data())
})
}(window.jQuery);

View File

@@ -0,0 +1,35 @@
/**
<b>Wizard</b>. A wrapper for FuelUX wizard element.
It's just a wrapper so you still need to include FuelUX wizard script first.
*/
(function($ , undefined) {
$.fn.ace_wizard = function(options) {
this.each(function() {
var $this = $(this);
$this.wizard();
var buttons = $this.siblings('.wizard-actions').eq(0);
var $wizard = $this.data('wizard');
$wizard.$prevBtn.remove();
$wizard.$nextBtn.remove();
$wizard.$prevBtn = buttons.find('.btn-prev').eq(0).on(ace.click_event, function(){
$wizard.previous();
}).attr('disabled', 'disabled');
$wizard.$nextBtn = buttons.find('.btn-next').eq(0).on(ace.click_event, function(){
$wizard.next();
}).removeAttr('disabled');
$wizard.nextText = $wizard.$nextBtn.text();
var step = options && ((options.selectedItem && options.selectedItem.step) || options.step);
if(step) {
$wizard.currentStep = step;
$wizard.setState();
}
});
return this;
}
})(window.jQuery);

View File

@@ -0,0 +1,321 @@
/**
<b>Wysiwyg</b>. A wrapper for Bootstrap wyswiwyg plugin.
It's just a wrapper so you still need to include Bootstrap wysiwyg script first.
*/
(function($ , undefined) {
$.fn.ace_wysiwyg = function($options , undefined) {
var options = $.extend( {
speech_button:true,
wysiwyg:{}
}, $options);
var color_values = [
'#ac725e','#d06b64','#f83a22','#fa573c','#ff7537','#ffad46',
'#42d692','#16a765','#7bd148','#b3dc6c','#fbe983','#fad165',
'#92e1c0','#9fe1e7','#9fc6e7','#4986e7','#9a9cff','#b99aff',
'#c2c2c2','#cabdbf','#cca6ac','#f691b2','#cd74e6','#a47ae2',
'#444444'
]
var button_defaults =
{
'font' : {
values:['Arial', 'Courier', 'Comic Sans MS', 'Helvetica', 'Open Sans', 'Tahoma', 'Verdana'],
icon:'fa fa-font',
title:'Font'
},
'fontSize' : {
values:{5:'Huge', 3:'Normal', 1:'Small'},
icon:'fa fa-text-height',
title:'Font Size'
},
'bold' : {
icon : 'fa fa-bold',
title : 'Bold (Ctrl/Cmd+B)'
},
'italic' : {
icon : 'fa fa-italic',
title : 'Italic (Ctrl/Cmd+I)'
},
'strikethrough' : {
icon : 'fa fa-strikethrough',
title : 'Strikethrough'
},
'underline' : {
icon : 'fa fa-underline',
title : 'Underline'
},
'insertunorderedlist' : {
icon : 'fa fa-list-ul',
title : 'Bullet list'
},
'insertorderedlist' : {
icon : 'fa fa-list-ol',
title : 'Number list'
},
'outdent' : {
icon : 'fa fa-outdent',
title : 'Reduce indent (Shift+Tab)'
},
'indent' : {
icon : 'fa fa-indent',
title : 'Indent (Tab)'
},
'justifyleft' : {
icon : 'fa fa-align-left',
title : 'Align Left (Ctrl/Cmd+L)'
},
'justifycenter' : {
icon : 'fa fa-align-center',
title : 'Center (Ctrl/Cmd+E)'
},
'justifyright' : {
icon : 'fa fa-align-right',
title : 'Align Right (Ctrl/Cmd+R)'
},
'justifyfull' : {
icon : 'fa fa-align-justify',
title : 'Justify (Ctrl/Cmd+J)'
},
'createLink' : {
icon : 'fa fa-link',
title : 'Hyperlink',
button_text : 'Add',
placeholder : 'URL',
button_class : 'btn-primary'
},
'unlink' : {
icon : 'fa fa-chain-broken',
title : 'Remove Hyperlink'
},
'insertImage' : {
icon : 'fa fa-picture-o',
title : 'Insert picture',
button_text : '<i class="'+ ace.vars['icon'] + 'fa fa-file"></i> Choose Image &hellip;',
placeholder : 'Image URL',
button_insert : 'Insert',
button_class : 'btn-success',
button_insert_class : 'btn-primary',
choose_file: true //show the choose file button?
},
'foreColor' : {
values : color_values,
title : 'Change Color'
},
'backColor' : {
values : color_values,
title : 'Change Background Color'
},
'undo' : {
icon : 'fa fa-undo',
title : 'Undo (Ctrl/Cmd+Z)'
},
'redo' : {
icon : 'fa fa-repeat',
title : 'Redo (Ctrl/Cmd+Y)'
},
'viewSource' : {
icon : 'fa fa-code',
title : 'View Source'
}
}
var toolbar_buttons =
options.toolbar ||
[
'font',
null,
'fontSize',
null,
'bold',
'italic',
'strikethrough',
'underline',
null,
'insertunorderedlist',
'insertorderedlist',
'outdent',
'indent',
null,
'justifyleft',
'justifycenter',
'justifyright',
'justifyfull',
null,
'createLink',
'unlink',
null,
'insertImage',
null,
'foreColor',
null,
'undo',
'redo',
null,
'viewSource'
]
this.each(function() {
var toolbar = ' <div class="wysiwyg-toolbar btn-toolbar center"> <div class="btn-group"> ';
for(var tb in toolbar_buttons) if(toolbar_buttons.hasOwnProperty(tb)) {
var button = toolbar_buttons[tb];
if(button === null){
toolbar += ' </div> <div class="btn-group"> ';
continue;
}
if(typeof button == "string" && button in button_defaults) {
button = button_defaults[button];
button.name = toolbar_buttons[tb];
} else if(typeof button == "object" && button.name in button_defaults) {
button = $.extend(button_defaults[button.name] , button);
}
else continue;
var className = "className" in button ? button.className : 'btn-default';
switch(button.name) {
case 'font':
toolbar += ' <a class="btn btn-sm '+className+' dropdown-toggle" data-toggle="dropdown" title="'+button.title+'"><i class="'+ ace.vars['icon'] + button.icon+'"></i><i class="' + ace.vars['icon'] + 'fa fa-angle-down icon-on-right"></i></a> ';
toolbar += ' <ul class="dropdown-menu dropdown-light dropdown-caret">';
for(var font in button.values)
if(button.values.hasOwnProperty(font))
toolbar += ' <li><a data-edit="fontName ' + button.values[font] +'" style="font-family:\''+ button.values[font] +'\'">'+button.values[font] + '</a></li> '
toolbar += ' </ul>';
break;
case 'fontSize':
toolbar += ' <a class="btn btn-sm '+className+' dropdown-toggle" data-toggle="dropdown" title="'+button.title+'"><i class="'+ ace.vars['icon'] + button.icon+'"></i>&nbsp;<i class="'+ ace.vars['icon'] + 'fa fa-angle-down icon-on-right"></i></a> ';
toolbar += ' <ul class="dropdown-menu dropdown-light dropdown-caret"> ';
for(var size in button.values)
if(button.values.hasOwnProperty(size))
toolbar += ' <li><a data-edit="fontSize '+size+'"><font size="'+size+'">'+ button.values[size] +'</font></a></li> '
toolbar += ' </ul> ';
break;
case 'createLink':
toolbar += ' <div class="btn-group"> <a class="btn btn-sm '+className+' dropdown-toggle" data-toggle="dropdown" title="'+button.title+'"><i class="'+ ace.vars['icon'] + button.icon+'"></i></a> ';
toolbar += ' <div class="dropdown-menu dropdown-caret dropdown-menu-right">\
<div class="input-group">\
<input class="form-control" placeholder="'+button.placeholder+'" type="text" data-edit="'+button.name+'" />\
<span class="input-group-btn">\
<button class="btn btn-sm '+button.button_class+'" type="button">'+button.button_text+'</button>\
</span>\
</div>\
</div> </div>';
break;
case 'insertImage':
toolbar += ' <div class="btn-group"> <a class="btn btn-sm '+className+' dropdown-toggle" data-toggle="dropdown" title="'+button.title+'"><i class="'+ ace.vars['icon'] + button.icon+'"></i></a> ';
toolbar += ' <div class="dropdown-menu dropdown-caret dropdown-menu-right">\
<div class="input-group">\
<input class="form-control" placeholder="'+button.placeholder+'" type="text" data-edit="'+button.name+'" />\
<span class="input-group-btn">\
<button class="btn btn-sm '+button.button_insert_class+'" type="button">'+button.button_insert+'</button>\
</span>\
</div>';
if( button.choose_file && 'FileReader' in window ) toolbar +=
'<div class="space-2"></div>\
<label class="center block no-margin-bottom">\
<button class="btn btn-sm '+button.button_class+' wysiwyg-choose-file" type="button">'+button.button_text+'</button>\
<input type="file" data-edit="'+button.name+'" />\
</label>'
toolbar += ' </div> </div>';
break;
case 'foreColor':
case 'backColor':
toolbar += ' <select class="hide wysiwyg_colorpicker" title="'+button.title+'"> ';
for(var color in button.values)
toolbar += ' <option value="'+button.values[color]+'">'+button.values[color]+'</option> ';
toolbar += ' </select> ';
toolbar += ' <input style="display:none;" disabled class="hide" type="text" data-edit="'+button.name+'" /> ';
break;
case 'viewSource':
toolbar += ' <a class="btn btn-sm '+className+'" data-view="source" title="'+button.title+'"><i class="'+ ace.vars['icon'] + button.icon+'"></i></a> ';
break;
default:
toolbar += ' <a class="btn btn-sm '+className+'" data-edit="'+button.name+'" title="'+button.title+'"><i class="'+ ace.vars['icon'] + button.icon+'"></i></a> ';
break;
}
}
toolbar += ' </div> ';
////////////
var speech_input;
if (options.speech_button && 'onwebkitspeechchange' in (speech_input = document.createElement('input'))) {
toolbar += ' <input class="wysiwyg-speech-input" type="text" data-edit="inserttext" x-webkit-speech />';
}
speech_input = null;
////////////
toolbar += ' </div> ';
//if we have a function to decide where to put the toolbar, then call that
if(options.toolbar_place) toolbar = options.toolbar_place.call(this, toolbar);
//otherwise put it just before our DIV
else toolbar = $(this).before(toolbar).prev();
toolbar.find('a[title]').tooltip({animation:false, container:'body'});
toolbar.find('.dropdown-menu input[type=text]').on('click', function() {return false})
.on('change', function() {$(this).closest('.dropdown-menu').siblings('.dropdown-toggle').dropdown('toggle')})
.on('keydown', function (e) {
if(e.which == 27) {
this.value = '';
$(this).change();
}
else if(e.which == 13) {
e.preventDefault();
e.stopPropagation();
$(this).change();
}
});
toolbar.find('input[type=file]').prev().on(ace.click_event, function (e) {
$(this).next().click();
});
toolbar.find('.wysiwyg_colorpicker').each(function() {
$(this).ace_colorpicker({pull_right:true}).change(function(){
$(this).nextAll('input').eq(0).val(this.value).change();
}).next().find('.btn-colorpicker').tooltip({title: this.title, animation:false, container:'body'})
});
var self = $(this);
//view source
var view_source = false;
toolbar.find('a[data-view=source]').on('click', function(e){
e.preventDefault();
if(!view_source) {
$('<textarea />')
.css({'width':self.outerWidth(), 'height':self.outerHeight()})
.val(self.html())
.insertAfter(self)
self.hide();
$(this).addClass('active');
}
else {
var textarea = self.next();
self.html(textarea.val()).show();
textarea.remove();
$(this).removeClass('active');
}
view_source = !view_source;
});
var $options = $.extend({}, { activeToolbarClass: 'active' , toolbarSelector : toolbar }, options.wysiwyg || {})
$(this).wysiwyg( $options );
});
return this;
}
})(window.jQuery);

View File

@@ -0,0 +1 @@
To build a custom JS file please open path/to/ace/build/js.html in your browser.

View File

@@ -0,0 +1,31 @@
{
"elements.scroller.js" : true,
"elements.colorpicker.js" : true,
"elements.fileinput.js" : true,
"elements.typeahead.js" : true,
"elements.wysiwyg.js" : true,
"elements.spinner.js" : true,
"elements.treeview.js" : true,
"elements.wizard.js" : true,
"ace.js" : true,
"ace.touch-drag.js" : true,
"ace.sidebar.js" : true,
"ace.submenu-1.js" : true,
"ace.sidebar-scroll-1.js" : true,
"ace.submenu-hover.js" : true,
"ace.widget-box.js" : true,
"ace.settings.js" : true,
"ace.settings-rtl.js" : true,
"ace.settings-skin.js" : true,
"ace.widget-on-reload.js" : true,
"ace.searchbox-autocomplete.js" : true,
"ace.autohide-sidebar.js" : false,
"ace.auto-padding.js" : false,
"ace.auto-container.js" : false
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,15 @@
/**
* Arabic translation for bootstrap-datepicker
* Mohammed Alshehri <alshehri866@gmail.com>
*/
;(function($){
$.fn.datepicker.dates['ar'] = {
days: ["الأحد", "الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد"],
daysShort: ["أحد", "اثنين", "ثلاثاء", "أربعاء", "خميس", "جمعة", "سبت", "أحد"],
daysMin: ["ح", "ن", "ث", "ع", "خ", "ج", "س", "ح"],
months: ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"],
monthsShort: ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"],
today: "هذا اليوم",
rtl: true
};
}(jQuery));

View File

@@ -0,0 +1,12 @@
// Azerbaijani
;(function($){
$.fn.datepicker.dates['az'] = {
days: ["Bazar", "Bazar ertəsi", "Çərşənbə axşamı", "Çərşənbə", "Cümə axşamı", "Cümə", "Şənbə", "Bazar"],
daysShort: ["B.", "B.e", "Ç.a", "Ç.", "C.a", "C.", "Ş.", "B."],
daysMin: ["B.", "B.e", "Ç.a", "Ç.", "C.a", "C.", "Ş.", "B."],
months: ["Yanvar", "Fevral", "Mart", "Aprel", "May", "İyun", "İyul", "Avqust", "Sentyabr", "Oktyabr", "Noyabr", "Dekabr"],
monthsShort: ["Yan", "Fev", "Mar", "Apr", "May", "İyun", "İyul", "Avq", "Sen", "Okt", "Noy", "Dek"],
today: "Bu gün",
weekStart: 1
};
}(jQuery));

View File

@@ -0,0 +1,14 @@
/**
* Welsh translation for bootstrap-datepicker
* S. Morris <s.morris@bangor.ac.uk>
*/
;(function($){
$.fn.datepicker.dates['cy'] = {
days: ["Sul", "Llun", "Mawrth", "Mercher", "Iau", "Gwener", "Sadwrn", "Sul"],
daysShort: ["Sul", "Llu", "Maw", "Mer", "Iau", "Gwe", "Sad", "Sul"],
daysMin: ["Su", "Ll", "Ma", "Me", "Ia", "Gwe", "Sa", "Su"],
months: ["Ionawr", "Chewfror", "Mawrth", "Ebrill", "Mai", "Mehefin", "Gorfennaf", "Awst", "Medi", "Hydref", "Tachwedd", "Rhagfyr"],
monthsShort: ["Ion", "Chw", "Maw", "Ebr", "Mai", "Meh", "Gor", "Aws", "Med", "Hyd", "Tach", "Rha"],
today: "Heddiw"
};
}(jQuery));

View File

@@ -0,0 +1,18 @@
/**
* Estonian translation for bootstrap-datepicker
* Ando Roots <https://github.com/anroots>
* Fixes by Illimar Tambek <<https://github.com/ragulka>
*/
;(function($){
$.fn.datepicker.dates['et'] = {
days: ["Pühapäev", "Esmaspäev", "Teisipäev", "Kolmapäev", "Neljapäev", "Reede", "Laupäev", "Pühapäev"],
daysShort: ["Pühap", "Esmasp", "Teisip", "Kolmap", "Neljap", "Reede", "Laup", "Pühap"],
daysMin: ["P", "E", "T", "K", "N", "R", "L", "P"],
months: ["Jaanuar", "Veebruar", "Märts", "Aprill", "Mai", "Juuni", "Juuli", "August", "September", "Oktoober", "November", "Detsember"],
monthsShort: ["Jaan", "Veebr", "Märts", "Apr", "Mai", "Juuni", "Juuli", "Aug", "Sept", "Okt", "Nov", "Dets"],
today: "Täna",
clear: "Tühjenda",
weekStart: 1,
format: "dd.mm.yyyy"
};
}(jQuery));

View File

@@ -0,0 +1,17 @@
/**
* Persian translation for bootstrap-datepicker
* Mostafa Rokooie <mostafa.rokooie@gmail.com>
*/
;(function($){
$.fn.datepicker.dates['fa'] = {
days: ["یک‌شنبه", "دوشنبه", "سه‌شنبه", "چهارشنبه", "پنج‌شنبه", "جمعه", "شنبه", "یک‌شنبه"],
daysShort: ["یک", "دو", "سه", "چهار", "پنج", "جمعه", "شنبه", "یک"],
daysMin: ["ی", "د", "س", "چ", "پ", "ج", "ش", "ی"],
months: ["ژانویه", "فوریه", "مارس", "آوریل", "مه", "ژوئن", "ژوئیه", "اوت", "سپتامبر", "اکتبر", "نوامبر", "دسامبر"],
monthsShort: ["ژان", "فور", "مار", "آور", "مه", "ژون", "ژوی", "اوت", "سپت", "اکت", "نوا", "دسا"],
today: "امروز",
clear: "پاک کن",
weekStart: 1,
format: "yyyy/mm/dd"
};
}(jQuery));

View File

@@ -0,0 +1,11 @@
;(function($){
$.fn.datepicker.dates['gl'] = {
days: ["Domingo", "Luns", "Martes", "Mércores", "Xoves", "Venres", "Sábado", "Domingo"],
daysShort: ["Dom", "Lun", "Mar", "Mér", "Xov", "Ven", "Sáb", "Dom"],
daysMin: ["Do", "Lu", "Ma", "Me", "Xo", "Ve", "Sa", "Do"],
months: ["Xaneiro", "Febreiro", "Marzo", "Abril", "Maio", "Xuño", "Xullo", "Agosto", "Setembro", "Outubro", "Novembro", "Decembro"],
monthsShort: ["Xan", "Feb", "Mar", "Abr", "Mai", "Xun", "Xul", "Ago", "Sep", "Out", "Nov", "Dec"],
today: "Hoxe",
clear: "Limpar"
};
}(jQuery));

View File

@@ -0,0 +1,17 @@
/**
* Georgian translation for bootstrap-datepicker
* Levan Melikishvili <levani0101@yahoo.com>
*/
;(function($){
$.fn.datepicker.dates['ka'] = {
days: ["კვირა", "ორშაბათი", "სამშაბათი", "ოთხშაბათი", "ხუთშაბათი", "პარასკევი", "შაბათი", "კვირა"],
daysShort: ["კვი", "ორშ", "სამ", "ოთხ", "ხუთ", "პარ", "შაბ", "კვი"],
daysMin: ["კვ", "ორ", "სა", "ოთ", "ხუ", "პა", "შა", "კვ"],
months: ["იანვარი", "თებერვალი", "მარტი", "აპრილი", "მაისი", "ივნისი", "ივლისი", "აგვისტო", "სექტემბერი", "ოქტომები", "ნოემბერი", "დეკემბერი"],
monthsShort: ["იან", "თებ", "მარ", "აპრ", "მაი", "ივნ", "ივლ", "აგვ", "სექ", "ოქტ", "ნოე", "დეკ"],
today: "დღეს",
clear: "გასუფთავება",
weekStart: 1,
format: "dd.mm.yyyy"
};
}(jQuery));

View File

@@ -0,0 +1,15 @@
/**
* Kazakh translation for bootstrap-datepicker
* Yerzhan Tolekov <era.tolekov@gmail.com>
*/
;(function($){
$.fn.datepicker.dates['kk'] = {
days: ["Жексенбі", "Дүйсенбі", "Сейсенбі", "Сәрсенбі", "Бейсенбі", "Жұма", "Сенбі", "Жексенбі"],
daysShort: ["Жек", "Дүй", "Сей", "Сәр", "Бей", "Жұм", "Сен", "Жек"],
daysMin: ["Жк", "Дс", "Сс", "Ср", "Бс", "Жм", "Сн", "Жк"],
months: ["Қаңтар", "Ақпан", "Наурыз", "Сәуір", "Мамыр", "Маусым", "Шілде", "Тамыз", "Қыркүйек", "Қазан", "Қараша", "Желтоқсан"],
monthsShort: ["Қаң", "Ақп", "Нау", "Сәу", "Мамыр", "Мау", "Шлд", "Тмз", "Қыр", "Қзн", "Қар", "Жел"],
today: "Бүгін",
weekStart: 1
};
}(jQuery));

View File

@@ -0,0 +1,15 @@
/**
* Macedonian translation for bootstrap-datepicker
* Marko Aleksic <psybaron@gmail.com>
*/
;(function($){
$.fn.datepicker.dates['mk'] = {
days: ["Недела", "Понеделник", "Вторник", "Среда", "Четврток", "Петок", "Сабота", "Недела"],
daysShort: ["Нед", "Пон", "Вто", "Сре", "Чет", "Пет", "Саб", "Нед"],
daysMin: ["Не", "По", "Вт", "Ср", "Че", "Пе", "Са", "Не"],
months: ["Јануари", "Февруари", "Март", "Април", "Мај", "Јуни", "Јули", "Август", "Септември", "Октомври", "Ноември", "Декември"],
monthsShort: ["Јан", "Фев", "Мар", "Апр", "Мај", "Јун", "Јул", "Авг", "Сеп", "Окт", "Ное", "Дек"],
today: "Денес",
format: "dd.mm.yyyy"
};
}(jQuery));

View File

@@ -0,0 +1,17 @@
/**
* Belgium-Dutch translation for bootstrap-datepicker
* Julien Poulin <poulin_julien@hotmail.com>
*/
;(function($){
$.fn.datepicker.dates['nl-BE'] = {
days: ["Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag", "Zondag"],
daysShort: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"],
daysMin: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"],
months: ["Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "Oktober", "November", "December"],
monthsShort: ["Jan", "Feb", "Mrt", "Apr", "Mei", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"],
today: "Vandaag",
clear: "Leegmaken",
weekStart: 1,
format: "dd/mm/yyyy"
};
}(jQuery));

View File

@@ -0,0 +1,16 @@
/**
* Norwegian translation for bootstrap-datepicker
**/
;(function($){
$.fn.datepicker.dates['no'] = {
days: ['Søndag','Mandag','Tirsdag','Onsdag','Torsdag','Fredag','Lørdag'],
daysShort: ['Søn','Man','Tir','Ons','Tor','Fre','Lør'],
daysMin: ['Sø','Ma','Ti','On','To','Fr','Lø'],
months: ['Januar','Februar','Mars','April','Mai','Juni','Juli','August','September','Oktober','November','Desember'],
monthsShort: ['Jan','Feb','Mar','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Des'],
today: 'I dag',
clear: 'Nullstill',
weekStart: 1,
format: 'dd.mm.yyyy'
};
}(jQuery));

View File

@@ -0,0 +1,15 @@
/**
* Albanian translation for bootstrap-datepicker
* Tomor Pupovci <http://www.github.com/ttomor>
*/
;(function($){
$.fn.datepicker.dates['sq'] = {
days: ["E Diel", "E Hënë", "E martē", "E mërkurë", "E Enjte", "E Premte", "E Shtunë", "E Diel"],
daysShort: ["Die", "Hën", "Mar", "Mër", "Enj", "Pre", "Shtu", "Die"],
daysMin: ["Di", "Hë", "Ma", "Më", "En", "Pr", "Sht", "Di"],
months: ["Janar", "Shkurt", "Mars", "Prill", "Maj", "Qershor", "Korrik", "Gusht", "Shtator", "Tetor", "Nëntor", "Dhjetor"],
monthsShort: ["Jan", "Shk", "Mar", "Pri", "Maj", "Qer", "Korr", "Gu", "Sht", "Tet", "Nën", "Dhjet"],
today: "Sot"
};
}(jQuery));

View File

@@ -0,0 +1,15 @@
/**
* Ukrainian translation for bootstrap-datepicker
* Igor Polynets
*/
;(function($){
$.fn.datepicker.dates['ua'] = {
days: ["Неділя", "Понеділок", "Вівторок", "Середа", "Четвер", "П'ятница", "Субота", "Неділя"],
daysShort: ["Нед", "Пнд", "Втр", "Срд", "Чтв", "Птн", "Суб", "Нед"],
daysMin: ["Нд", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Нд"],
months: ["Cічень", "Лютий", "Березень", "Квітень", "Травень", "Червень", "Липень", "Серпень", "Вересень", "Жовтень", "Листопад", "Грудень"],
monthsShort: ["Січ", "Лют", "Бер", "Кві", "Тра", "Чер", "Лип", "Сер", "Вер", "Жов", "Лис", "Гру"],
today: "Сьогодні",
weekStart: 1
};
}(jQuery));

View File

@@ -0,0 +1,16 @@
/**
* Vietnamese translation for bootstrap-datepicker
* An Vo <https://github.com/anvoz/>
*/
;(function($){
$.fn.datepicker.dates['vi'] = {
days: ["Chủ nhật", "Thứ hai", "Thứ ba", "Thứ tư", "Thứ năm", "Thứ sáu", "Thứ bảy", "Chủ nhật"],
daysShort: ["CN", "Thứ 2", "Thứ 3", "Thứ 4", "Thứ 5", "Thứ 6", "Thứ 7", "CN"],
daysMin: ["CN", "T2", "T3", "T4", "T5", "T6", "T7", "CN"],
months: ["Tháng 1", "Tháng 2", "Tháng 3", "Tháng 4", "Tháng 5", "Tháng 6", "Tháng 7", "Tháng 8", "Tháng 9", "Tháng 10", "Tháng 11", "Tháng 12"],
monthsShort: ["Th1", "Th2", "Th3", "Th4", "Th5", "Th6", "Th7", "Th8", "Th9", "Th10", "Th11", "Th12"],
today: "Hôm nay",
clear: "Xóa",
format: "dd/mm/yyyy"
};
}(jQuery));

View File

@@ -0,0 +1,178 @@
var DataSourceTree = function(options) {
this._data = options.data;
this._delay = options.delay;
}
DataSourceTree.prototype.data = function(options, callback) {
var self = this;
var $data = null;
if(!("name" in options) && !("type" in options)){
$data = this._data;//the root tree
callback({ data: $data });
return;
}
else if("type" in options && options.type == "folder") {
if("additionalParameters" in options && "children" in options.additionalParameters)
$data = options.additionalParameters.children;
else $data = {}//no data
}
if($data != null)//this setTimeout is only for mimicking some random delay
setTimeout(function(){callback({ data: $data });} , parseInt(Math.random() * 500) + 200);
//we have used static data here
//but you can retrieve your data dynamically from a server using ajax call
//checkout examples/treeview.html and examples/treeview.js for more info
};
var tree_data = {
'for-sale' : {name: 'For Sale', type: 'folder'} ,
'vehicles' : {name: 'Vehicles', type: 'folder'} ,
'rentals' : {name: 'Rentals', type: 'folder'} ,
'real-estate' : {name: 'Real Estate', type: 'folder'} ,
'pets' : {name: 'Pets', type: 'folder'} ,
'tickets' : {name: 'Tickets', type: 'item'} ,
'services' : {name: 'Services', type: 'item'} ,
'personals' : {name: 'Personals', type: 'item'}
}
tree_data['for-sale']['additionalParameters'] = {
'children' : {
'appliances' : {name: 'Appliances', type: 'item'},
'arts-crafts' : {name: 'Arts & Crafts', type: 'item'},
'clothing' : {name: 'Clothing', type: 'item'},
'computers' : {name: 'Computers', type: 'item'},
'jewelry' : {name: 'Jewelry', type: 'item'},
'office-business' : {name: 'Office & Business', type: 'item'},
'sports-fitness' : {name: 'Sports & Fitness', type: 'item'}
}
}
tree_data['vehicles']['additionalParameters'] = {
'children' : {
'cars' : {name: 'Cars', type: 'folder'},
'motorcycles' : {name: 'Motorcycles', type: 'item'},
'boats' : {name: 'Boats', type: 'item'}
}
}
tree_data['vehicles']['additionalParameters']['children']['cars']['additionalParameters'] = {
'children' : {
'classics' : {name: 'Classics', type: 'item'},
'convertibles' : {name: 'Convertibles', type: 'item'},
'coupes' : {name: 'Coupes', type: 'item'},
'hatchbacks' : {name: 'Hatchbacks', type: 'item'},
'hybrids' : {name: 'Hybrids', type: 'item'},
'suvs' : {name: 'SUVs', type: 'item'},
'sedans' : {name: 'Sedans', type: 'item'},
'trucks' : {name: 'Trucks', type: 'item'}
}
}
tree_data['rentals']['additionalParameters'] = {
'children' : {
'apartments-rentals' : {name: 'Apartments', type: 'item'},
'office-space-rentals' : {name: 'Office Space', type: 'item'},
'vacation-rentals' : {name: 'Vacation Rentals', type: 'item'}
}
}
tree_data['real-estate']['additionalParameters'] = {
'children' : {
'apartments' : {name: 'Apartments', type: 'item'},
'villas' : {name: 'Villas', type: 'item'},
'plots' : {name: 'Plots', type: 'item'}
}
}
tree_data['pets']['additionalParameters'] = {
'children' : {
'cats' : {name: 'Cats', type: 'item'},
'dogs' : {name: 'Dogs', type: 'item'},
'horses' : {name: 'Horses', type: 'item'},
'reptiles' : {name: 'Reptiles', type: 'item'}
}
}
var treeDataSource = new DataSourceTree({data: tree_data});
var ace_icon = ace.vars['icon'];
//class="'+ace_icon+' fa fa-file-text grey"
//becomes
//class="ace-icon fa fa-file-text grey"
var tree_data_2 = {
'pictures' : {name: 'Pictures', type: 'folder', 'icon-class':'red'} ,
'music' : {name: 'Music', type: 'folder', 'icon-class':'orange'} ,
'video' : {name: 'Video', type: 'folder', 'icon-class':'blue'} ,
'documents' : {name: 'Documents', type: 'folder', 'icon-class':'green'} ,
'backup' : {name: 'Backup', type: 'folder'} ,
'readme' : {name: '<i class="'+ace_icon+' fa fa-file-text grey"></i> ReadMe.txt', type: 'item'},
'manual' : {name: '<i class="'+ace_icon+' fa fa-book blue"></i> Manual.html', type: 'item'}
}
tree_data_2['music']['additionalParameters'] = {
'children' : [
{name: '<i class="'+ace_icon+' fa fa-music blue"></i> song1.ogg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-music blue"></i> song2.ogg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-music blue"></i> song3.ogg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-music blue"></i> song4.ogg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-music blue"></i> song5.ogg', type: 'item'}
]
}
tree_data_2['video']['additionalParameters'] = {
'children' : [
{name: '<i class="'+ace_icon+' fa fa-film blue"></i> movie1.avi', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-film blue"></i> movie2.avi', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-film blue"></i> movie3.avi', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-film blue"></i> movie4.avi', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-film blue"></i> movie5.avi', type: 'item'}
]
}
tree_data_2['pictures']['additionalParameters'] = {
'children' : {
'wallpapers' : {name: 'Wallpapers', type: 'folder', 'icon-class':'pink'},
'camera' : {name: 'Camera', type: 'folder', 'icon-class':'pink'}
}
}
tree_data_2['pictures']['additionalParameters']['children']['wallpapers']['additionalParameters'] = {
'children' : [
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> wallpaper1.jpg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> wallpaper2.jpg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> wallpaper3.jpg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> wallpaper4.jpg', type: 'item'}
]
}
tree_data_2['pictures']['additionalParameters']['children']['camera']['additionalParameters'] = {
'children' : [
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> photo1.jpg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> photo2.jpg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> photo3.jpg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> photo4.jpg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> photo5.jpg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> photo6.jpg', type: 'item'}
]
}
tree_data_2['documents']['additionalParameters'] = {
'children' : [
{name: '<i class="'+ace_icon+' fa fa-file-text red"></i> document1.pdf', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-file-text grey"></i> document2.doc', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-file-text grey"></i> document3.doc', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-file-text red"></i> document4.pdf', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-file-text grey"></i> document5.doc', type: 'item'}
]
}
tree_data_2['backup']['additionalParameters'] = {
'children' : [
{name: '<i class="'+ace_icon+' fa fa-archive brown"></i> backup1.zip', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-archive brown"></i> backup2.zip', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-archive brown"></i> backup3.zip', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-archive brown"></i> backup4.zip', type: 'item'}
]
}
var treeDataSource2 = new DataSourceTree({data: tree_data_2});

File diff suppressed because one or more lines are too long

7
static/js/lib/ace/jquery-ui.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,200 @@
// Generated by CoffeeScript 1.6.3
/*
Easy pie chart is a jquery plugin to display simple animated pie charts for only one value
Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
Built on top of the jQuery library (http://jquery.com)
@source: http://github.com/rendro/easy-pie-chart/
@autor: Robert Fleischmann
@version: 1.2.5
Inspired by: http://dribbble.com/shots/631074-Simple-Pie-Charts-II?list=popular&offset=210
Thanks to Philip Thrasher for the jquery plugin boilerplate for coffee script
*/
(function($) {
$.easyPieChart = function(el, options) {
var addScaleLine, animateLine, drawLine, easeInOutQuad, rAF, renderBackground, renderScale, renderTrack,
_this = this;
this.el = el;
this.$el = $(el);
this.$el.data("easyPieChart", this);
this.init = function() {
var percent, scaleBy;
_this.options = $.extend({}, $.easyPieChart.defaultOptions, options);
percent = parseInt(_this.$el.data('percent'), 10);
_this.percentage = 0;
_this.canvas = $("<canvas width='" + _this.options.size + "' height='" + _this.options.size + "'></canvas>").get(0);
_this.$el.append(_this.canvas);
if (typeof G_vmlCanvasManager !== "undefined" && G_vmlCanvasManager !== null) {
G_vmlCanvasManager.initElement(_this.canvas);
}
_this.ctx = _this.canvas.getContext('2d');
if (window.devicePixelRatio > 1) {
scaleBy = window.devicePixelRatio;
$(_this.canvas).css({
width: _this.options.size,
height: _this.options.size
});
_this.canvas.width *= scaleBy;
_this.canvas.height *= scaleBy;
_this.ctx.scale(scaleBy, scaleBy);
}
_this.ctx.translate(_this.options.size / 2, _this.options.size / 2);
_this.ctx.rotate(_this.options.rotate * Math.PI / 180);
_this.$el.addClass('easyPieChart');
_this.$el.css({
width: _this.options.size,
height: _this.options.size,
lineHeight: "" + _this.options.size + "px"
});
_this.update(percent);
return _this;
};
this.update = function(percent) {
percent = parseFloat(percent) || 0;
if (_this.options.animate === false) {
drawLine(percent);
} else {
if (_this.options.delay) {
animateLine(_this.percentage, 0);
setTimeout(function() {
return animateLine(_this.percentage, percent);
}, _this.options.delay);
} else {
animateLine(_this.percentage, percent);
}
}
return _this;
};
renderScale = function() {
var i, _i, _results;
_this.ctx.fillStyle = _this.options.scaleColor;
_this.ctx.lineWidth = 1;
_results = [];
for (i = _i = 0; _i <= 24; i = ++_i) {
_results.push(addScaleLine(i));
}
return _results;
};
addScaleLine = function(i) {
var offset;
offset = i % 6 === 0 ? 0 : _this.options.size * 0.017;
_this.ctx.save();
_this.ctx.rotate(i * Math.PI / 12);
_this.ctx.fillRect(_this.options.size / 2 - offset, 0, -_this.options.size * 0.05 + offset, 1);
_this.ctx.restore();
};
renderTrack = function() {
var offset;
offset = _this.options.size / 2 - _this.options.lineWidth / 2;
if (_this.options.scaleColor !== false) {
offset -= _this.options.size * 0.08;
}
_this.ctx.beginPath();
_this.ctx.arc(0, 0, offset, 0, Math.PI * 2, true);
_this.ctx.closePath();
_this.ctx.strokeStyle = _this.options.trackColor;
_this.ctx.lineWidth = _this.options.lineWidth;
_this.ctx.stroke();
};
renderBackground = function() {
if (_this.options.scaleColor !== false) {
renderScale();
}
if (_this.options.trackColor !== false) {
renderTrack();
}
};
drawLine = function(percent) {
var offset;
renderBackground();
_this.ctx.strokeStyle = $.isFunction(_this.options.barColor) ? _this.options.barColor(percent) : _this.options.barColor;
_this.ctx.lineCap = _this.options.lineCap;
_this.ctx.lineWidth = _this.options.lineWidth;
offset = _this.options.size / 2 - _this.options.lineWidth / 2;
if (_this.options.scaleColor !== false) {
offset -= _this.options.size * 0.08;
}
_this.ctx.save();
_this.ctx.rotate(-Math.PI / 2);
_this.ctx.beginPath();
_this.ctx.arc(0, 0, offset, 0, Math.PI * 2 * percent / 100, false);
_this.ctx.stroke();
_this.ctx.restore();
};
rAF = (function() {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) {
return window.setTimeout(callback, 1000 / 60);
};
})();
animateLine = function(from, to) {
var anim, startTime;
_this.options.onStart.call(_this);
_this.percentage = to;
Date.now || (Date.now = function() {
return +(new Date);
});
startTime = Date.now();
anim = function() {
var currentValue, process;
process = Math.min(Date.now() - startTime, _this.options.animate);
_this.ctx.clearRect(-_this.options.size / 2, -_this.options.size / 2, _this.options.size, _this.options.size);
renderBackground.call(_this);
currentValue = [easeInOutQuad(process, from, to - from, _this.options.animate)];
_this.options.onStep.call(_this, currentValue);
drawLine.call(_this, currentValue);
if (process >= _this.options.animate) {
return _this.options.onStop.call(_this, currentValue, to);
} else {
return rAF(anim);
}
};
rAF(anim);
};
easeInOutQuad = function(t, b, c, d) {
var easeIn, easing;
easeIn = function(t) {
return Math.pow(t, 2);
};
easing = function(t) {
if (t < 1) {
return easeIn(t);
} else {
return 2 - easeIn((t / 2) * -2 + 2);
}
};
t /= d / 2;
return c / 2 * easing(t) + b;
};
return this.init();
};
$.easyPieChart.defaultOptions = {
barColor: '#ef1e25',
trackColor: '#f2f2f2',
scaleColor: '#dfe0e0',
lineCap: 'round',
rotate: 0,
size: 110,
lineWidth: 3,
animate: false,
delay: false,
onStart: $.noop,
onStop: $.noop,
onStep: $.noop
};
$.fn.easyPieChart = function(options) {
return $.each(this, function(i, el) {
var $el, instanceOptions;
$el = $(el);
if (!$el.data('easyPieChart')) {
instanceOptions = $.extend({}, options, $el.data());
return $el.data('easyPieChart', new $.easyPieChart(el, instanceOptions));
}
});
};
return void 0;
})(jQuery);

View File

@@ -0,0 +1,9 @@
/**!
* easyPieChart
* Lightweight plugin to render simple, animated and retina optimized pie charts
*
* @license
* @author Robert Fleischmann <rendro87@gmail.com> (http://robert-fleischmann.de)
* @version 2.1.5
**/
(function(a,b){if(typeof exports==="object"){module.exports=b(require("jquery"))}else{if(typeof define==="function"&&define.amd){define(["jquery"],b)}else{b(a.jQuery)}}}(this,function(c){var a=function(e,n){var l;var f=document.createElement("canvas");e.appendChild(f);if(typeof(G_vmlCanvasManager)!=="undefined"){G_vmlCanvasManager.initElement(f)}var m=f.getContext("2d");f.width=f.height=n.size;var k=1;if(window.devicePixelRatio>1){k=window.devicePixelRatio;f.style.width=f.style.height=[n.size,"px"].join("");f.width=f.height=n.size*k;m.scale(k,k)}m.translate(n.size/2,n.size/2);m.rotate((-1/2+n.rotate/180)*Math.PI);var i=(n.size-n.lineWidth)/2;if(n.scaleColor&&n.scaleLength){i-=n.scaleLength+2}Date.now=Date.now||function(){return +(new Date())};var j=function(q,o,r){r=Math.min(Math.max(-1,r||0),1);var p=r<=0?true:false;m.beginPath();m.arc(0,0,i,0,Math.PI*2*r,p);m.strokeStyle=q;m.lineWidth=o;m.stroke()};var d=function(){var q;var p;m.lineWidth=1;m.fillStyle=n.scaleColor;m.save();for(var o=24;o>0;--o){if(o%6===0){p=n.scaleLength;q=0}else{p=n.scaleLength*0.6;q=n.scaleLength-p}m.fillRect(-n.size/2+q,0,p,1);m.rotate(Math.PI/12)}m.restore()};var h=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(o){window.setTimeout(o,1000/60)}}());var g=function(){if(n.scaleColor){d()}if(n.trackColor){j(n.trackColor,n.lineWidth,1)}};this.getCanvas=function(){return f};this.getCtx=function(){return m};this.clear=function(){m.clearRect(n.size/-2,n.size/-2,n.size,n.size)};this.draw=function(p){if(!!n.scaleColor||!!n.trackColor){if(m.getImageData&&m.putImageData){if(!l){g();l=m.getImageData(0,0,n.size*k,n.size*k)}else{m.putImageData(l,0,0)}}else{this.clear();g()}}else{this.clear()}m.lineCap=n.lineCap;var o;if(typeof(n.barColor)==="function"){o=n.barColor(p)}else{o=n.barColor}j(o,n.lineWidth,p/100)}.bind(this);this.animate=function(r,q){var o=Date.now();n.onStart(r,q);var p=function(){var t=Math.min(Date.now()-o,n.animate.duration);var s=n.easing(this,t,r,q-r,n.animate.duration);this.draw(s);n.onStep(r,q,s);if(t>=n.animate.duration){n.onStop(r,q)}else{h(p)}}.bind(this);h(p)}.bind(this)};var b=function(g,h){var d={barColor:"#ef1e25",trackColor:"#f9f9f9",scaleColor:"#dfe0e0",scaleLength:5,lineCap:"round",lineWidth:3,size:110,rotate:0,animate:{duration:1000,enabled:true},easing:function(k,l,j,n,m){l=l/(m/2);if(l<1){return n/2*l*l+j}return -n/2*((--l)*(l-2)-1)+j},onStart:function(k,j){return},onStep:function(l,k,j){return},onStop:function(k,j){return}};if(typeof(a)!=="undefined"){d.renderer=a}else{if(typeof(SVGRenderer)!=="undefined"){d.renderer=SVGRenderer}else{throw new Error("Please load either the SVG- or the CanvasRenderer")}}var e={};var f=0;var i=function(){this.el=g;this.options=e;for(var j in d){if(d.hasOwnProperty(j)){e[j]=h&&typeof(h[j])!=="undefined"?h[j]:d[j];if(typeof(e[j])==="function"){e[j]=e[j].bind(this)}}}if(typeof(e.easing)==="string"&&typeof(jQuery)!=="undefined"&&jQuery.isFunction(jQuery.easing[e.easing])){e.easing=jQuery.easing[e.easing]}else{e.easing=d.easing}if(typeof(e.animate)==="number"){e.animate={duration:e.animate,enabled:true}}if(typeof(e.animate)==="boolean"&&!e.animate){e.animate={duration:1000,enabled:e.animate}}this.renderer=new e.renderer(g,e);this.renderer.draw(f);if(g.dataset&&g.dataset.percent){this.update(parseFloat(g.dataset.percent))}else{if(g.getAttribute&&g.getAttribute("data-percent")){this.update(parseFloat(g.getAttribute("data-percent")))}}g.style.width=g.style.height=e.size+"px";g.style.lineHeight=(e.size-1)+"px"}.bind(this);this.update=function(j){j=parseFloat(j);if(e.animate.enabled){this.renderer.animate(f,j)}else{this.renderer.draw(j)}f=j;return this}.bind(this);this.disableAnimation=function(){e.animate.enabled=false;return this};this.enableAnimation=function(){e.animate.enabled=true;return this};i()};c.fn.easyPieChart=function(d){return this.each(function(){var e;if(!c.data(this,"easyPieChart")){e=c.extend({},d,c(this).data());c.data(this,"easyPieChart",new b(this,e))}})}}));

File diff suppressed because one or more lines are too long

4
static/js/lib/ace/jquery.min.js vendored Normal file

File diff suppressed because one or more lines are too long

4
static/js/lib/ace/jquery1x.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,178 @@
var DataSourceTree = function(options) {
this._data = options.data;
this._delay = options.delay;
}
DataSourceTree.prototype.data = function(options, callback) {
var self = this;
var $data = null;
if(!("name" in options) && !("type" in options)){
$data = this._data;//the root tree
callback({ data: $data });
return;
}
else if("type" in options && options.type == "folder") {
if("additionalParameters" in options && "children" in options.additionalParameters)
$data = options.additionalParameters.children;
else $data = {}//no data
}
if($data != null)//this setTimeout is only for mimicking some random delay
setTimeout(function(){callback({ data: $data });} , parseInt(Math.random() * 500) + 200);
//we have used static data here
//but you can retrieve your data dynamically from a server using ajax call
//checkout examples/treeview.html and examples/treeview.js for more info
};
var tree_data = {
'for-sale' : {name: 'For Sale', type: 'folder'} ,
'vehicles' : {name: 'Vehicles', type: 'folder'} ,
'rentals' : {name: 'Rentals', type: 'folder'} ,
'real-estate' : {name: 'Real Estate', type: 'folder'} ,
'pets' : {name: 'Pets', type: 'folder'} ,
'tickets' : {name: 'Tickets', type: 'item'} ,
'services' : {name: 'Services', type: 'item'} ,
'personals' : {name: 'Personals', type: 'item'}
}
tree_data['for-sale']['additionalParameters'] = {
'children' : {
'appliances' : {name: 'Appliances', type: 'item'},
'arts-crafts' : {name: 'Arts & Crafts', type: 'item'},
'clothing' : {name: 'Clothing', type: 'item'},
'computers' : {name: 'Computers', type: 'item'},
'jewelry' : {name: 'Jewelry', type: 'item'},
'office-business' : {name: 'Office & Business', type: 'item'},
'sports-fitness' : {name: 'Sports & Fitness', type: 'item'}
}
}
tree_data['vehicles']['additionalParameters'] = {
'children' : {
'cars' : {name: 'Cars', type: 'folder'},
'motorcycles' : {name: 'Motorcycles', type: 'item'},
'boats' : {name: 'Boats', type: 'item'}
}
}
tree_data['vehicles']['additionalParameters']['children']['cars']['additionalParameters'] = {
'children' : {
'classics' : {name: 'Classics', type: 'item'},
'convertibles' : {name: 'Convertibles', type: 'item'},
'coupes' : {name: 'Coupes', type: 'item'},
'hatchbacks' : {name: 'Hatchbacks', type: 'item'},
'hybrids' : {name: 'Hybrids', type: 'item'},
'suvs' : {name: 'SUVs', type: 'item'},
'sedans' : {name: 'Sedans', type: 'item'},
'trucks' : {name: 'Trucks', type: 'item'}
}
}
tree_data['rentals']['additionalParameters'] = {
'children' : {
'apartments-rentals' : {name: 'Apartments', type: 'item'},
'office-space-rentals' : {name: 'Office Space', type: 'item'},
'vacation-rentals' : {name: 'Vacation Rentals', type: 'item'}
}
}
tree_data['real-estate']['additionalParameters'] = {
'children' : {
'apartments' : {name: 'Apartments', type: 'item'},
'villas' : {name: 'Villas', type: 'item'},
'plots' : {name: 'Plots', type: 'item'}
}
}
tree_data['pets']['additionalParameters'] = {
'children' : {
'cats' : {name: 'Cats', type: 'item'},
'dogs' : {name: 'Dogs', type: 'item'},
'horses' : {name: 'Horses', type: 'item'},
'reptiles' : {name: 'Reptiles', type: 'item'}
}
}
var treeDataSource = new DataSourceTree({data: tree_data});
var ace_icon = ace.vars['icon'];
//class="'+ace_icon+' fa fa-file-text grey"
//becomes
//class="ace-icon fa fa-file-text grey"
var tree_data_2 = {
'pictures' : {name: 'Pictures', type: 'folder', 'icon-class':'red'} ,
'music' : {name: 'Music', type: 'folder', 'icon-class':'orange'} ,
'video' : {name: 'Video', type: 'folder', 'icon-class':'blue'} ,
'documents' : {name: 'Documents', type: 'folder', 'icon-class':'green'} ,
'backup' : {name: 'Backup', type: 'folder'} ,
'readme' : {name: '<i class="'+ace_icon+' fa fa-file-text grey"></i> ReadMe.txt', type: 'item'},
'manual' : {name: '<i class="'+ace_icon+' fa fa-book blue"></i> Manual.html', type: 'item'}
}
tree_data_2['music']['additionalParameters'] = {
'children' : [
{name: '<i class="'+ace_icon+' fa fa-music blue"></i> song1.ogg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-music blue"></i> song2.ogg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-music blue"></i> song3.ogg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-music blue"></i> song4.ogg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-music blue"></i> song5.ogg', type: 'item'}
]
}
tree_data_2['video']['additionalParameters'] = {
'children' : [
{name: '<i class="'+ace_icon+' fa fa-film blue"></i> movie1.avi', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-film blue"></i> movie2.avi', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-film blue"></i> movie3.avi', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-film blue"></i> movie4.avi', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-film blue"></i> movie5.avi', type: 'item'}
]
}
tree_data_2['pictures']['additionalParameters'] = {
'children' : {
'wallpapers' : {name: 'Wallpapers', type: 'folder', 'icon-class':'pink'},
'camera' : {name: 'Camera', type: 'folder', 'icon-class':'pink'}
}
}
tree_data_2['pictures']['additionalParameters']['children']['wallpapers']['additionalParameters'] = {
'children' : [
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> wallpaper1.jpg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> wallpaper2.jpg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> wallpaper3.jpg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> wallpaper4.jpg', type: 'item'}
]
}
tree_data_2['pictures']['additionalParameters']['children']['camera']['additionalParameters'] = {
'children' : [
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> photo1.jpg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> photo2.jpg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> photo3.jpg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> photo4.jpg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> photo5.jpg', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-picture-o green"></i> photo6.jpg', type: 'item'}
]
}
tree_data_2['documents']['additionalParameters'] = {
'children' : [
{name: '<i class="'+ace_icon+' fa fa-file-text red"></i> document1.pdf', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-file-text grey"></i> document2.doc', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-file-text grey"></i> document3.doc', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-file-text red"></i> document4.pdf', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-file-text grey"></i> document5.doc', type: 'item'}
]
}
tree_data_2['backup']['additionalParameters'] = {
'children' : [
{name: '<i class="'+ace_icon+' fa fa-archive brown"></i> backup1.zip', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-archive brown"></i> backup2.zip', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-archive brown"></i> backup3.zip', type: 'item'},
{name: '<i class="'+ace_icon+' fa fa-archive brown"></i> backup4.zip', type: 'item'}
]
}
var treeDataSource2 = new DataSourceTree({data: tree_data_2});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

15008
static/js/lib/ace/uncompressed/jquery-ui.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,362 @@
/**!
* easyPieChart
* Lightweight plugin to render simple, animated and retina optimized pie charts
*
* @license
* @author Robert Fleischmann <rendro87@gmail.com> (http://robert-fleischmann.de)
* @version 2.1.5
**/
(function(root, factory) {
if(typeof exports === 'object') {
module.exports = factory(require('jquery'));
}
else if(typeof define === 'function' && define.amd) {
define(['jquery'], factory);
}
else {
factory(root.jQuery);
}
}(this, function($) {
/**
* Renderer to render the chart on a canvas object
* @param {DOMElement} el DOM element to host the canvas (root of the plugin)
* @param {object} options options object of the plugin
*/
var CanvasRenderer = function(el, options) {
var cachedBackground;
var canvas = document.createElement('canvas');
el.appendChild(canvas);
if (typeof(G_vmlCanvasManager) !== 'undefined') {
G_vmlCanvasManager.initElement(canvas);
}
var ctx = canvas.getContext('2d');
canvas.width = canvas.height = options.size;
// canvas on retina devices
var scaleBy = 1;
if (window.devicePixelRatio > 1) {
scaleBy = window.devicePixelRatio;
canvas.style.width = canvas.style.height = [options.size, 'px'].join('');
canvas.width = canvas.height = options.size * scaleBy;
ctx.scale(scaleBy, scaleBy);
}
// move 0,0 coordinates to the center
ctx.translate(options.size / 2, options.size / 2);
// rotate canvas -90deg
ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI);
var radius = (options.size - options.lineWidth) / 2;
if (options.scaleColor && options.scaleLength) {
radius -= options.scaleLength + 2; // 2 is the distance between scale and bar
}
// IE polyfill for Date
Date.now = Date.now || function() {
return +(new Date());
};
/**
* Draw a circle around the center of the canvas
* @param {strong} color Valid CSS color string
* @param {number} lineWidth Width of the line in px
* @param {number} percent Percentage to draw (float between -1 and 1)
*/
var drawCircle = function(color, lineWidth, percent) {
percent = Math.min(Math.max(-1, percent || 0), 1);
var isNegative = percent <= 0 ? true : false;
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, isNegative);
ctx.strokeStyle = color;
ctx.lineWidth = lineWidth;
ctx.stroke();
};
/**
* Draw the scale of the chart
*/
var drawScale = function() {
var offset;
var length;
ctx.lineWidth = 1;
ctx.fillStyle = options.scaleColor;
ctx.save();
for (var i = 24; i > 0; --i) {
if (i % 6 === 0) {
length = options.scaleLength;
offset = 0;
} else {
length = options.scaleLength * 0.6;
offset = options.scaleLength - length;
}
ctx.fillRect(-options.size/2 + offset, 0, length, 1);
ctx.rotate(Math.PI / 12);
}
ctx.restore();
};
/**
* Request animation frame wrapper with polyfill
* @return {function} Request animation frame method or timeout fallback
*/
var reqAnimationFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
}());
/**
* Draw the background of the plugin including the scale and the track
*/
var drawBackground = function() {
if(options.scaleColor) drawScale();
if(options.trackColor) drawCircle(options.trackColor, options.lineWidth, 1);
};
/**
* Canvas accessor
*/
this.getCanvas = function() {
return canvas;
};
/**
* Canvas 2D context 'ctx' accessor
*/
this.getCtx = function() {
return ctx;
};
/**
* Clear the complete canvas
*/
this.clear = function() {
ctx.clearRect(options.size / -2, options.size / -2, options.size, options.size);
};
/**
* Draw the complete chart
* @param {number} percent Percent shown by the chart between -100 and 100
*/
this.draw = function(percent) {
// do we need to render a background
if (!!options.scaleColor || !!options.trackColor) {
// getImageData and putImageData are supported
if (ctx.getImageData && ctx.putImageData) {
if (!cachedBackground) {
drawBackground();
cachedBackground = ctx.getImageData(0, 0, options.size * scaleBy, options.size * scaleBy);
} else {
ctx.putImageData(cachedBackground, 0, 0);
}
} else {
this.clear();
drawBackground();
}
} else {
this.clear();
}
ctx.lineCap = options.lineCap;
// if barcolor is a function execute it and pass the percent as a value
var color;
if (typeof(options.barColor) === 'function') {
color = options.barColor(percent);
} else {
color = options.barColor;
}
// draw bar
drawCircle(color, options.lineWidth, percent / 100);
}.bind(this);
/**
* Animate from some percent to some other percentage
* @param {number} from Starting percentage
* @param {number} to Final percentage
*/
this.animate = function(from, to) {
var startTime = Date.now();
options.onStart(from, to);
var animation = function() {
var process = Math.min(Date.now() - startTime, options.animate.duration);
var currentValue = options.easing(this, process, from, to - from, options.animate.duration);
this.draw(currentValue);
options.onStep(from, to, currentValue);
if (process >= options.animate.duration) {
options.onStop(from, to);
} else {
reqAnimationFrame(animation);
}
}.bind(this);
reqAnimationFrame(animation);
}.bind(this);
};
var EasyPieChart = function(el, opts) {
var defaultOptions = {
barColor: '#ef1e25',
trackColor: '#f9f9f9',
scaleColor: '#dfe0e0',
scaleLength: 5,
lineCap: 'round',
lineWidth: 3,
size: 110,
rotate: 0,
animate: {
duration: 1000,
enabled: true
},
easing: function (x, t, b, c, d) { // more can be found here: http://gsgd.co.uk/sandbox/jquery/easing/
t = t / (d/2);
if (t < 1) {
return c / 2 * t * t + b;
}
return -c/2 * ((--t)*(t-2) - 1) + b;
},
onStart: function(from, to) {
return;
},
onStep: function(from, to, currentValue) {
return;
},
onStop: function(from, to) {
return;
}
};
// detect present renderer
if (typeof(CanvasRenderer) !== 'undefined') {
defaultOptions.renderer = CanvasRenderer;
} else if (typeof(SVGRenderer) !== 'undefined') {
defaultOptions.renderer = SVGRenderer;
} else {
throw new Error('Please load either the SVG- or the CanvasRenderer');
}
var options = {};
var currentValue = 0;
/**
* Initialize the plugin by creating the options object and initialize rendering
*/
var init = function() {
this.el = el;
this.options = options;
// merge user options into default options
for (var i in defaultOptions) {
if (defaultOptions.hasOwnProperty(i)) {
options[i] = opts && typeof(opts[i]) !== 'undefined' ? opts[i] : defaultOptions[i];
if (typeof(options[i]) === 'function') {
options[i] = options[i].bind(this);
}
}
}
// check for jQuery easing
if (typeof(options.easing) === 'string' && typeof(jQuery) !== 'undefined' && jQuery.isFunction(jQuery.easing[options.easing])) {
options.easing = jQuery.easing[options.easing];
} else {
options.easing = defaultOptions.easing;
}
// process earlier animate option to avoid bc breaks
if (typeof(options.animate) === 'number') {
options.animate = {
duration: options.animate,
enabled: true
};
}
if (typeof(options.animate) === 'boolean' && !options.animate) {
options.animate = {
duration: 1000,
enabled: options.animate
};
}
// create renderer
this.renderer = new options.renderer(el, options);
// initial draw
this.renderer.draw(currentValue);
// initial update
if (el.dataset && el.dataset.percent) {
this.update(parseFloat(el.dataset.percent));
} else if (el.getAttribute && el.getAttribute('data-percent')) {
this.update(parseFloat(el.getAttribute('data-percent')));
}
el.style['width'] = el.style['height'] = options.size + 'px';//ACE
el.style['lineHeight'] = (options.size - 1) + 'px';//ACE
}.bind(this);
/**
* Update the value of the chart
* @param {number} newValue Number between 0 and 100
* @return {object} Instance of the plugin for method chaining
*/
this.update = function(newValue) {
newValue = parseFloat(newValue);
if (options.animate.enabled) {
this.renderer.animate(currentValue, newValue);
} else {
this.renderer.draw(newValue);
}
currentValue = newValue;
return this;
}.bind(this);
/**
* Disable animation
* @return {object} Instance of the plugin for method chaining
*/
this.disableAnimation = function() {
options.animate.enabled = false;
return this;
};
/**
* Enable animation
* @return {object} Instance of the plugin for method chaining
*/
this.enableAnimation = function() {
options.animate.enabled = true;
return this;
};
init();
};
$.fn.easyPieChart = function(options) {
return this.each(function() {
var instanceOptions;
if (!$.data(this, 'easyPieChart')) {
instanceOptions = $.extend({}, options, $(this).data());
$.data(this, 'easyPieChart', new EasyPieChart(this, instanceOptions));
}
});
};
}));

9111
static/js/lib/ace/uncompressed/jquery.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,485 @@
/*!
* Nestable jQuery Plugin - Copyright (c) 2012 David Bushell - http://dbushell.com/
* Dual-licensed under the BSD or MIT licenses
*/
;(function($, window, document, undefined)
{
var hasTouch = 'ontouchstart' in document.documentElement;
/**
* Detect CSS pointer-events property
* events are normally disabled on the dragging element to avoid conflicts
* https://github.com/ausi/Feature-detection-technique-for-pointer-events/blob/master/modernizr-pointerevents.js
*/
var hasPointerEvents = (function()
{
var el = document.createElement('div'),
docEl = document.documentElement;
if (!('pointerEvents' in el.style)) {
return false;
}
el.style.pointerEvents = 'auto';
el.style.pointerEvents = 'x';
docEl.appendChild(el);
var supports = window.getComputedStyle && window.getComputedStyle(el, '').pointerEvents === 'auto';
docEl.removeChild(el);
return !!supports;
})();
var eStart = hasTouch ? 'touchstart' : 'mousedown',
eMove = hasTouch ? 'touchmove' : 'mousemove',
eEnd = hasTouch ? 'touchend' : 'mouseup';
eCancel = hasTouch ? 'touchcancel' : 'mouseup';
var defaults = {
listNodeName : 'ol',
itemNodeName : 'li',
rootClass : 'dd',
listClass : 'dd-list',
itemClass : 'dd-item',
dragClass : 'dd-dragel',
handleClass : 'dd-handle',
collapsedClass : 'dd-collapsed',
placeClass : 'dd-placeholder',
noDragClass : 'dd-nodrag',
emptyClass : 'dd-empty',
expandBtnHTML : '<button data-action="expand" type="button">Expand</button>',
collapseBtnHTML : '<button data-action="collapse" type="button">Collapse</button>',
group : 0,
maxDepth : 5,
threshold : 20
};
function Plugin(element, options)
{
this.w = $(window);
this.el = $(element);
this.options = $.extend({}, defaults, options);
this.init();
}
Plugin.prototype = {
init: function()
{
var list = this;
list.reset();
list.el.data('nestable-group', this.options.group);
list.placeEl = $('<div class="' + list.options.placeClass + '"/>');
$.each(this.el.find(list.options.itemNodeName), function(k, el) {
list.setParent($(el));
});
list.el.on('click', 'button', function(e) {
if (list.dragEl || (!hasTouch && e.button !== 0)) {
return;
}
var target = $(e.currentTarget),
action = target.data('action'),
item = target.parent(list.options.itemNodeName);
if (action === 'collapse') {
list.collapseItem(item);
}
if (action === 'expand') {
list.expandItem(item);
}
});
var onStartEvent = function(e)
{
var handle = $(e.target);
if (!handle.hasClass(list.options.handleClass)) {
if (handle.closest('.' + list.options.noDragClass).length) {
return;
}
handle = handle.closest('.' + list.options.handleClass);
}
if (!handle.length || list.dragEl || (!hasTouch && e.button !== 0) || (hasTouch && e.touches.length !== 1)) {
return;
}
e.preventDefault();
list.dragStart(hasTouch ? e.touches[0] : e);
};
var onMoveEvent = function(e)
{
if (list.dragEl) {
e.preventDefault();
list.dragMove(hasTouch ? e.touches[0] : e);
}
};
var onEndEvent = function(e)
{
if (list.dragEl) {
e.preventDefault();
list.dragStop(hasTouch ? e.touches[0] : e);
}
};
if (hasTouch) {
list.el[0].addEventListener(eStart, onStartEvent, false);
window.addEventListener(eMove, onMoveEvent, false);
window.addEventListener(eEnd, onEndEvent, false);
window.addEventListener(eCancel, onEndEvent, false);
} else {
list.el.on(eStart, onStartEvent);
list.w.on(eMove, onMoveEvent);
list.w.on(eEnd, onEndEvent);
}
},
serialize: function()
{
var data,
depth = 0,
list = this;
step = function(level, depth)
{
var array = [ ],
items = level.children(list.options.itemNodeName);
items.each(function()
{
var li = $(this),
item = $.extend({}, li.data()),
sub = li.children(list.options.listNodeName);
if (sub.length) {
item.children = step(sub, depth + 1);
}
array.push(item);
});
return array;
};
data = step(list.el.find(list.options.listNodeName).first(), depth);
return data;
},
serialise: function()
{
return this.serialize();
},
reset: function()
{
this.mouse = {
offsetX : 0,
offsetY : 0,
startX : 0,
startY : 0,
lastX : 0,
lastY : 0,
nowX : 0,
nowY : 0,
distX : 0,
distY : 0,
dirAx : 0,
dirX : 0,
dirY : 0,
lastDirX : 0,
lastDirY : 0,
distAxX : 0,
distAxY : 0
};
this.moving = false;
this.dragEl = null;
this.dragRootEl = null;
this.dragDepth = 0;
this.hasNewRoot = false;
this.pointEl = null;
},
expandItem: function(li)
{
li.removeClass(this.options.collapsedClass);
li.children('[data-action="expand"]').hide();
li.children('[data-action="collapse"]').show();
li.children(this.options.listNodeName).show();
},
collapseItem: function(li)
{
var lists = li.children(this.options.listNodeName);
if (lists.length) {
li.addClass(this.options.collapsedClass);
li.children('[data-action="collapse"]').hide();
li.children('[data-action="expand"]').show();
li.children(this.options.listNodeName).hide();
}
},
expandAll: function()
{
var list = this;
list.el.find(list.options.itemNodeName).each(function() {
list.expandItem($(this));
});
},
collapseAll: function()
{
var list = this;
list.el.find(list.options.itemNodeName).each(function() {
list.collapseItem($(this));
});
},
setParent: function(li)
{
if (li.children(this.options.listNodeName).length) {
li.prepend($(this.options.expandBtnHTML));
li.prepend($(this.options.collapseBtnHTML));
}
li.children('[data-action="expand"]').hide();
},
unsetParent: function(li)
{
li.removeClass(this.options.collapsedClass);
li.children('[data-action]').remove();
li.children(this.options.listNodeName).remove();
},
dragStart: function(e)
{
var mouse = this.mouse,
target = $(e.target),
dragItem = target.closest(this.options.itemNodeName);
this.placeEl.css('height', dragItem.height());
mouse.offsetX = e.offsetX !== undefined ? e.offsetX : e.pageX - target.offset().left;
mouse.offsetY = e.offsetY !== undefined ? e.offsetY : e.pageY - target.offset().top;
mouse.startX = mouse.lastX = e.pageX;
mouse.startY = mouse.lastY = e.pageY;
this.dragRootEl = this.el;
this.dragEl = $(document.createElement(this.options.listNodeName)).addClass(this.options.listClass + ' ' + this.options.dragClass);
this.dragEl.css('width', dragItem.width());
// fix for zepto.js
//dragItem.after(this.placeEl).detach().appendTo(this.dragEl);
dragItem.after(this.placeEl);
dragItem[0].parentNode.removeChild(dragItem[0]);
dragItem.appendTo(this.dragEl);
$(document.body).append(this.dragEl);
this.dragEl.css({
'left' : e.pageX - mouse.offsetX,
'top' : e.pageY - mouse.offsetY
});
// total depth of dragging item
var i, depth,
items = this.dragEl.find(this.options.itemNodeName);
for (i = 0; i < items.length; i++) {
depth = $(items[i]).parents(this.options.listNodeName).length;
if (depth > this.dragDepth) {
this.dragDepth = depth;
}
}
},
dragStop: function(e)
{
// fix for zepto.js
//this.placeEl.replaceWith(this.dragEl.children(this.options.itemNodeName + ':first').detach());
var el = this.dragEl.children(this.options.itemNodeName).first();
el[0].parentNode.removeChild(el[0]);
this.placeEl.replaceWith(el);
this.dragEl.remove();
this.el.trigger('change');
if (this.hasNewRoot) {
this.dragRootEl.trigger('change');
}
this.reset();
},
dragMove: function(e)
{
var list, parent, prev, next, depth,
opt = this.options,
mouse = this.mouse;
this.dragEl.css({
'left' : e.pageX - mouse.offsetX,
'top' : e.pageY - mouse.offsetY
});
// mouse position last events
mouse.lastX = mouse.nowX;
mouse.lastY = mouse.nowY;
// mouse position this events
mouse.nowX = e.pageX;
mouse.nowY = e.pageY;
// distance mouse moved between events
mouse.distX = mouse.nowX - mouse.lastX;
mouse.distY = mouse.nowY - mouse.lastY;
// direction mouse was moving
mouse.lastDirX = mouse.dirX;
mouse.lastDirY = mouse.dirY;
// direction mouse is now moving (on both axis)
mouse.dirX = mouse.distX === 0 ? 0 : mouse.distX > 0 ? 1 : -1;
mouse.dirY = mouse.distY === 0 ? 0 : mouse.distY > 0 ? 1 : -1;
// axis mouse is now moving on
var newAx = Math.abs(mouse.distX) > Math.abs(mouse.distY) ? 1 : 0;
// do nothing on first move
if (!mouse.moving) {
mouse.dirAx = newAx;
mouse.moving = true;
return;
}
// calc distance moved on this axis (and direction)
if (mouse.dirAx !== newAx) {
mouse.distAxX = 0;
mouse.distAxY = 0;
} else {
mouse.distAxX += Math.abs(mouse.distX);
if (mouse.dirX !== 0 && mouse.dirX !== mouse.lastDirX) {
mouse.distAxX = 0;
}
mouse.distAxY += Math.abs(mouse.distY);
if (mouse.dirY !== 0 && mouse.dirY !== mouse.lastDirY) {
mouse.distAxY = 0;
}
}
mouse.dirAx = newAx;
/**
* move horizontal
*/
if (mouse.dirAx && mouse.distAxX >= opt.threshold) {
// reset move distance on x-axis for new phase
mouse.distAxX = 0;
prev = this.placeEl.prev(opt.itemNodeName);
// increase horizontal level if previous sibling exists and is not collapsed
if (mouse.distX > 0 && prev.length && !prev.hasClass(opt.collapsedClass)) {
// cannot increase level when item above is collapsed
list = prev.find(opt.listNodeName).last();
// check if depth limit has reached
depth = this.placeEl.parents(opt.listNodeName).length;
if (depth + this.dragDepth <= opt.maxDepth) {
// create new sub-level if one doesn't exist
if (!list.length) {
list = $('<' + opt.listNodeName + '/>').addClass(opt.listClass);
list.append(this.placeEl);
prev.append(list);
this.setParent(prev);
} else {
// else append to next level up
list = prev.children(opt.listNodeName).last();
list.append(this.placeEl);
}
}
}
// decrease horizontal level
if (mouse.distX < 0) {
// we can't decrease a level if an item preceeds the current one
next = this.placeEl.next(opt.itemNodeName);
if (!next.length) {
parent = this.placeEl.parent();
this.placeEl.closest(opt.itemNodeName).after(this.placeEl);
if (!parent.children().length) {
this.unsetParent(parent.parent());
}
}
}
}
var isEmpty = false;
// find list item under cursor
if (!hasPointerEvents) {
this.dragEl[0].style.visibility = 'hidden';
}
this.pointEl = $(document.elementFromPoint(e.pageX - document.body.scrollLeft, e.pageY - (window.pageYOffset || document.documentElement.scrollTop)));
if (!hasPointerEvents) {
this.dragEl[0].style.visibility = 'visible';
}
if (this.pointEl.hasClass(opt.handleClass)) {
this.pointEl = this.pointEl.parent(opt.itemNodeName);
}
if (this.pointEl.hasClass(opt.emptyClass)) {
isEmpty = true;
}
else if (!this.pointEl.length || !this.pointEl.hasClass(opt.itemClass)) {
return;
}
// find parent list of item under cursor
var pointElRoot = this.pointEl.closest('.' + opt.rootClass),
isNewRoot = this.dragRootEl.data('nestable-id') !== pointElRoot.data('nestable-id');
/**
* move vertical
*/
if (!mouse.dirAx || isNewRoot || isEmpty) {
// check if groups match if dragging over new root
if (isNewRoot && opt.group !== pointElRoot.data('nestable-group')) {
return;
}
// check depth limit
depth = this.dragDepth - 1 + this.pointEl.parents(opt.listNodeName).length;
if (depth > opt.maxDepth) {
return;
}
var before = e.pageY < (this.pointEl.offset().top + this.pointEl.height() / 2);
parent = this.placeEl.parent();
// if empty create new list to replace empty placeholder
if (isEmpty) {
list = $(document.createElement(opt.listNodeName)).addClass(opt.listClass);
list.append(this.placeEl);
this.pointEl.replaceWith(list);
}
else if (before) {
this.pointEl.before(this.placeEl);
}
else {
this.pointEl.after(this.placeEl);
}
if (!parent.children().length) {
this.unsetParent(parent.parent());
}
if (!this.dragRootEl.find(opt.itemNodeName).length) {
this.dragRootEl.append('<div class="' + opt.emptyClass + '"/>');
}
// parent root list has changed
if (isNewRoot) {
this.dragRootEl = pointElRoot;
this.hasNewRoot = this.el[0] !== this.dragRootEl[0];
}
}
}
};
$.fn.nestable = function(params)
{
var lists = this,
retval = this;
lists.each(function()
{
var plugin = $(this).data("nestable");
if (!plugin) {
$(this).data("nestable", new Plugin(this, params));
$(this).data("nestable-id", new Date().getTime());
} else {
if (typeof params === 'string' && typeof plugin[params] === 'function') {
retval = plugin[params]();
}
}
});
return retval || lists;
};
})(window.jQuery || window.Zepto, window, document);

10337
static/js/lib/ace/uncompressed/jquery1x.js vendored Normal file

File diff suppressed because it is too large Load Diff