@@ -35,3 +35,15 @@ div.appframe-toolbar { | |||
border-bottom: 1px solid #ccc; | |||
} | |||
div.appframe-toolbar .label { | |||
margin: 2px 2px; | |||
} | |||
div.appframe-toolbar input, div.appframe-toolbar select { | |||
font-size: 80%; | |||
margin: 2px 2px; | |||
} | |||
div.appframe-toolbar button { | |||
padding: 3px 7px !important; | |||
} | |||
@@ -57,7 +57,7 @@ $(ele).css('-box-shadow','0px 0px '+spread+'px rgba(0,0,0,0.3);')};(function($){ | |||
this.selectedIndex=0;return $(this);} | |||
$.fn.set_working=function(){var ele=this.get(0);$(ele).attr('disabled','disabled');if(ele.loading_img){$(ele.loading_img).toggle(true);}else{ele.loading_img=$('<img src="images/lib/ui/button-load.gif" \ | |||
style="margin-left: 4px; margin-bottom: -2px; display: inline;" />').insertAfter(ele);}} | |||
$.fn.done_working=function(){var ele=this.get(0);$(ele).attr('disabled',null);if(ele.loading_img){$(ele.loading_img).toggle(false);};}})(jQuery); | |||
$.fn.done_working=function(){var ele=this.get(0);$(ele).attr('disabled',null);if(ele.loading_img){$(ele.loading_img).toggle(false);};}})(jQuery);wn.to_csv=function(data){var res=[];$.each(data,function(i,row){row=$.map(row,function(col){return typeof(col)==="string"?('"'+col.replace(/"/g,'\"')+'"'):col;});res.push(row.join(","));});return res.join("\n");} | |||
/* | |||
* lib/js/wn/model.js | |||
*/ | |||
@@ -234,8 +234,9 @@ $(page).bind('show',onshow);if(onshow) | |||
$(page).bind('hide',onhide);page.label=label;wn.pages[label]=page;return page;},change_to:function(label){if(this.page&&this.page.label==label){return;} | |||
var me=this;if(label.tagName){var page=label;}else{var page=wn.pages[label];} | |||
if(!page){console.log('Page not found '+label);return;} | |||
if(this.page){$(this.page).toggle(false);$(this.page).trigger('hide');} | |||
this.page=page;$(this.page).fadeIn();this.page._route=window.location.hash;document.title=this.page.label;$(this.page).trigger('show');scroll(0,0);return this.page;}});wn.views.add_module_btn=function(parent,module){$(parent).append(repl('<span class="label" style="margin-right: 8px; cursor: pointer;"\ | |||
if(this.page&&this.page!=page){$(this.page).toggle(false);$(this.page).trigger('hide');} | |||
if(!this.page||this.page!=page){this.page=page;$(this.page).fadeIn();} | |||
this.page._route=window.location.hash;document.title=this.page.label;$(this.page).trigger('show');scroll(0,0);return this.page;}});wn.views.add_module_btn=function(parent,module){$(parent).append(repl('<span class="label" style="margin-right: 8px; cursor: pointer;"\ | |||
onclick="wn.set_route(\'%(module_small)s-home\')">\ | |||
<i class="icon-home icon-white"></i> %(module)s Home\ | |||
</span>',{module:module,module_small:module.toLowerCase()}));} | |||
@@ -271,8 +272,7 @@ msgprint(r.server_messages);} | |||
if(r.exc){r.exc=JSON.parse(r.exc);if(r.exc instanceof Array){$.each(r.exc,function(i,v){if(v)console.log(v);})}else{console.log(r.exc);}};if(r['403']){wn.container.change_to('403');} | |||
if(r.docs){LocalDB.sync(r.docs);}} | |||
wn.request.call=function(opts){wn.request.prepare(opts);var ajax_args={url:opts.url||wn.request.url,data:opts.args,type:opts.type||'POST',dataType:opts.dataType||'json',success:function(r,xhr){wn.request.cleanup(opts,r);opts.success&&opts.success(r,xhr.responseText);},error:function(xhr,textStatus){wn.request.cleanup(opts,{});show_alert('Unable to complete request: '+textStatus) | |||
opts.error&&opts.error(xhr)}};if(opts.progress_bar){var interval=null;$.extend(ajax_args,{xhr:function(){var xhr=jQuery.ajaxSettings.xhr();interval=setInterval(function(){if(xhr.readyState>2){var total=parseInt(xhr.getResponseHeader('Original-Length')||0)||parseInt(xhr.getResponseHeader('Content-Length'));var completed=parseInt(xhr.responseText.length);var percent=(100.0/total*completed).toFixed(2) | |||
opts.progress_bar.css('width',(percent<10?10:percent)+'%');}},50);wn.last_xhr=xhr;return xhr;},complete:function(){opts.progress_bar.css('width','100%');clearInterval(interval);}})} | |||
opts.error&&opts.error(xhr)}};if(opts.progress_bar){var interval=null;$.extend(ajax_args,{xhr:function(){var xhr=jQuery.ajaxSettings.xhr();interval=setInterval(function(){if(xhr.readyState>2){var total=parseInt(xhr.getResponseHeader('Original-Length')||0)||parseInt(xhr.getResponseHeader('Content-Length'));var completed=parseInt(xhr.responseText.length);var percent=(100.0/total*completed).toFixed(2);opts.progress_bar.css('width',(percent<10?10:percent)+'%');}},50);wn.last_xhr=xhr;return xhr;},complete:function(){opts.progress_bar.css('width','100%');clearInterval(interval);}})} | |||
$.ajax(ajax_args);} | |||
wn.call=function(opts){var args=$.extend({},opts.args) | |||
if(opts.module&&opts.page){args.cmd=opts.module+'.page.'+opts.page+'.'+opts.page+'.'+opts.method}else if(opts.method){args.cmd=opts.method;} | |||
@@ -58,6 +58,7 @@ function msgprint(msg, title) { | |||
msg_dialog.msg_area.append(msg); | |||
msg_dialog.show(); | |||
return msg_dialog; | |||
} | |||
// Floating Message | |||
@@ -0,0 +1,3 @@ | |||
/* Downloadify 0.2 (c) 2009 by Douglas Neiner. Licensed under the MIT license */ | |||
/* See http://github.com/dcneiner/Downloadify for license and more info */ | |||
(function(){Downloadify=window.Downloadify={queue:{},uid:new Date().getTime(),getTextForSave:function(a){var b=Downloadify.queue[a];if(b)return b.getData();return""},getFileNameForSave:function(a){var b=Downloadify.queue[a];if(b)return b.getFilename();return""},getDataTypeForSave:function(a){var b=Downloadify.queue[a];if(b)return b.getDataType();return""},saveComplete:function(a){var b=Downloadify.queue[a];if(b)b.complete();return true},saveCancel:function(a){var b=Downloadify.queue[a];if(b)b.cancel();return true},saveError:function(a){var b=Downloadify.queue[a];if(b)b.error();return true},addToQueue:function(a){Downloadify.queue[a.queue_name]=a},getUID:function(a){if(a.id=="")a.id='downloadify_'+Downloadify.uid++;return a.id}};Downloadify.create=function(a,b){var c=(typeof(a)=="string"?document.getElementById(a):a);return new Downloadify.Container(c,b)};Downloadify.Container=function(d,e){var f=this;f.el=d;f.enabled=true;f.dataCallback=null;f.filenameCallback=null;f.data=null;f.filename=null;var g=function(){f.options=e;if(!f.options.append)f.el.innerHTML="";f.flashContainer=document.createElement('span');f.el.appendChild(f.flashContainer);f.queue_name=Downloadify.getUID(f.flashContainer);if(typeof(f.options.filename)==="function")f.filenameCallback=f.options.filename;else if(f.options.filename)f.filename=f.options.filename;if(typeof(f.options.data)==="function")f.dataCallback=f.options.data;else if(f.options.data)f.data=f.options.data;var a={queue_name:f.queue_name,width:f.options.width,height:f.options.height};var b={allowScriptAccess:'always'};var c={id:f.flashContainer.id,name:f.flashContainer.id};if(f.options.enabled===false)f.enabled=false;if(f.options.transparent===true)b.wmode="transparent";if(f.options.downloadImage)a.downloadImage=f.options.downloadImage;swfobject.embedSWF(f.options.swf,f.flashContainer.id,f.options.width,f.options.height,"10",null,a,b,c);Downloadify.addToQueue(f)};f.enable=function(){var a=document.getElementById(f.flashContainer.id);a.setEnabled(true);f.enabled=true};f.disable=function(){var a=document.getElementById(f.flashContainer.id);a.setEnabled(false);f.enabled=false};f.getData=function(){if(!f.enabled)return"";if(f.dataCallback)return f.dataCallback();else if(f.data)return f.data;else return""};f.getFilename=function(){if(f.filenameCallback)return f.filenameCallback();else if(f.filename)return f.filename;else return""};f.getDataType=function(){if(f.options.dataType)return f.options.dataType;return"string"};f.complete=function(){if(typeof(f.options.onComplete)==="function")f.options.onComplete()};f.cancel=function(){if(typeof(f.options.onCancel)==="function")f.options.onCancel()};f.error=function(){if(typeof(f.options.onError)==="function")f.options.onError()};g()};Downloadify.defaultOptions={swf:'media/downloadify.swf',downloadImage:'images/download.png',width:100,height:30,transparent:true,append:false,dataType:"string"}})();if(typeof(jQuery)!="undefined"){(function($){$.fn.downloadify=function(b){return this.each(function(){b=$.extend({},Downloadify.defaultOptions,b);var a=Downloadify.create(this,b);$(this).data('Downloadify',a)})}})(jQuery)};if(typeof(MooTools)!='undefined'){Element.implement({downloadify:function(a){a=$merge(Downloadify.defaultOptions,a);return this.store('Downloadify',Downloadify.create(this,a))}})}; |
@@ -161,3 +161,14 @@ wn.dom.set_box_shadow = function(ele, spread) { | |||
}; | |||
} | |||
})(jQuery); | |||
wn.to_csv = function(data) { | |||
var res = []; | |||
$.each(data, function(i, row) { | |||
row = $.map(row, function(col) { | |||
return typeof(col)==="string" ? ('"' + col.replace(/"/g, '\"') + '"') : col; | |||
}); | |||
res.push(row.join(",")); | |||
}); | |||
return res.join("\n"); | |||
} |
@@ -119,7 +119,7 @@ wn.request.call = function(opts) { | |||
var total = parseInt(xhr.getResponseHeader('Original-Length') || 0) || | |||
parseInt(xhr.getResponseHeader('Content-Length')); | |||
var completed = parseInt(xhr.responseText.length); | |||
var percent = (100.0 / total * completed).toFixed(2) | |||
var percent = (100.0 / total * completed).toFixed(2); | |||
opts.progress_bar.css('width', (percent < 10 ? 10 : percent) + '%'); | |||
} | |||
}, 50); | |||
@@ -64,15 +64,20 @@ wn.ui.AppFrame = Class.extend({ | |||
this.toolbar = this.$w.find('.appframe-toolbar'); | |||
}, | |||
add_label: function(label) { | |||
return $("<span style='margin: 2px 4px;'>"+label+" </span>").appendTo(this.toolbar); | |||
return $("<span class='label'>"+label+" </span>").appendTo(this.toolbar); | |||
}, | |||
add_select: function(label, options) { | |||
this.add_toolbar(); | |||
return $("<select style='width: 160px; margin: 2px 4px;'>").add_options(options).appendTo(this.toolbar); | |||
return $("<select style='width: 160px;'>").add_options(options).appendTo(this.toolbar); | |||
}, | |||
add_data: function(label) { | |||
this.add_toolbar(); | |||
return $("<input style='width: 100px;' placeholder='"+ label +"'>") | |||
.appendTo(this.toolbar); | |||
}, | |||
add_date: function(label, date) { | |||
this.add_toolbar(); | |||
return $("<input style='width: 80px; margin: 2px 4px;'>").datepicker({ | |||
return $("<input style='width: 80px;'>").datepicker({ | |||
dateFormat: sys_defaults.date_format.replace("yyyy", "yy"), | |||
changeYear: true, | |||
}).val(dateutil.str_to_user(date) || "").appendTo(this.toolbar); | |||
@@ -25,6 +25,7 @@ wn.views.Container = Class.extend({ | |||
change_to: function(label) { | |||
if(this.page && this.page.label == label) { | |||
// don't trigger double events | |||
//$(this.page).trigger('show'); | |||
return; | |||
} | |||
@@ -41,14 +42,16 @@ wn.views.Container = Class.extend({ | |||
} | |||
// hide current | |||
if(this.page) { | |||
if(this.page && this.page != page) { | |||
$(this.page).toggle(false); | |||
$(this.page).trigger('hide'); | |||
} | |||
// show new | |||
this.page = page; | |||
$(this.page).fadeIn(); | |||
if(!this.page || this.page != page) { | |||
this.page = page; | |||
$(this.page).fadeIn(); | |||
} | |||
this.page._route = window.location.hash; | |||
document.title = this.page.label; | |||
$(this.page).trigger('show'); | |||
@@ -99,6 +99,36 @@ wn.views.GridReport = Class.extend({ | |||
<div class="bar" style="width: 10%"></div></div>') | |||
.appendTo(this.wrapper); | |||
}, | |||
make_grid_wrapper: function() { | |||
$('<div style="text-align: right;"> \ | |||
<a href="#" class="grid-report-print"><i class="icon icon-print"></i> Print</a> \ | |||
<span style="color: #aaa; margin: 0px 10px;"> | </span> \ | |||
<a href="#" class="grid-report-export"><i class="icon icon-download-alt"></i> Export</a> \ | |||
</div>').appendTo(this.wrapper); | |||
this.wrapper.find(".grid-report-export").click(function() { return me.export(); }); | |||
this.grid_wrapper = $("<div style='height: 500px; border: 1px solid #aaa; \ | |||
background-color: #eee; margin-top: 15px;'>") | |||
.appendTo(this.wrapper); | |||
this.id = wn.dom.set_unique_id(this.grid_wrapper.get(0)); | |||
var me = this; | |||
// bind show event to reset cur_report_grid | |||
// and refresh filters from url | |||
// this must be called after init | |||
// because "wn.container.page" will only be set | |||
// once "load" event is over. | |||
$(wn.container.page).bind('show', function() { | |||
// reapply filters on show | |||
wn.cur_grid_report = me; | |||
me.apply_filters_from_route(); | |||
me.refresh(); | |||
}); | |||
this.apply_filters_from_route(); | |||
}, | |||
load_filters: function(callback) { | |||
// override | |||
callback(); | |||
@@ -109,13 +139,21 @@ wn.views.GridReport = Class.extend({ | |||
v.fieldname = v.fieldname || v.label.replace(/ /g, '_').toLowerCase(); | |||
var input = null; | |||
if(v.fieldtype=='Select') { | |||
input = me.appframe.add_select(v.label, ["Select "+v.options]); | |||
input = me.appframe.add_select(v.label, [v.default_value]); | |||
} else if(v.fieldtype=='Button') { | |||
input = me.appframe.add_button(v.label); | |||
if(v.icon) { | |||
$('<i class="icon '+ v.icon +'"></i>').prependTo(input); | |||
} | |||
} else if(v.fieldtype=='Date') { | |||
input = me.appframe.add_date(v.label); | |||
} else if(v.fieldtype=='Label') { | |||
input = me.appframe.add_label(v.label); | |||
} else if(v.fieldtype=='Data') { | |||
input = me.appframe.add_data(v.label); | |||
} | |||
if(v.cssClass) { | |||
input && input.addClass(v.cssClass); | |||
} | |||
input && (input.get(0).opts = v); | |||
me.filter_inputs[v.fieldname] = input; | |||
@@ -131,15 +169,35 @@ wn.views.GridReport = Class.extend({ | |||
wn.dom.set_style('.slick-cell { font-size: 12px; }'); | |||
}, | |||
refresh: function() { | |||
this.prepare_data(); | |||
this.render(); | |||
}, | |||
apply_filters_from_route: function() { | |||
var hash = window.location.hash; | |||
var me = this; | |||
if(hash.indexOf('/') != -1) { | |||
$.each(hash.split('/').splice(1).join('/').split('&'), function(i, f) { | |||
var f = f.split("="); | |||
me.filter_inputs[f[0]].val(decodeURIComponent(f[1])); | |||
}); | |||
} | |||
}, | |||
set_route: function() { | |||
wn.set_route(wn.container.page.page_name, $.map(this.filter_inputs, function(v) { | |||
var val = v.val(); | |||
var opts = v.get(0).opts; | |||
if(val && val != opts.default_value) | |||
return encodeURIComponent(opts.fieldname) | |||
+ '=' + encodeURIComponent(val); | |||
}).join('&')) | |||
}, | |||
render: function() { | |||
// new slick grid | |||
this.waiting.toggle(false); | |||
this.grid_wrapper = $("<div style='height: 500px; border: 1px solid #aaa;'>") | |||
.appendTo(this.wrapper); | |||
this.id = wn.dom.set_unique_id(this.grid_wrapper.get(0)); | |||
if(!this.grid_wrapper) this.make_grid_wrapper(); | |||
this.apply_link_formatters(); | |||
this.prepare_data(); | |||
this.grid = new Slick.Grid("#"+this.id, this.dataView, this.columns, this.options); | |||
@@ -162,11 +220,58 @@ wn.views.GridReport = Class.extend({ | |||
this.dataView.setFilter(this.dataview_filter); | |||
this.dataView.endUpdate(); | |||
}, | |||
export: function() { | |||
var me = this; | |||
var res = [$.map(this.columns, function(v) { return v.name; })]; | |||
var col_map = $.map(this.columns, function(v) { return v.field; }); | |||
for (var i=0, len=this.dataView.getLength(); i<len; i++) { | |||
var d = this.dataView.getItem(i); | |||
var row = $.map(col_map, function(col) { | |||
return d[col]; | |||
}); | |||
res.push(row); | |||
} | |||
wn.require("js/lib/downloadify/downloadify.min.js"); | |||
wn.require("js/lib/downloadify/swfobject.js"); | |||
var id = wn.dom.set_unique_id(); | |||
var msgobj = msgprint('<p id="'+ id +'">You must have Flash 10 installed to download this file.</p>'); | |||
Downloadify.create(id ,{ | |||
filename: function(){ | |||
return me.title + '.csv'; | |||
}, | |||
data: function(){ | |||
return wn.to_csv(res); | |||
}, | |||
swf: 'js/lib/downloadify/downloadify.swf', | |||
downloadImage: 'js/lib/downloadify/download.png', | |||
onComplete: function(){ msgobj.hide(); }, | |||
onCancel: function(){ msgobj.hide(); }, | |||
onError: function(){ msgobj.hide(); }, | |||
width: 100, | |||
height: 30, | |||
transparent: true, | |||
append: false | |||
}); | |||
return false; | |||
}, | |||
options: { | |||
editable: false, | |||
enableColumnReorder: false | |||
}, | |||
dataview_filter: function(item) { | |||
var filters = wn.cur_grid_report.filter_inputs; | |||
for (i in filters) { | |||
var filter = filters[i].get(0); | |||
if(filter.opts.filter && !filter.opts.filter($(filter).val(), item, filter.opts)) { | |||
return false; | |||
} | |||
} | |||
return true; | |||
}, | |||
date_formatter: function(row, cell, value, columnDef, dataContext) { | |||
@@ -174,5 +279,42 @@ wn.views.GridReport = Class.extend({ | |||
}, | |||
currency_formatter: function(row, cell, value, columnDef, dataContext) { | |||
return "<div style='text-align: right;'>" + fmt_money(value) + "</div>"; | |||
}, | |||
text_formatter: function(row, cell, value, columnDef, dataContext) { | |||
return "<span title='" + value +"'>" + value + "</div>"; | |||
}, | |||
apply_link_formatters: function() { | |||
var me = this; | |||
$.each(this.columns, function(i, col) { | |||
if(col.link_formatter) { | |||
col.formatter = function(row, cell, value, columnDef, dataContext) { | |||
// added link and open button to links | |||
// link_formatter must have | |||
// filter_input, open_btn (true / false), doctype (will be eval'd) | |||
// make link to add a filter | |||
var link_formatter = wn.cur_grid_report.columns[cell].link_formatter; | |||
var html = repl('<a href="#" \ | |||
onclick="wn.cur_grid_report.filter_inputs.%(col_name)s.val(\'%(value)s\'); \ | |||
wn.cur_grid_report.set_route(); return false;">\ | |||
%(value)s</a>', { | |||
value: value, | |||
col_name: link_formatter.filter_input, | |||
page_name: wn.container.page.page_name | |||
}) | |||
// make icon to open form | |||
if(link_formatter.open_btn) { | |||
html += repl(' <i class="icon icon-share" style="cursor: pointer;"\ | |||
onclick="wn.set_route(\'Form\', \'%(doctype)s\', \'%(value)s\');">\ | |||
</i>', { | |||
value: value, | |||
doctype: eval(link_formatter.doctype) | |||
}); | |||
} | |||
return html; | |||
} | |||
} | |||
}) | |||
} | |||
}) |