mirror of
https://github.com/openMF/community-app.git
synced 2026-02-06 13:51:55 +00:00
using less for mifos custom styles. using require css and less plugins to dynamically load styles
This commit is contained in:
parent
52346a28c3
commit
e1582b10cc
@ -4,10 +4,6 @@
|
||||
<meta charset="utf-8">
|
||||
<title>MifosX prototype</title>
|
||||
<style>[data-ng-cloak] { display: none !important; }</style>
|
||||
<link rel="stylesheet" href="stylesheets/skeleton/base.css">
|
||||
<link rel="stylesheet" href="stylesheets/skeleton/skeleton.css">
|
||||
<link rel="stylesheet" href="stylesheets/skeleton/layout.css">
|
||||
<link rel="stylesheet" href="stylesheets/mifosX.css">
|
||||
</head>
|
||||
<body data-ng-cloak data-ng-controller="MainController">
|
||||
<div class="container">
|
||||
|
||||
42
js/loader.js
42
js/loader.js
@ -6,35 +6,37 @@
|
||||
'angular-mocks': '../lib/angular/angular-mocks',
|
||||
'underscore': '../lib/underscore/underscore',
|
||||
'webstorage': '../lib/angular-webstorage',
|
||||
'test': '../test/functional'
|
||||
'require-css': '../lib/require-css',
|
||||
'require-less': '../lib/require-less',
|
||||
'styles': '../stylesheets',
|
||||
'test': '../test/functional',
|
||||
},
|
||||
shim: {
|
||||
'angular': {
|
||||
exports: 'angular'
|
||||
},
|
||||
'angular-resource': {
|
||||
deps: ['angular']
|
||||
},
|
||||
'webstorage': {
|
||||
deps: ['angular']
|
||||
},
|
||||
'angular': { exports: 'angular' },
|
||||
'angular-resource': { deps: ['angular'] },
|
||||
'angular-mocks': { deps: ['angular'] },
|
||||
'webstorage': { deps: ['angular'] },
|
||||
'mifosX': {
|
||||
deps: ['angular', 'angular-resource', 'webstorage'],
|
||||
exports: 'mifosX'
|
||||
}
|
||||
},
|
||||
packages: [
|
||||
{
|
||||
name: 'css',
|
||||
location: '../lib/require-css',
|
||||
main: 'css'
|
||||
},
|
||||
{
|
||||
name: 'less',
|
||||
location: '../lib/require-less',
|
||||
main: 'less'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
require(['mifosXComponents', 'mifosX', 'underscore'], function(components) {
|
||||
var dependencies = _.reduce(_.keys(components), function(list, group) {
|
||||
return list.concat(_.map(components[group], function(name) { return group + "/" + name; }));
|
||||
}, [
|
||||
'test/testInitializer',
|
||||
'routes',
|
||||
'webstorage-configuration'
|
||||
]);
|
||||
|
||||
require(dependencies, function(testMode) {
|
||||
require(['mifosXComponents', 'mifosXStyles'], function() {
|
||||
require(['test/testInitializer'], function(testMode) {
|
||||
if (!testMode) {
|
||||
angular.bootstrap(document, ["MifosX_Application"]);
|
||||
}
|
||||
|
||||
@ -1,17 +1,26 @@
|
||||
define({
|
||||
models: [
|
||||
'User',
|
||||
'roleMap'
|
||||
],
|
||||
controllers: [
|
||||
'MainController',
|
||||
'LoginFormController'
|
||||
],
|
||||
services: [
|
||||
'ResourceFactoryProvider',
|
||||
'HttpServiceProvider',
|
||||
'AuthenticationService',
|
||||
'SessionManager'
|
||||
],
|
||||
directives: []
|
||||
define(['underscore', 'mifosX'], function() {
|
||||
var components = {
|
||||
models: [
|
||||
'User',
|
||||
'roleMap'
|
||||
],
|
||||
controllers: [
|
||||
'MainController',
|
||||
'LoginFormController'
|
||||
],
|
||||
services: [
|
||||
'ResourceFactoryProvider',
|
||||
'HttpServiceProvider',
|
||||
'AuthenticationService',
|
||||
'SessionManager'
|
||||
],
|
||||
directives: []
|
||||
};
|
||||
|
||||
require(_.reduce(_.keys(components), function(list, group) {
|
||||
return list.concat(_.map(components[group], function(name) { return group + "/" + name; }));
|
||||
}, [
|
||||
'routes',
|
||||
'webstorage-configuration'
|
||||
]));
|
||||
});
|
||||
|
||||
16
js/mifosXStyles.js
Normal file
16
js/mifosXStyles.js
Normal file
@ -0,0 +1,16 @@
|
||||
define(['underscore'], function() {
|
||||
var styles = {
|
||||
css: [
|
||||
'skeleton/base',
|
||||
'skeleton/skeleton',
|
||||
'skeleton/layout'
|
||||
],
|
||||
less: [
|
||||
'mifosX'
|
||||
]
|
||||
};
|
||||
|
||||
require(_.reduce(_.keys(styles), function(list, pluginName) {
|
||||
return list.concat(_.map(styles[pluginName], function(stylename) { return pluginName + "!styles/" + stylename; }));
|
||||
}, []));
|
||||
});
|
||||
1
lib/require-css/.gitignore
vendored
Normal file
1
lib/require-css/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
example/www-built
|
||||
251
lib/require-css/css-builder.js
Normal file
251
lib/require-css/css-builder.js
Normal file
@ -0,0 +1,251 @@
|
||||
define(['require', './normalize'], function(req, normalize) {
|
||||
var nodePrint = function() {};
|
||||
if (requirejs.tools)
|
||||
requirejs.tools.useLib(function(req) {
|
||||
req(['node/print'], function(_nodePrint) {
|
||||
nodePrint = _nodePrint;
|
||||
}, function(){});
|
||||
});
|
||||
|
||||
var cssAPI = {};
|
||||
|
||||
function compress(css) {
|
||||
if (typeof process !== "undefined" && process.versions && !!process.versions.node && require.nodeRequire) {
|
||||
try {
|
||||
var csso = require.nodeRequire('csso');
|
||||
var csslen = css.length;
|
||||
css = csso.justDoIt(css);
|
||||
nodePrint('Compressed CSS output to ' + Math.round(css.length / csslen * 100) + '%.');
|
||||
return css;
|
||||
}
|
||||
catch(e) {
|
||||
nodePrint('Compression module not installed. Use "npm install csso -g" to enable.');
|
||||
return css;
|
||||
}
|
||||
}
|
||||
nodePrint('Compression not supported outside of nodejs environments.');
|
||||
return css;
|
||||
}
|
||||
|
||||
//load file code - stolen from text plugin
|
||||
function loadFile(path) {
|
||||
if (typeof process !== "undefined" && process.versions && !!process.versions.node && require.nodeRequire) {
|
||||
var fs = require.nodeRequire('fs');
|
||||
var file = fs.readFileSync(path, 'utf8');
|
||||
if (file.indexOf('\uFEFF') === 0)
|
||||
return file.substring(1);
|
||||
return file;
|
||||
}
|
||||
else {
|
||||
var file = new java.io.File(path),
|
||||
lineSeparator = java.lang.System.getProperty("line.separator"),
|
||||
input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), 'utf-8')),
|
||||
stringBuffer, line;
|
||||
try {
|
||||
stringBuffer = new java.lang.StringBuffer();
|
||||
line = input.readLine();
|
||||
if (line && line.length() && line.charAt(0) === 0xfeff)
|
||||
line = line.substring(1);
|
||||
stringBuffer.append(line);
|
||||
while ((line = input.readLine()) !== null) {
|
||||
stringBuffer.append(lineSeparator).append(line);
|
||||
}
|
||||
return String(stringBuffer.toString());
|
||||
}
|
||||
finally {
|
||||
input.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function saveFile(path, data) {
|
||||
if (typeof process !== "undefined" && process.versions && !!process.versions.node && require.nodeRequire) {
|
||||
var fs = require.nodeRequire('fs');
|
||||
fs.writeFileSync(path, data, 'utf8');
|
||||
}
|
||||
else {
|
||||
var content = new java.lang.String(data);
|
||||
var output = new java.io.BufferedWriter(new java.io.OutputStreamWriter(new java.io.FileOutputStream(path), 'utf-8'));
|
||||
|
||||
try {
|
||||
output.write(content, 0, content.length());
|
||||
output.flush();
|
||||
}
|
||||
finally {
|
||||
output.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//when adding to the link buffer, paths are normalised to the baseUrl
|
||||
//when removing from the link buffer, paths are normalised to the output file path
|
||||
function escape(content) {
|
||||
return content.replace(/(["'\\])/g, '\\$1')
|
||||
.replace(/[\f]/g, "\\f")
|
||||
.replace(/[\b]/g, "\\b")
|
||||
.replace(/[\n]/g, "\\n")
|
||||
.replace(/[\t]/g, "\\t")
|
||||
.replace(/[\r]/g, "\\r");
|
||||
}
|
||||
|
||||
// NB add @media query support for media imports
|
||||
var importRegEx = /@import\s*(url)?\s*(('([^']*)'|"([^"]*)")|\(('([^']*)'|"([^"]*)"|([^\)]*))\))\s*;?/g;
|
||||
|
||||
var loadCSSFile = function(fileUrl) {
|
||||
var css = loadFile(fileUrl);
|
||||
|
||||
// normalize the css (except import statements)
|
||||
css = normalize(css, fileUrl, baseUrl, cssBase);
|
||||
|
||||
// detect all import statements in the css and normalize
|
||||
var importUrls = [];
|
||||
var importIndex = [];
|
||||
var importLength = [];
|
||||
var match;
|
||||
while (match = importRegEx.exec(css)) {
|
||||
var importUrl = match[4] || match[5] || match[7] || match[8] || match[9];
|
||||
|
||||
// normalize import url
|
||||
if (importUrl.substr(importUrl.length - 5, 5) != '.less' && importUrl.substr(importUrl.length - 4, 4) != '.css')
|
||||
importUrl += '.css';
|
||||
|
||||
// contains a protocol
|
||||
if (importUrl.match(/:\/\//))
|
||||
continue;
|
||||
|
||||
// relative to css base
|
||||
if (importUrl.substr(0, 1) == '/' && cssBase)
|
||||
importUrl = cssBase + importUrl;
|
||||
else
|
||||
importUrl = baseUrl + importUrl;
|
||||
|
||||
importUrls.push(importUrl);
|
||||
importIndex.push(importRegEx.lastIndex - match[0].length);
|
||||
importLength.push(match[0].length);
|
||||
}
|
||||
|
||||
// load the import stylesheets and substitute into the css
|
||||
for (var i = 0; i < importUrls.length; i++)
|
||||
(function(i) {
|
||||
var importCSS = loadCSSFile(importUrls[i]);
|
||||
css = css.substr(0, importIndex[i]) + importCSS + css.substr(importIndex[i] + importLength[i]);
|
||||
var lenDiff = importCSS.length - importLength[i];
|
||||
for (var j = i + 1; j < importUrls.length; j++)
|
||||
importIndex[j] += lenDiff;
|
||||
})(i);
|
||||
|
||||
return css;
|
||||
}
|
||||
|
||||
|
||||
var baseUrl;
|
||||
var cssBase;
|
||||
var curModule;
|
||||
cssAPI.load = function(name, req, load, config, parse) {
|
||||
if (!baseUrl)
|
||||
baseUrl = config.baseUrl;
|
||||
|
||||
if (!cssBase)
|
||||
cssBase = config.cssBase;
|
||||
|
||||
if (config.modules) {
|
||||
//run through the module list - the first one without a layer set is the current layer we are in
|
||||
//allows to track the current layer number for layer-specific config
|
||||
for (var i = 0; i < config.modules.length; i++)
|
||||
if (config.modules[i].layer === undefined) {
|
||||
curModule = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//store config
|
||||
cssAPI.config = cssAPI.config || config;
|
||||
|
||||
name += !parse ? '.css' : '.less';
|
||||
|
||||
var fileUrl = req.toUrl(name);
|
||||
|
||||
//external URLS don't get added (just like JS requires)
|
||||
if (fileUrl.substr(0, 7) == 'http://' || fileUrl.substr(0, 8) == 'https://')
|
||||
return;
|
||||
|
||||
//add to the buffer
|
||||
_cssBuffer[name] = loadCSSFile(fileUrl);
|
||||
|
||||
// parse if necessary
|
||||
if (parse)
|
||||
_cssBuffer[name] = parse(_cssBuffer[name]);
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
cssAPI.normalize = function(name, normalize) {
|
||||
if (name.substr(name.length - 4, 4) == '.css')
|
||||
name = name.substr(0, name.length - 4);
|
||||
return normalize(name);
|
||||
}
|
||||
|
||||
//list of cssIds included in this layer
|
||||
var _layerBuffer = [];
|
||||
var _cssBuffer = [];
|
||||
cssAPI.write = function(pluginName, moduleName, write, parse) {
|
||||
//external URLS don't get added (just like JS requires)
|
||||
if (moduleName.substr(0, 7) == 'http://' || moduleName.substr(0, 8) == 'https://')
|
||||
return;
|
||||
|
||||
var resourceName = moduleName + (!parse ? '.css' : '.less');
|
||||
_layerBuffer.push(_cssBuffer[resourceName]);
|
||||
|
||||
var separateCSS = false;
|
||||
if (cssAPI.config.separateCSS)
|
||||
separateCSS = true;
|
||||
if (typeof curModule == 'number' && cssAPI.config.modules[curModule].separateCSS !== undefined)
|
||||
separateCSS = cssAPI.config.modules[curModule].separateCSS;
|
||||
if (separateCSS)
|
||||
write.asModule(pluginName + '!' + moduleName, 'define(function(){})');
|
||||
else
|
||||
write("requirejs.s.contexts._.nextTick = function(f){f()}; require(['css'], function(css) { css.addBuffer('" + resourceName + "'); }); requirejs.s.contexts._.nextTick = requirejs.nextTick;");
|
||||
}
|
||||
|
||||
cssAPI.onLayerEnd = function(write, data, parser) {
|
||||
firstWrite = true;
|
||||
//separateCSS parameter set either globally or as a layer setting
|
||||
var separateCSS = false;
|
||||
if (cssAPI.config.separateCSS)
|
||||
separateCSS = true;
|
||||
if (typeof curModule == 'number' && cssAPI.config.modules[curModule].separateCSS !== undefined)
|
||||
separateCSS = cssAPI.config.modules[curModule].separateCSS;
|
||||
curModule = null;
|
||||
|
||||
//calculate layer css
|
||||
var css = _layerBuffer.join('');
|
||||
|
||||
if (separateCSS) {
|
||||
nodePrint('Writing CSS! file: ' + data.name + '\n');
|
||||
|
||||
//calculate the css output path for this layer
|
||||
var path = this.config.appDir ? this.config.baseUrl + data.name + '.css' : cssAPI.config.out.replace(/\.js$/, '.css');
|
||||
|
||||
//renormalize the css to the output path
|
||||
var output = compress(normalize(css, baseUrl, path));
|
||||
|
||||
saveFile(path, output);
|
||||
}
|
||||
else {
|
||||
if (css == '')
|
||||
return;
|
||||
//write the injection and layer index into the layer
|
||||
//prepare the css
|
||||
css = escape(compress(css));
|
||||
|
||||
//the code below overrides async require functionality to ensure instant buffer injection
|
||||
write("requirejs.s.contexts._.nextTick = function(f){f()}; require(['css'], function(css) { css.setBuffer('" + css + (parser ? "', true" : "'") + "); }); requirejs.s.contexts._.nextTick = requirejs.nextTick; ");
|
||||
}
|
||||
|
||||
//clear layer buffer for next layer
|
||||
_layerBuffer = [];
|
||||
}
|
||||
|
||||
return cssAPI;
|
||||
});
|
||||
435
lib/require-css/css.js
Normal file
435
lib/require-css/css.js
Normal file
@ -0,0 +1,435 @@
|
||||
/*
|
||||
* Require-CSS RequireJS css! loader plugin
|
||||
* Guy Bedford 2013
|
||||
* MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* Usage:
|
||||
* require(['css!./mycssFile']);
|
||||
*
|
||||
* NB leave out the '.css' extension.
|
||||
*
|
||||
* - Fully supports cross origin CSS loading
|
||||
* - Works with builds
|
||||
*
|
||||
* Tested and working in (up to latest versions as of March 2013):
|
||||
* Android
|
||||
* iOS 6
|
||||
* IE 6 - 10
|
||||
* Chome 3 - 26
|
||||
* Firefox 3.5 - 19
|
||||
* Opera 10 - 12
|
||||
*
|
||||
* browserling.com used for virtual testing environment
|
||||
*
|
||||
* Credit to B Cavalier & J Hann for the elegant IE 6 - 9 hack.
|
||||
*
|
||||
* Sources that helped along the way:
|
||||
* - https://developer.mozilla.org/en-US/docs/Browser_detection_using_the_user_agent
|
||||
* - http://www.phpied.com/when-is-a-stylesheet-really-loaded/
|
||||
* - https://github.com/cujojs/curl/blob/master/src/curl/plugin/css.js
|
||||
*
|
||||
*/
|
||||
|
||||
define(['./normalize'], function(normalize) {
|
||||
function indexOf(a, e) { for (var i=0, l=a.length; i < l; i++) if (a[i] === e) return i; return -1 }
|
||||
|
||||
if (typeof window == 'undefined')
|
||||
return { load: function(n, r, load){ load() } };
|
||||
|
||||
// set to true to enable test prompts for device testing
|
||||
var testing = false;
|
||||
|
||||
var head = document.getElementsByTagName('head')[0];
|
||||
|
||||
var engine = window.navigator.userAgent.match(/Trident\/([^ ;]*)|AppleWebKit\/([^ ;]*)|Opera\/([^ ;]*)|rv\:([^ ;]*)(.*?)Gecko\/([^ ;]*)|MSIE\s([^ ;]*)/);
|
||||
var hackLinks = false;
|
||||
|
||||
if (!engine) {}
|
||||
else if (engine[1] || engine[7]) {
|
||||
hackLinks = parseInt(engine[1]) < 6 || parseInt(engine[7]) <= 9;
|
||||
engine = 'trident';
|
||||
}
|
||||
else if (engine[2]) {
|
||||
// unfortunately style querying still doesnt work with onload callback in webkit
|
||||
hackLinks = true;
|
||||
engine = 'webkit';
|
||||
}
|
||||
else if (engine[3]) {
|
||||
// engine = 'opera';
|
||||
}
|
||||
else if (engine[4]) {
|
||||
hackLinks = parseInt(engine[4]) < 18;
|
||||
engine = 'gecko';
|
||||
}
|
||||
else if (testing)
|
||||
alert('Engine detection failed');
|
||||
|
||||
//main api object
|
||||
var cssAPI = {};
|
||||
|
||||
var absUrlRegEx = /^\/|([^\:\/]*:)/;
|
||||
|
||||
cssAPI.pluginBuilder = './css-builder';
|
||||
|
||||
// used by layer builds to register their css buffers
|
||||
|
||||
// the current layer buffer items (from addBuffer)
|
||||
var curBuffer = [];
|
||||
|
||||
// the callbacks for buffer loads
|
||||
var onBufferLoad = {};
|
||||
|
||||
// the full list of resources in the buffer
|
||||
var bufferResources = [];
|
||||
|
||||
cssAPI.addBuffer = function(resourceId) {
|
||||
// just in case layer scripts are included twice, also check
|
||||
// against the previous buffers
|
||||
if (indexOf(curBuffer, resourceId) != -1)
|
||||
return;
|
||||
if (indexOf(bufferResources, resourceId) != -1)
|
||||
return;
|
||||
curBuffer.push(resourceId);
|
||||
bufferResources.push(resourceId);
|
||||
}
|
||||
cssAPI.setBuffer = function(css, isLess) {
|
||||
var pathname = window.location.pathname.split('/');
|
||||
pathname.pop();
|
||||
pathname = pathname.join('/') + '/';
|
||||
|
||||
var baseParts = require.toUrl('base_url').split('/');
|
||||
baseParts.pop();
|
||||
var baseUrl = baseParts.join('/') + '/';
|
||||
baseUrl = normalize.convertURIBase(baseUrl, pathname, '/');
|
||||
if (!baseUrl.match(absUrlRegEx))
|
||||
baseUrl = '/' + baseUrl;
|
||||
if (baseUrl.substr(baseUrl.length - 1, 1) != '/')
|
||||
baseUrl = baseUrl + '/';
|
||||
|
||||
cssAPI.inject(normalize(css, baseUrl, pathname));
|
||||
|
||||
// set up attach callback if registered
|
||||
// clear the current buffer for the next layer
|
||||
// (just the less or css part as we have two buffers in one effectively)
|
||||
for (var i = 0; i < curBuffer.length; i++) {
|
||||
// find the resources in the less or css buffer dependening which one this is
|
||||
if ((isLess && curBuffer[i].substr(curBuffer[i].length - 5, 5) == '.less') ||
|
||||
(!isLess && curBuffer[i].substr(curBuffer[i].length - 4, 4) == '.css')) {
|
||||
(function(resourceId) {
|
||||
// mark that the onBufferLoad is about to be called (set to true if not already a callback function)
|
||||
onBufferLoad[resourceId] = onBufferLoad[resourceId] || true;
|
||||
|
||||
// set a short timeout (as injection isn't instant in Chrome), then call the load
|
||||
setTimeout(function() {
|
||||
if (typeof onBufferLoad[resourceId] == 'function')
|
||||
onBufferLoad[resourceId]();
|
||||
// remove from onBufferLoad to indicate loaded
|
||||
delete onBufferLoad[resourceId];
|
||||
}, 7);
|
||||
})(curBuffer[i]);
|
||||
|
||||
// remove the current resource from the buffer
|
||||
curBuffer.splice(i--, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
cssAPI.attachBuffer = function(resourceId, load) {
|
||||
// attach can happen during buffer collecting, or between injection and callback
|
||||
// we assume it is not possible to attach multiple callbacks
|
||||
// requirejs plugin load function ensures this by queueing duplicate calls
|
||||
|
||||
// check if the resourceId is in the current buffer
|
||||
for (var i = 0; i < curBuffer.length; i++)
|
||||
if (curBuffer[i] == resourceId) {
|
||||
onBufferLoad[resourceId] = load;
|
||||
return true;
|
||||
}
|
||||
|
||||
// check if the resourceId is waiting for injection callback
|
||||
// (onBufferLoad === true is a shortcut indicator for this)
|
||||
if (onBufferLoad[resourceId] === true) {
|
||||
onBufferLoad[resourceId] = load;
|
||||
return true;
|
||||
}
|
||||
|
||||
// if it's in the full buffer list and not either of the above, its loaded already
|
||||
if (indexOf(bufferResources, resourceId) != -1) {
|
||||
load();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
var webkitLoadCheck = function(link, callback) {
|
||||
setTimeout(function() {
|
||||
for (var i = 0; i < document.styleSheets.length; i++) {
|
||||
var sheet = document.styleSheets[i];
|
||||
if (sheet.href == link.href)
|
||||
return callback();
|
||||
}
|
||||
webkitLoadCheck(link, callback);
|
||||
}, 10);
|
||||
}
|
||||
|
||||
var mozillaLoadCheck = function(style, callback) {
|
||||
setTimeout(function() {
|
||||
try {
|
||||
style.sheet.cssRules;
|
||||
return callback();
|
||||
} catch (e){}
|
||||
mozillaLoadCheck(style, callback);
|
||||
}, 10);
|
||||
}
|
||||
|
||||
// ie link detection, as adapted from https://github.com/cujojs/curl/blob/master/src/curl/plugin/css.js
|
||||
if (engine == 'trident' && hackLinks) {
|
||||
var ieStyles = [],
|
||||
ieQueue = [],
|
||||
ieStyleCnt = 0;
|
||||
var ieLoad = function(url, callback) {
|
||||
var style;
|
||||
ieQueue.push({
|
||||
url: url,
|
||||
cb: callback
|
||||
});
|
||||
style = ieStyles.shift();
|
||||
if (!style && ieStyleCnt++ < 12) {
|
||||
style = document.createElement('style');
|
||||
head.appendChild(style);
|
||||
}
|
||||
ieLoadNextImport(style);
|
||||
}
|
||||
var ieLoadNextImport = function(style) {
|
||||
var curImport = ieQueue.shift();
|
||||
if (!curImport) {
|
||||
style.onload = noop;
|
||||
ieStyles.push(style);
|
||||
return;
|
||||
}
|
||||
style.onload = function() {
|
||||
curImport.cb(curImport.ss);
|
||||
ieLoadNextImport(style);
|
||||
};
|
||||
var curSheet = style.styleSheet;
|
||||
curImport.ss = curSheet.imports[curSheet.addImport(curImport.url)];
|
||||
}
|
||||
}
|
||||
|
||||
// uses the <link> load method
|
||||
var createLink = function(url) {
|
||||
var link = document.createElement('link');
|
||||
link.type = 'text/css';
|
||||
link.rel = 'stylesheet';
|
||||
link.href = url;
|
||||
return link;
|
||||
}
|
||||
|
||||
var noop = function(){}
|
||||
|
||||
cssAPI.linkLoad = function(url, callback) {
|
||||
var timeout = setTimeout(function() {
|
||||
if (testing) alert('timeout');
|
||||
callback();
|
||||
}, waitSeconds * 1000 - 100);
|
||||
var _callback = function() {
|
||||
clearTimeout(timeout);
|
||||
if (link)
|
||||
link.onload = noop;
|
||||
// for style querying, a short delay still seems necessary
|
||||
setTimeout(callback, 7);
|
||||
}
|
||||
if (!hackLinks) {
|
||||
var link = createLink(url);
|
||||
link.onload = _callback;
|
||||
head.appendChild(link);
|
||||
}
|
||||
// hacks
|
||||
else {
|
||||
if (engine == 'webkit') {
|
||||
var link = createLink(url);
|
||||
webkitLoadCheck(link, _callback);
|
||||
head.appendChild(link);
|
||||
}
|
||||
else if (engine == 'gecko') {
|
||||
var style = document.createElement('style');
|
||||
style.textContent = '@import "' + url + '"';
|
||||
mozillaLoadCheck(style, _callback);
|
||||
head.appendChild(style);
|
||||
}
|
||||
else if (engine == 'trident')
|
||||
ieLoad(url, _callback);
|
||||
}
|
||||
}
|
||||
|
||||
/* injection api */
|
||||
var progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
|
||||
var fileCache = {};
|
||||
var get = function(url, callback, errback) {
|
||||
if (fileCache[url]) {
|
||||
callback(fileCache[url]);
|
||||
return;
|
||||
}
|
||||
|
||||
var xhr, i, progId;
|
||||
if (typeof XMLHttpRequest !== 'undefined')
|
||||
xhr = new XMLHttpRequest();
|
||||
else if (typeof ActiveXObject !== 'undefined')
|
||||
for (i = 0; i < 3; i += 1) {
|
||||
progId = progIds[i];
|
||||
try {
|
||||
xhr = new ActiveXObject(progId);
|
||||
}
|
||||
catch (e) {}
|
||||
|
||||
if (xhr) {
|
||||
progIds = [progId]; // so faster next time
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
xhr.open('GET', url, requirejs.inlineRequire ? false : true);
|
||||
|
||||
xhr.onreadystatechange = function (evt) {
|
||||
var status, err;
|
||||
//Do not explicitly handle errors, those should be
|
||||
//visible via console output in the browser.
|
||||
if (xhr.readyState === 4) {
|
||||
status = xhr.status;
|
||||
if (status > 399 && status < 600) {
|
||||
//An http 4xx or 5xx error. Signal an error.
|
||||
err = new Error(url + ' HTTP status: ' + status);
|
||||
err.xhr = xhr;
|
||||
errback(err);
|
||||
}
|
||||
else {
|
||||
fileCache[url] = xhr.responseText;
|
||||
callback(xhr.responseText);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
xhr.send(null);
|
||||
}
|
||||
//uses the <style> load method
|
||||
var styleCnt = 0;
|
||||
var curStyle;
|
||||
cssAPI.inject = function(css) {
|
||||
if (styleCnt < 31) {
|
||||
curStyle = document.createElement('style');
|
||||
curStyle.type = 'text/css';
|
||||
head.appendChild(curStyle);
|
||||
styleCnt++;
|
||||
}
|
||||
if (curStyle.styleSheet)
|
||||
curStyle.styleSheet.cssText += css;
|
||||
else
|
||||
curStyle.appendChild(document.createTextNode(css));
|
||||
}
|
||||
|
||||
// NB add @media query support for media imports
|
||||
var importRegEx = /@import\s*(url)?\s*(('([^']*)'|"([^"]*)")|\(('([^']*)'|"([^"]*)"|([^\)]*))\))\s*;?/g;
|
||||
|
||||
var pathname = window.location.pathname.split('/');
|
||||
pathname.pop();
|
||||
pathname = pathname.join('/') + '/';
|
||||
|
||||
var loadCSS = function(fileUrl, callback, errback) {
|
||||
|
||||
//make file url absolute
|
||||
if (!fileUrl.match(absUrlRegEx))
|
||||
fileUrl = '/' + normalize.convertURIBase(fileUrl, pathname, '/');
|
||||
|
||||
get(fileUrl, function(css) {
|
||||
|
||||
// normalize the css (except import statements)
|
||||
css = normalize(css, fileUrl, pathname);
|
||||
|
||||
// detect all import statements in the css and normalize
|
||||
var importUrls = [];
|
||||
var importIndex = [];
|
||||
var importLength = [];
|
||||
var match;
|
||||
while (match = importRegEx.exec(css)) {
|
||||
var importUrl = match[4] || match[5] || match[7] || match[8] || match[9];
|
||||
|
||||
importUrls.push(importUrl);
|
||||
importIndex.push(importRegEx.lastIndex - match[0].length);
|
||||
importLength.push(match[0].length);
|
||||
}
|
||||
|
||||
// load the import stylesheets and substitute into the css
|
||||
var completeCnt = 0;
|
||||
for (var i = 0; i < importUrls.length; i++)
|
||||
(function(i) {
|
||||
loadCSS(importUrls[i], function(importCSS) {
|
||||
css = css.substr(0, importIndex[i]) + importCSS + css.substr(importIndex[i] + importLength[i]);
|
||||
var lenDiff = importCSS.length - importLength[i];
|
||||
for (var j = i + 1; j < importUrls.length; j++)
|
||||
importIndex[j] += lenDiff;
|
||||
completeCnt++;
|
||||
if (completeCnt == importUrls.length) {
|
||||
callback(css);
|
||||
}
|
||||
}, errback);
|
||||
})(i);
|
||||
|
||||
if (importUrls.length == 0)
|
||||
callback(css);
|
||||
}, errback);
|
||||
}
|
||||
|
||||
|
||||
cssAPI.normalize = function(name, normalize) {
|
||||
if (name.substr(name.length - 4, 4) == '.css')
|
||||
name = name.substr(0, name.length - 4);
|
||||
|
||||
return normalize(name);
|
||||
}
|
||||
|
||||
var waitSeconds;
|
||||
var alerted = false;
|
||||
cssAPI.load = function(cssId, req, load, config, parse) {
|
||||
|
||||
waitSeconds = waitSeconds || config.waitSeconds || 7;
|
||||
|
||||
var resourceId = cssId + (!parse ? '.css' : '.less');
|
||||
|
||||
// attach the load function to a buffer if there is one in registration
|
||||
// if not, we do a full injection load
|
||||
if (cssAPI.attachBuffer(resourceId, load))
|
||||
return;
|
||||
|
||||
fileUrl = req.toUrl(resourceId);
|
||||
|
||||
if (!alerted && testing) {
|
||||
alert(hackLinks ? 'hacking links' : 'not hacking');
|
||||
alerted = true;
|
||||
}
|
||||
|
||||
if (!parse) {
|
||||
cssAPI.linkLoad(fileUrl, load);
|
||||
}
|
||||
else {
|
||||
loadCSS(fileUrl, function(css) {
|
||||
// run parsing after normalization - since less is a CSS subset this works fine
|
||||
if (parse)
|
||||
css = parse(css, function(css) {
|
||||
cssAPI.inject(css);
|
||||
setTimeout(load, 7);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (testing)
|
||||
cssAPI.inspect = function() {
|
||||
if (stylesheet.styleSheet)
|
||||
return stylesheet.styleSheet.cssText;
|
||||
else if (stylesheet.innerHTML)
|
||||
return stylesheet.innerHTML;
|
||||
}
|
||||
|
||||
return cssAPI;
|
||||
});
|
||||
138
lib/require-css/normalize.js
Normal file
138
lib/require-css/normalize.js
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* css.normalize.js
|
||||
*
|
||||
* CSS Normalization
|
||||
*
|
||||
* CSS paths are normalized based on an optional basePath and the RequireJS config
|
||||
*
|
||||
* Usage:
|
||||
* normalize(css, fromBasePath, toBasePath);
|
||||
*
|
||||
* css: the stylesheet content to normalize
|
||||
* fromBasePath: the absolute base path of the css relative to any root (but without ../ backtracking)
|
||||
* toBasePath: the absolute new base path of the css relative to the same root
|
||||
*
|
||||
* Absolute dependencies are left untouched.
|
||||
*
|
||||
* Urls in the CSS are picked up by regular expressions.
|
||||
* These will catch all statements of the form:
|
||||
*
|
||||
* url(*)
|
||||
* url('*')
|
||||
* url("*")
|
||||
*
|
||||
* @import '*'
|
||||
* @import "*"
|
||||
*
|
||||
* (and so also @import url(*) variations)
|
||||
*
|
||||
* For urls needing normalization
|
||||
*
|
||||
*/
|
||||
|
||||
define(['require', 'module'], function(require, module) {
|
||||
|
||||
// regular expression for removing double slashes
|
||||
// eg http://www.example.com//my///url/here -> http://www.example.com/my/url/here
|
||||
var slashes = /([^:])\/+/g
|
||||
var removeDoubleSlashes = function(uri) {
|
||||
return uri.replace(slashes, '$1/');
|
||||
}
|
||||
|
||||
// given a relative URI, and two absolute base URIs, convert it from one base to another
|
||||
var protocolRegEx = /[^\:\/]*:\/\/([^\/])*/
|
||||
function convertURIBase(uri, fromBase, toBase) {
|
||||
if(uri.indexOf("data:") === 0)
|
||||
return uri;
|
||||
uri = removeDoubleSlashes(uri);
|
||||
// absolute urls are left in tact
|
||||
if (uri.match(/^\//) || uri.match(protocolRegEx))
|
||||
return uri;
|
||||
// if toBase specifies a protocol path, ensure this is the same protocol as fromBase, if not
|
||||
// use absolute path at fromBase
|
||||
var toBaseProtocol = toBase.match(protocolRegEx);
|
||||
var fromBaseProtocol = fromBase.match(protocolRegEx);
|
||||
if (fromBaseProtocol && (!toBaseProtocol || toBaseProtocol[1] != fromBaseProtocol[1] || toBaseProtocol[2] != fromBaseProtocol[2]))
|
||||
return absoluteURI(uri, fromBase);
|
||||
|
||||
else {
|
||||
return relativeURI(absoluteURI(uri, fromBase), toBase);
|
||||
}
|
||||
};
|
||||
|
||||
// given a relative URI, calculate the absolute URI
|
||||
function absoluteURI(uri, base) {
|
||||
if (uri.substr(0, 2) == './')
|
||||
uri = uri.substr(2);
|
||||
|
||||
var baseParts = base.split('/');
|
||||
var uriParts = uri.split('/');
|
||||
|
||||
baseParts.pop();
|
||||
|
||||
while (curPart = uriParts.shift())
|
||||
if (curPart == '..')
|
||||
baseParts.pop();
|
||||
else
|
||||
baseParts.push(curPart);
|
||||
|
||||
return baseParts.join('/');
|
||||
};
|
||||
|
||||
|
||||
// given an absolute URI, calculate the relative URI
|
||||
function relativeURI(uri, base) {
|
||||
|
||||
// reduce base and uri strings to just their difference string
|
||||
var baseParts = base.split('/');
|
||||
baseParts.pop();
|
||||
base = baseParts.join('/') + '/';
|
||||
i = 0;
|
||||
while (base.substr(i, 1) == uri.substr(i, 1))
|
||||
i++;
|
||||
while (base.substr(i, 1) != '/')
|
||||
i--;
|
||||
base = base.substr(i + 1);
|
||||
uri = uri.substr(i + 1);
|
||||
|
||||
// each base folder difference is thus a backtrack
|
||||
baseParts = base.split('/');
|
||||
var uriParts = uri.split('/');
|
||||
out = '';
|
||||
while (baseParts.shift())
|
||||
out += '../';
|
||||
|
||||
// finally add uri parts
|
||||
while (curPart = uriParts.shift())
|
||||
out += curPart + '/';
|
||||
|
||||
return out.substr(0, out.length - 1);
|
||||
};
|
||||
|
||||
var normalizeCSS = function(source, fromBase, toBase, cssBase) {
|
||||
|
||||
fromBase = removeDoubleSlashes(fromBase);
|
||||
toBase = removeDoubleSlashes(toBase);
|
||||
|
||||
var urlRegEx = /@import\s*("([^"]*)"|'([^']*)')|url\s*\(\s*(\s*"([^"]*)"|'([^']*)'|[^\)]*\s*)\s*\)/ig;
|
||||
var result, url, source;
|
||||
|
||||
while (result = urlRegEx.exec(source)) {
|
||||
url = result[3] || result[2] || result[5] || result[6] || result[4];
|
||||
var newUrl;
|
||||
if (cssBase && url.substr(0, 1) == '/')
|
||||
newUrl = cssBase + url;
|
||||
else
|
||||
newUrl = convertURIBase(url, fromBase, toBase);
|
||||
var quoteLen = result[5] || result[6] ? 1 : 0;
|
||||
source = source.substr(0, urlRegEx.lastIndex - url.length - quoteLen - 1) + newUrl + source.substr(urlRegEx.lastIndex - quoteLen - 1);
|
||||
urlRegEx.lastIndex = urlRegEx.lastIndex + (newUrl.length - url.length);
|
||||
}
|
||||
|
||||
return source;
|
||||
};
|
||||
|
||||
normalizeCSS.convertURIBase = convertURIBase;
|
||||
|
||||
return normalizeCSS;
|
||||
});
|
||||
1
lib/require-less/.gitignore
vendored
Normal file
1
lib/require-less/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
example/www-built
|
||||
42
lib/require-less/less-builder.js
Normal file
42
lib/require-less/less-builder.js
Normal file
@ -0,0 +1,42 @@
|
||||
define(['css/css-builder', './lessc-server', 'require'], function(css, lessc, req) {
|
||||
var less = {};
|
||||
|
||||
var baseParts = req.toUrl('base_url').split('/');
|
||||
baseParts.pop();
|
||||
var baseUrl = baseParts.join('/');
|
||||
|
||||
// include the base url as a path
|
||||
var parser = new lessc.Parser({
|
||||
paths: [baseUrl + '/']
|
||||
});
|
||||
|
||||
var parseLess = function(less) {
|
||||
var CSS;
|
||||
parser.parse(less, function(err, tree) {
|
||||
if (err)
|
||||
throw err;
|
||||
CSS = tree.toCSS();
|
||||
});
|
||||
return CSS;
|
||||
}
|
||||
|
||||
less.normalize = function(name, normalize) {
|
||||
if (name.substr(name.length - 5, 5) == '.less')
|
||||
name = name.substr(0, name.length - 5);
|
||||
return normalize(name);
|
||||
}
|
||||
|
||||
less.load = function(name, req, load, config) {
|
||||
css.load(name, req, load, config, parseLess);
|
||||
}
|
||||
|
||||
less.write = function(pluginName, moduleName, write) {
|
||||
css.write(pluginName, moduleName, write, parseLess);
|
||||
}
|
||||
|
||||
less.onLayerEnd = function(write, data) {
|
||||
css.onLayerEnd(write, data, true);
|
||||
}
|
||||
|
||||
return less;
|
||||
});
|
||||
46
lib/require-less/less.js
Normal file
46
lib/require-less/less.js
Normal file
@ -0,0 +1,46 @@
|
||||
define(['css', 'require'], function(css, require) {
|
||||
|
||||
var less = {};
|
||||
|
||||
less.pluginBuilder = './less-builder';
|
||||
|
||||
if (typeof window == 'undefined') {
|
||||
less.load = function(n, r, load) { load(); }
|
||||
return less;
|
||||
}
|
||||
|
||||
//copy api methods from the css plugin
|
||||
less.normalize = function(name, normalize) {
|
||||
if (name.substr(name.length - 5, 5) == '.less')
|
||||
name = name.substr(0, name.length - 5);
|
||||
|
||||
name = normalize(name);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
less.parse = function(less, callback) {
|
||||
require(['./lessc'], function(lessc) {
|
||||
var css;
|
||||
var parser = new lessc.Parser();
|
||||
parser.parse(less, function(err, tree) {
|
||||
if (err)
|
||||
throw err;
|
||||
try {
|
||||
css = tree.toCSS();
|
||||
}
|
||||
catch(e) {
|
||||
throw new Error("LESS parse error: " + e.type + ", " + e.message);
|
||||
}
|
||||
//instant callback luckily for builds
|
||||
callback(css);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
less.load = function(lessId, req, load, config) {
|
||||
css.load(lessId, req, load, config, less.parse);
|
||||
}
|
||||
|
||||
return less;
|
||||
});
|
||||
96
lib/require-less/lessc-server.js
Normal file
96
lib/require-less/lessc-server.js
Normal file
@ -0,0 +1,96 @@
|
||||
define(['./lessc'], function(less) {
|
||||
|
||||
if (['node', 'rhino'].indexOf(less.mode) == -1) {
|
||||
throw new Error('Environment not supported by require-less builder: ' + less.mode);
|
||||
}
|
||||
|
||||
var readFile = (function() {
|
||||
if (less.mode === 'node') {
|
||||
var fs = require.nodeRequire('fs');
|
||||
var path = require.nodeRequire('path');
|
||||
return function(pathname) {
|
||||
return fs.readFileSync(pathname, 'utf-8');
|
||||
};
|
||||
} else if (less.mode === 'rhino') {
|
||||
return function(pathname) {
|
||||
return readFile(pathname, 'UTF-8');
|
||||
};
|
||||
}
|
||||
}());
|
||||
|
||||
var checkPath = (function() {
|
||||
if (less.mode === 'node') {
|
||||
var fs = require.nodeRequire('fs');
|
||||
var path = require.nodeRequire('path');
|
||||
return function(pathname, file) {
|
||||
try {
|
||||
pathname = path.join(pathname, file);
|
||||
fs.statSync(pathname);
|
||||
return pathname;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
} else if (less.mode === 'rhino') {
|
||||
return function(pathname, file) {
|
||||
var f = new java.io.File(pathname, file);
|
||||
if (f.isFile()) {
|
||||
return f.getPath();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}());
|
||||
|
||||
less.Parser.importer = function (file, paths, callback, env) {
|
||||
var pathname, data;
|
||||
|
||||
// TODO: Undo this at some point,
|
||||
// or use different approach.
|
||||
var paths = [].concat(paths);
|
||||
paths.push('.');
|
||||
|
||||
for (var i = 0; i < paths.length; i++) {
|
||||
pathname = checkPath(paths[i], file);
|
||||
if (pathname != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
paths = paths.slice(0, paths.length - 1);
|
||||
|
||||
if (!pathname) {
|
||||
if (typeof(env.errback) === "function") {
|
||||
env.errback(file, paths, callback);
|
||||
} else {
|
||||
callback({ type: 'File', message: "'" + file + "' wasn't found.\n" });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
function parseFile(e, data) {
|
||||
if (e) return callback(e);
|
||||
env.contents = env.contents || {};
|
||||
env.contents[pathname] = data; // Updating top importing parser content cache.
|
||||
new(less.Parser)({
|
||||
paths: [path.dirname(pathname)].concat(paths),
|
||||
filename: pathname,
|
||||
contents: env.contents,
|
||||
files: env.files,
|
||||
syncImport: env.syncImport,
|
||||
dumpLineNumbers: env.dumpLineNumbers
|
||||
}).parse(data, function (e, root) {
|
||||
callback(e, root, pathname);
|
||||
});
|
||||
};
|
||||
|
||||
try {
|
||||
readFile(pathname);
|
||||
parseFile(null, data);
|
||||
} catch (e) {
|
||||
parseFile(e);
|
||||
}
|
||||
}
|
||||
return less;
|
||||
});
|
||||
4441
lib/require-less/lessc.js
Normal file
4441
lib/require-less/lessc.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,24 +0,0 @@
|
||||
nav a:link {
|
||||
color: #58b4df;
|
||||
}
|
||||
nav a:visited {
|
||||
color: #58b4df;
|
||||
}
|
||||
nav a:hover {
|
||||
color: #000000;
|
||||
}
|
||||
nav a:active {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.menu-links {
|
||||
float: left;
|
||||
}
|
||||
.menu-user {
|
||||
margin-right: 20px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.menu-user a {
|
||||
cursor: pointer;
|
||||
}
|
||||
26
stylesheets/mifosX.less
Normal file
26
stylesheets/mifosX.less
Normal file
@ -0,0 +1,26 @@
|
||||
nav a {
|
||||
&:link {
|
||||
color: #58b4df;
|
||||
}
|
||||
&:visited {
|
||||
color: #58b4df;
|
||||
}
|
||||
&:hover {
|
||||
color: #000000;
|
||||
}
|
||||
&:active {
|
||||
color: #000000;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-links {
|
||||
float: left;
|
||||
}
|
||||
.menu-user {
|
||||
margin-right: 20px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.menu-user a {
|
||||
cursor: pointer;
|
||||
}
|
||||
@ -4,7 +4,7 @@ define(['mifosX', 'angular-mocks'], {
|
||||
mifosX.ng.application.config(function($provide) {
|
||||
$provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
|
||||
}).run(function($httpBackend, $log) {
|
||||
$log.warn("Loading test scenario: " + scenarioName);
|
||||
$log.warn("Running test scenario: " + scenarioName);
|
||||
$httpBackend.when("GET", /\.html$/).passThrough();
|
||||
scenario.stubServer($httpBackend);
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user