simpler text list column head elements, better column drag

This commit is contained in:
rlx 2011-09-09 10:41:13 +00:00
parent 7bf42e5b0b
commit 0ba258281f
12 changed files with 461 additions and 330 deletions

View file

@ -9,7 +9,9 @@ Ox.load('Image', function() {
'Method...', 'blur(1)', 'blur(5)', 'Method...', 'blur(1)', 'blur(5)',
'channel("r")', 'channel("g")', 'channel("b")', 'channel("a")', 'channel("r")', 'channel("g")', 'channel("b")', 'channel("a")',
'channel("h")', 'channel("s")', 'channel("l")', 'channel("h")', 'channel("s")', 'channel("l")',
'contour()', 'depth(1)', 'depth(4)', 'edges()', 'emboss()', 'contour()',
'depth(1)', 'depth(2)', 'depth(4)',
'edges()', 'emboss()',
'encode("secret")', 'decode()', 'encode("secret")', 'decode()',
'encode("secret", false)', 'decode(false)', 'encode("secret", false)', 'decode(false)',
'encode("secret", 1)', 'decode(1)', 'encode("secret", 1)', 'decode(1)',
@ -18,9 +20,10 @@ Ox.load('Image', function() {
'hue(-60)', 'hue(60)', 'hue(-60)', 'hue(60)',
'invert()', 'invert()',
'lightness(-0.5)', 'lightness(0.5)', 'lightness(-0.5)', 'lightness(0.5)',
'motionBlur()', 'posterize()', 'mosaic(4)', 'motionBlur()', 'photocopy()', 'posterize()',
'resize(256, 256)', 'resize(512, 512)', 'resize(256, 256)', 'resize(512, 512)',
'saturation(-0.5)', 'saturation(0.5)', 'saturation(-0.5)', 'saturation(0.5)',
'scale(0.5, -1)',
'sharpen()', 'solarize()', 'sharpen()', 'solarize()',
'src("png/Lenna.png")', 'src("png/OxJS.png")' 'src("png/Lenna.png")', 'src("png/OxJS.png")'
].forEach(function(filter) { ].forEach(function(filter) {
@ -41,7 +44,7 @@ Ox.load('Image', function() {
image[fn].apply(null, Ox.merge(args, function(image) { image[fn].apply(null, Ox.merge(args, function(image) {
Ox.element('#filter').attr({ Ox.element('#filter').attr({
src: image.src() src: image.src()
}); }).css({width: '512px', height: '512px'});
})); }));
} else if (fn == 'decode') { } else if (fn == 'decode') {
image[fn].apply(null, Ox.merge(args, function(str) { image[fn].apply(null, Ox.merge(args, function(str) {

View file

@ -8,19 +8,21 @@
Ox.load('Image', function() { Ox.load('Image', function() {
var fixmeOxelement; var fixmeOxelement;
var body = Ox.element('body'), var body = Ox.element('body'),
button = Ox.element('<input>').attr({type: 'button', value: 'encode'}).click(function() { button = Ox.element('<input>').attr({type: 'button', value: 'Encode'}).click(function() {
button.attr({disabled: 'disabled'}) button.attr({disabled: 'disabled'})
if (button.attr('value') == 'encode') { if (button.attr('value') == 'Encode') {
button.attr({value: 'encoding...'}); button.attr({value: 'Encoding...'});
encode(function(image) { encode(function(image) {
fixmeOxelement = image; fixmeOxelement = image;
button.removeAttr('disabled').attr({value: 'decode'}); button.removeAttr('disabled').attr({value: 'Decode'});
}); });
} else { } else {
button.attr({value: 'decoding...'}); button.attr({value: 'Decoding...'});
decode(fixmeOxelement, function() { setTimeout(function() {
button.attr({value: 'done'}) decode(fixmeOxelement, function() {
}); button.attr({value: 'Done'})
});
}, 0);
} }
}).appendTo(body); }).appendTo(body);
Ox.element('<br>').appendTo(body); Ox.element('<br>').appendTo(body);

View file

@ -4,6 +4,8 @@ Ox.load.Image = function(options, callback) {
/*@ /*@
Ox.Image <f> Generic image object Ox.Image <f> Generic image object
To render the image as an image element, use its <code>src()</code>
method, to render it as a canvas, use its <code>canvas</code> property.
(src, callback) -> <u> undefined (src, callback) -> <u> undefined
(width, height, callback) -> <u> undefined (width, height, callback) -> <u> undefined
(width, height, background, callback) -> <u> undefined (width, height, background, callback) -> <u> undefined
@ -26,7 +28,8 @@ Ox.load.Image = function(options, callback) {
} else { } else {
self.width = arguments[0]; self.width = arguments[0];
self.height = arguments[1]; self.height = arguments[1];
self.background = arguments.length == 4 ? arguments[2] : [0, 0, 0, 0]; self.background = arguments.length == 4
? arguments[2] : [0, 0, 0, 0];
init(); init();
} }
@ -66,19 +69,21 @@ Ox.load.Image = function(options, callback) {
self.width = self.image.width; self.width = self.image.width;
self.height = self.image.height; self.height = self.image.height;
} }
self.canvas = Ox.element('<canvas>').attr({ that.canvas = Ox.element('<canvas>').attr({
width: self.width, width: self.width,
height: self.height height: self.height
}); });
self.context = self.canvas[0].getContext('2d'); that.context = that.canvas[0].getContext('2d');
if (self.image) { if (self.image) {
self.context.drawImage(self.image, 0, 0); that.context.drawImage(self.image, 0, 0);
} else if (Ox.sum(self.background)) { } else if (Ox.sum(self.background)) {
that.fillStyle(self.background); that.context.fillStyle(self.background);
that.fillRect(0, 0, self.width, self.height); that.context.fillRect(0, 0, self.width, self.height);
} }
self.imageData = self.context.getImageData(0, 0, self.width, self.height); that.imageData = that.context.getImageData(
self.data = self.imageData.data; 0, 0, self.width, self.height
);
self.data = that.imageData.data;
self.callback(that); self.callback(that);
} }
@ -92,6 +97,11 @@ Ox.load.Image = function(options, callback) {
}); });
} }
/*@
blur <f> Apply blur filter
(val) -> <o> The image object
val <n> Amount of blur (1 to 5, more is slow)
@*/
that.blur = function(val) { that.blur = function(val) {
var filter = [], var filter = [],
size = val * 2 + 1; size = val * 2 + 1;
@ -111,6 +121,13 @@ Ox.load.Image = function(options, callback) {
return that.filter(filter); return that.filter(filter);
}; };
//@ canvas <o> Canvas object
/*@
channel <f> Reduce the image to one channel
(channel) -> <o> The image object
channel <str> 'r', 'g', 'b', 'a', 'h', 's' or 'l'
@*/
that.channel = function(str) { that.channel = function(str) {
str = str[0].toLowerCase(); str = str[0].toLowerCase();
return that.map(function(rgba) { return that.map(function(rgba) {
@ -134,6 +151,12 @@ Ox.load.Image = function(options, callback) {
}); });
} }
//@ context <o> 2D drawing context
/*@
contour <f> Apply contour filter
() -> <o> The image object
@*/
that.contour = function(val) { that.contour = function(val) {
return that.filter([ return that.filter([
+1, +1, +1, +1, +1, +1,
@ -142,15 +165,24 @@ Ox.load.Image = function(options, callback) {
]); ]);
}; };
/*@
depth <f> Reduce the bit depth
(depth) -> <o> The image object
depth <n> Bits per channel (1 to 7)
@*/
that.depth = function(val) { that.depth = function(val) {
var pow = Math.pow(2, 8 - val); var pow = Math.pow(2, 8 - val);
return that.map(function(rgba) { return that.map(function(rgba) {
return rgba.map(function(v, i) { return rgba.map(function(v, i) {
return i < 3 ? Math.floor(v / pow) * pow : v return i < 3 ? Math.floor(v / pow) * pow/* * 255 / val*/ : v;
}); });
}); });
} };
/*@
edges <f> Apply edges filter
() -> <o> The image object
@*/
that.edges = function(val) { that.edges = function(val) {
return that.filter([ return that.filter([
-1, -1, -1, -1, -1, -1,
@ -159,6 +191,10 @@ Ox.load.Image = function(options, callback) {
]).saturation(-1); ]).saturation(-1);
}; };
/*@
emboss <f> Apply emboss filter
() -> <o> The image object
@*/
that.emboss = function(val) { that.emboss = function(val) {
return that.filter([ return that.filter([
-1, -1, +0, -1, -1, +0,
@ -171,8 +207,8 @@ Ox.load.Image = function(options, callback) {
encode <f> Encodes a string into the image encode <f> Encodes a string into the image
For most purposes, deflate and mode should be omitted, since the For most purposes, deflate and mode should be omitted, since the
defaults make the existence of the message harder to detect. A valid defaults make the existence of the message harder to detect. A valid
use case for deflate and mode would be to encode, additionally to use case for deflate and mode would be to first encode a more easily
the secret string, a more easily detected decoy string: <code> detected decoy string, and only then the secret string: <code>
image.encode(decoy, false, 1, function(image) { image.encode(secret, image.encode(decoy, false, 1, function(image) { image.encode(secret,
-1, callback); })</code>. -1, callback); })</code>.
(str, callback) -> <o> The image object (unmodified) (str, callback) -> <o> The image object (unmodified)
@ -183,7 +219,7 @@ Ox.load.Image = function(options, callback) {
str <s> The string to be encoded str <s> The string to be encoded
callback <f> Callback function callback <f> Callback function
image <o> The image object (modified) image <o> The image object (modified)
deflate <b|true> If true, compress string with deflate deflate <b|true> If true, encode the string with deflate
mode <n|0> Encoding mode mode <n|0> Encoding mode
If mode is between -7 and 0, the string will be encoded one bit If mode is between -7 and 0, the string will be encoded one bit
per byte, as the number of bits within that byte set to 1, per byte, as the number of bits within that byte set to 1,
@ -199,6 +235,7 @@ Ox.load.Image = function(options, callback) {
mode = Ox.isNumber(arguments[1]) ? arguments[1] mode = Ox.isNumber(arguments[1]) ? arguments[1]
: Ox.isNumber(arguments[2]) ? arguments[2] : 0, : Ox.isNumber(arguments[2]) ? arguments[2] : 0,
b = 0, bin, b = 0, bin,
// Array of bits per byte to be modified (0 is LSB)
bits = mode < 1 ? [-mode] : Ox.map(Ox.range(8), function(bit) { bits = mode < 1 ? [-mode] : Ox.map(Ox.range(8), function(bit) {
return mode & 1 << bit ? bit : null; return mode & 1 << bit ? bit : null;
}), }),
@ -226,6 +263,7 @@ Ox.load.Image = function(options, callback) {
if (rgba[3] == 255) { if (rgba[3] == 255) {
var index = getIndex(xy); var index = getIndex(xy);
Ox.loop(3, function(c) { Ox.loop(3, function(c) {
// fixme: use: var data = that.context.imageData.data[i + c]
var i = index + c; var i = index + c;
Ox.forEach(bits, function(bit) { Ox.forEach(bits, function(bit) {
if (( if ((
@ -245,11 +283,23 @@ Ox.load.Image = function(options, callback) {
}); });
} }
}); });
self.context.putImageData(self.imageData, 0, 0); that.context.putImageData(that.imageData, 0, 0);
callback(that); callback(that);
return that; return that;
}; };
/*@
decode <f> Decode encoded string
(callback) -> <o> The image object (unmodified)
(deflate, callback) -> <o> The image object (unmodified)
(mode, callback) -> <o> The image object (unmodified)
(deflate, mode, callback) -> <o> The image object (unmodified)
(mode, deflate, callback) -> <o> The image object (unmodified)
deflate <b|true> If true, decode the string with deflate
mode <n|0> See encode method
callback <f> Callback function
image <o> The image object (modified)
@*/
that.decode = function() { that.decode = function() {
var callback = arguments[arguments.length - 1], var callback = arguments[arguments.length - 1],
deflate = Ox.isBoolean(arguments[0]) ? arguments[0] deflate = Ox.isBoolean(arguments[0]) ? arguments[0]
@ -257,6 +307,7 @@ Ox.load.Image = function(options, callback) {
mode = Ox.isNumber(arguments[0]) ? arguments[0] mode = Ox.isNumber(arguments[0]) ? arguments[0]
: Ox.isNumber(arguments[1]) ? arguments[1] : 0, : Ox.isNumber(arguments[1]) ? arguments[1] : 0,
bin = '', bin = '',
// Array of bits per byte to be modified (0 is LSB)
bits = mode < 1 ? [-mode] : Ox.map(Ox.range(8), function(b) { bits = mode < 1 ? [-mode] : Ox.map(Ox.range(8), function(b) {
return mode & 1 << b ? b : null; return mode & 1 << b ? b : null;
}), }),
@ -268,35 +319,41 @@ Ox.load.Image = function(options, callback) {
var i = index + c; var i = index + c;
Ox.forEach(bits, function(bit) { Ox.forEach(bits, function(bit) {
bin += mode < 1 bin += mode < 1
// Read the number of bits set to 1, mod 2
? Ox.sum(Ox.range(8).map(function(bit) { ? Ox.sum(Ox.range(8).map(function(bit) {
return +!!(self.data[i] & 1 << bit); return +!!(self.data[i] & 1 << bit);
})) % 2 })) % 2
// or the one bit in question
: +!!(self.data[i] & 1 << bit); : +!!(self.data[i] & 1 << bit);
if (bin.length == 8) { if (bin.length == 8) {
// Every 8 bits, add one byte to the string
str += Ox.char(parseInt(bin, 2)); str += Ox.char(parseInt(bin, 2));
bin = ''; bin = '';
if (str.length == len) { if (str.length == len) {
if (++done == 1) { if (++done == 1) {
// After 4 bytes, parse string as length
len = Ox.decodeBase256(str); len = Ox.decodeBase256(str);
Ox.print("LEN", len) if (
len + 4 > getCapacity(bits.length) len <= 0 ||
&& error('decode'); len > getCapacity(bits.length) - 4
) {
error('decode');
}
str = ''; str = '';
} else { } else {
// After length more bytes, break
return false; return false;
} }
} }
} }
}); });
return done != 2;
}); });
if (done == 2) { return done != 2;
return false;
}
} }
}); });
try { try {
if (deflate) { if (deflate) {
Ox.print('DEFLATE')
Ox.decodeDeflate(str, callback); Ox.decodeDeflate(str, callback);
} else { } else {
callback(Ox.decodeUTF8(str)); callback(Ox.decodeUTF8(str));
@ -306,28 +363,22 @@ Ox.load.Image = function(options, callback) {
} }
} }
that.fillRect = function(x, y, w, h) { /*@
self.context.fillRect(x, y, w, h); filter <f> Pixel-wise filter function
return that; Undocumented, see source code
}; (filter) -> <o> The image object
(filter, bias) -> <o> The image object
that.fillStyle = function() { filter <[n]> Filter matrix
if (arguments.length == 0) { bias <n> Bias
return self.context.fillStyle; @*/
} else {
self.context.fillStyle = arguments[0];
return that;
}
};
that.filter = function(filter, bias) { that.filter = function(filter, bias) {
bias = bias || 0; bias = bias || 0;
var filterSize = Math.sqrt(filter.length), var filterSize = Math.sqrt(filter.length),
d = (filterSize - 1) / 2, d = (filterSize - 1) / 2,
imageData = self.context.createImageData(self.width, self.height), imageData = that.context.createImageData(self.width, self.height),
data = []; data = [];
self.imageData = self.context.getImageData(0, 0, self.width, self.height); that.imageData = that.context.getImageData(0, 0, self.width, self.height);
self.data = self.imageData.data; self.data = that.imageData.data;
Ox.loop(0, self.data.length, 4, function(i) { Ox.loop(0, self.data.length, 4, function(i) {
var filterIndex = 0, var filterIndex = 0,
xy = getXY(i); xy = getXY(i);
@ -351,8 +402,8 @@ Ox.load.Image = function(options, callback) {
: self.data[i + c]; : self.data[i + c];
}); });
}); });
self.context.putImageData(imageData, 0, 0); that.context.putImageData(imageData, 0, 0);
self.imageData = imageData; that.imageData = imageData;
self.data = data; self.data = data;
return that; return that;
}; };
@ -383,12 +434,23 @@ Ox.load.Image = function(options, callback) {
}); });
}; };
//@ imageData <o> Image data object
/*@
invert <f> Apply invert filter
() -> <o> The image object
@*/
that.invert = function() { that.invert = function() {
return that.map(function(rgba) { return that.map(function(rgba) {
return [255 - rgba[0], 255 - rgba[1], 255 - rgba[2], rgba[3]]; return [255 - rgba[0], 255 - rgba[1], 255 - rgba[2], rgba[3]];
}); });
}; };
/*@
lightness <f> Apply lightness filter
(val) -> <o> The image object
val <n> Amount, from -1 (darkest) to 1 (lightest)
@*/
that.lightness = function(val) { that.lightness = function(val) {
return setSL('l', val); return setSL('l', val);
}; };
@ -401,8 +463,8 @@ Ox.load.Image = function(options, callback) {
xy <[n]> XY coordinates xy <[n]> XY coordinates
@*/ @*/
that.map = function(fn) { that.map = function(fn) {
self.imageData = self.context.getImageData(0, 0, self.width, self.height); that.imageData = that.context.getImageData(0, 0, self.width, self.height);
self.data = self.imageData.data; self.data = that.imageData.data;
Ox.loop(0, self.data.length, 4, function(i) { Ox.loop(0, self.data.length, 4, function(i) {
fn([ fn([
self.data[i], self.data[i + 1], self.data[i], self.data[i + 1],
@ -411,10 +473,44 @@ Ox.load.Image = function(options, callback) {
self.data[i + c] = val; self.data[i + c] = val;
}); });
}) })
self.context.putImageData(self.imageData, 0, 0); that.context.putImageData(that.imageData, 0, 0);
return that; return that;
}; };
/*@
mosaic <f> Apply mosaic filter
(size) -> <o> The image object
size <n> Mosaic size
@*/
that.mosaic = function(size) {
that.forEach(function(rgba, xy) {
if (xy[0] % size == 0 && xy[1] % size == 0) {
Ox.loop(size, function(x) {
Ox.loop(size, function(y) {
var hsl, rgb;
if ((x == 0 || y == 0) && !(x == size - 1 || y == size - 1)) {
that.pixel(xy[0] + x, xy[1] + y, rgba.map(function(c, i) {
return i < 3 ? Math.min(c + 16, 255) : c;
}));
} else if ((x == size - 1 || y == size - 1) && !(x == 0 || y == 0)) {
that.pixel(xy[0] + x, xy[1] + y, rgba.map(function(c, i) {
return i < 3 ? Math.max(c - 16, 0) : c;
}));
} else {
that.pixel(xy[0] + x, xy[1] + y, rgba);
}
});
});
}
});
that.context.putImageData(that.imageData, 0, 0);
return that;
}
/*@
motionBlur <f> Apply motion blur filter
() -> <o> The image object
@*/
that.motionBlur = function() { that.motionBlur = function() {
return that.filter([ return that.filter([
0.2, 0.0, 0.0, 0.0, 0.0, 0.2, 0.0, 0.0, 0.0, 0.0,
@ -425,6 +521,22 @@ Ox.load.Image = function(options, callback) {
]); ]);
}; };
/*@
photocopy <f> Apply photocopy filter
() -> <o> The image object
@*/
that.photocopy = function(val) {
return that.saturation(-1).depth(1).blur(1);
};
/*@
pixel <f> Get or set pixel values
(x, y) -> <[n]> RGBA values
(x, y, val) -> <o> The image object
x <n> X coordinate
y <n> Y coordinate
val <[n]> RGBA values
@*/
that.pixel = function(x, y, val) { that.pixel = function(x, y, val) {
var i = getIndex(x, y); var i = getIndex(x, y);
if (!val) { if (!val) {
@ -438,6 +550,10 @@ Ox.load.Image = function(options, callback) {
} }
} }
/*@
posterize <f> Apply posterize filter
() -> <o> The image object
@*/
that.posterize = function() { that.posterize = function() {
return that.blur(3).map(function(rgba) { return that.blur(3).map(function(rgba) {
return [ return [
@ -450,17 +566,27 @@ Ox.load.Image = function(options, callback) {
}; };
that.resize = function(width, height) { that.resize = function(width, height) {
self.canvas.attr({ // fixme: may not work this way
that.canvas.attr({
width: width, width: width,
height: height height: height
}); });
return that; return that;
} }
/*@
saturation <f> Apply saturation filter
(val) -> <o> The image object
val <n> Amount, from -1 (lowest) to 1 (highest)
@*/
that.saturation = function(val) { that.saturation = function(val) {
return setSL('s', val); return setSL('s', val);
}; };
/*@
sharpen <f> Apply sharpen filter
() -> <o> The image object
@*/
that.sharpen = function(val) { that.sharpen = function(val) {
return that.filter([ return that.filter([
-1, -1, -1, -1, -1, -1,
@ -469,6 +595,10 @@ Ox.load.Image = function(options, callback) {
]); ]);
}; };
/*@
solarize <f> Apply solarize filter
() -> <o> The image object
@*/
that.solarize = function() { that.solarize = function() {
return that.map(function(rgba) { return that.map(function(rgba) {
return [ return [
@ -480,9 +610,15 @@ Ox.load.Image = function(options, callback) {
}); });
} }
/*@
src <f> Get or set the image source
() -> <s> Data URL
(src) -> <o> Image object, with new source
src <s> Image source (local, remote or data URL)
@*/
that.src = function() { that.src = function() {
if (arguments.length == 0) { if (arguments.length == 0) {
return self.canvas[0].toDataURL(); return that.canvas[0].toDataURL();
} else { } else {
var callback = arguments[1]; var callback = arguments[1];
self.src = arguments[0]; self.src = arguments[0];
@ -490,13 +626,13 @@ Ox.load.Image = function(options, callback) {
self.image.onload = function() { self.image.onload = function() {
self.width = self.image.width; self.width = self.image.width;
self.height = self.image.height; self.height = self.image.height;
self.canvas.attr({ that.canvas.attr({
width: self.width, width: self.width,
height: self.height height: self.height
}); });
self.context.drawImage(self.image, 0, 0); that.context.drawImage(self.image, 0, 0);
self.imageData = self.context.getImageData(0, 0, self.width, self.height); that.imageData = that.context.getImageData(0, 0, self.width, self.height);
self.data = self.imageData.data; self.data = that.imageData.data;
callback && callback(that); callback && callback(that);
} }
self.image.src = self.src; self.image.src = self.src;
@ -504,8 +640,6 @@ Ox.load.Image = function(options, callback) {
} }
}; };
that.toDataURL = that.src;
}; };
callback(true); callback(true);

View file

@ -1105,25 +1105,23 @@ Lists
//-moz-box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.75); //-moz-box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.75);
//-webkit-box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.75); //-webkit-box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.75);
} }
.OxTextList .OxBar .OxHead { .OxTextList .OxHead {
position: absolute; position: absolute;
left: 0; left: 0;
height: 16px; height: 16px;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
} }
.OxTextList .OxBar .OxCell { .OxTextList .OxHead .OxHeadCell {
float: left; float: left;
padding: 2px 4px 2px 4px;
height: 12px;
} }
.OxTextList .OxBar .OxCell:nthChild(1) { .OxTextList .OxHead .OxHeadCell:first-child {
margin-left: 0; padding-left: 2px;
} }
.OxTextList .OxBar .OxTitle { .OxTextList .OxHead .OxTitle {
float: left; float: left;
height: 15px; height: 14px;
padding: 1px 2px 0 2px; padding: 2px 2px 0 2px;
font-weight: bold; font-weight: bold;
font-size: 10px; font-size: 10px;
text-overflow: ellipsis; text-overflow: ellipsis;
@ -1131,47 +1129,34 @@ Lists
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
} }
.OxTextList .OxBar .OxTitle img { .OxTextList .OxHead .OxTitle img {
width: 16px;
height: 16px;
margin: -1px 0 0 -4px;
}
.OxTextList .OxBar .OxTitle:first-child {
padding-left: 4px;
}
.OxTextList .OxBar .OxOrder {
float: left;
width: 10px; width: 10px;
height: 13px; height: 10px;
padding: 3px 0 0 6px; margin: 1px 0 0 -1px;
font-size: 7px; }
.OxTextList .OxHead .OxOrder {
float: left;
display: none; display: none;
} }
.OxTextList .OxBar .OxOrder.OxSelected { .OxTextList .OxHead .OxHeadCell.OxSelected .OxOrder {
//cursor: pointer; //cursor: pointer;
display: block; display: block;
} }
.OxTextList .OxBar .OxResize { .OxTextList .OxHead .OxResize {
float: left; float: left;
width: 5px; width: 5px;
height: 16px; height: 16px;
} }
.OxTextList .OxBar .OxResize.OxResizable { .OxTextList .OxHead .OxResize.OxResizable {
cursor: ew-resize; cursor: ew-resize;
} }
.OxTextList .OxBar .OxResize .OxLeft, .OxTextList .OxHead .OxResize div {
.OxTextList .OxBar .OxResize .OxCenter,
.OxTextList .OxBar .OxResize .OxRight {
float: left; float: left;
width: 2px;
height: 16px; height: 16px;
} }
.OxTextList .OxBar .OxResize .OxLeft, .OxTextList .OxHead .OxResize div.OxCenter {
.OxTextList .OxBar .OxResize .OxRight {
width: 2px;
}
.OxTextList .OxBar .OxResize .OxCenter {
width: 1px; width: 1px;
background: rgb(24, 24, 24);
} }
.OxTextList .OxBar .OxSelect { .OxTextList .OxBar .OxSelect {
position: absolute; position: absolute;

View file

@ -1,13 +1,10 @@
// vim: et:ts=4:sw=4:sts=4:ft=javascript // vim: et:ts=4:sw=4:sts=4:ft=javascript
/*@ /*@
Ox.Clipboard <o> Basic clipboard handler Ox.Clipboard <o> Basic clipboard handler
copy <f> copy to clipbloard copy <f> Copy data to clipboard
(data) -> <u> set clipboard to data (data) -> <u> undefined
paste <f> paste from clipbload paste <f> Paste data from clipboard
() -> <o> get clipboard data () -> <*> Clipboard data
_print <f> debug function
() -> <u> print clipboard contents to console
data <o> clipboard object
@*/ @*/
Ox.Clipboard = function() { Ox.Clipboard = function() {
var clipboard = {}; var clipboard = {};

View file

@ -309,6 +309,8 @@ Ox.List = function(options, self) {
} }
function copyItems() { function copyItems() {
// fixme: both copy and paste should just deal with Ox.Clipboard,
// and use a "type"
self.options.selected.length && that.triggerEvent('copy', { self.options.selected.length && that.triggerEvent('copy', {
ids: self.options.selected ids: self.options.selected
}); });
@ -653,7 +655,7 @@ Ox.List = function(options, self) {
if (self.$items.length == 0) { if (self.$items.length == 0) {
return self.options.selected; return self.options.selected;
} else { } else {
return $.map(self.selected, function(pos) { return self.selected.map(function(pos) {
return self.$items[pos].options('data')[self.options.unique]; return self.$items[pos].options('data')[self.options.unique];
}); });
} }
@ -826,7 +828,7 @@ Ox.List = function(options, self) {
}); });
that.triggerEvent('move', { that.triggerEvent('move', {
//id: id, //id: id,
ids: $.map(self.$items, function($item) { ids: self.$items.map(function($item) {
return $item.options('data')[self.options.unique]; return $item.options('data')[self.options.unique];
}) })
//position: pos //position: pos

View file

@ -81,59 +81,59 @@ Ox.TextList = function(options, self) {
keys: find keys: find
}); });
self.options.columns.forEach(function(v) { // fixme: can this go into a generic ox.js function? self.options.columns.forEach(function(column) { // fixme: can this go into a generic ox.js function?
// fixme: and can't these just remain undefined? // fixme: and can't these just remain undefined?
if (Ox.isUndefined(v.align)) { if (Ox.isUndefined(column.align)) {
v.align = 'left'; column.align = 'left';
} }
if (Ox.isUndefined(v.clickable)) { if (Ox.isUndefined(column.clickable)) {
v.clickable = false; column.clickable = false;
} }
if (Ox.isUndefined(v.editable)) { if (Ox.isUndefined(column.editable)) {
v.editable = false; column.editable = false;
} }
if (Ox.isUndefined(v.unique)) { if (Ox.isUndefined(column.unique)) {
v.unique = false; column.unique = false;
} }
if (Ox.isUndefined(v.visible)) { if (Ox.isUndefined(column.visible)) {
v.visible = false; column.visible = false;
} }
if (v.unique) { if (column.unique) {
self.unique = v.id; self.unique = column.id;
} }
}); });
$.extend(self, { Ox.extend(self, {
columnPositions: [], columnPositions: [],
defaultColumnWidths: $.map(self.options.columns, function(v) { defaultColumnWidths: self.options.columns.map(function(column) {
return v.defaultWidth || v.width; return column.defaultWidth || column.width;
}), }),
itemHeight: 16, itemHeight: 16,
page: 0, page: 0,
pageLength: 100, pageLength: 100,
scrollLeft: 0, scrollLeft: 0,
selectedColumn: getColumnIndexById(self.options.sort[0].key), selectedColumn: getColumnIndexById(self.options.sort[0].key),
visibleColumns: $.map(self.options.columns, function(v) { visibleColumns: self.options.columns.filter(function(column) {
return v.visible ? v : null; return column.visible;
}) })
}); });
// fixme: there might be a better way than passing both visible and position // fixme: there might be a better way than passing both visible and position
self.options.columns.forEach(function(v) { self.options.columns.forEach(function(column) {
if (!Ox.isUndefined(v.position)) { if (!Ox.isUndefined(column.position)) {
self.visibleColumns[v.position] = v; self.visibleColumns[column.position] = column;
} }
}); });
$.extend(self, { Ox.extend(self, {
columnWidths: $.map(self.visibleColumns, function(v, i) { columnWidths: self.visibleColumns.map(function(column) {
return v.width; return column.width;
}), }),
pageHeight: self.options.pageLength * self.itemHeight pageHeight: self.options.pageLength * self.itemHeight
}); });
self.format = {}; self.format = {};
self.options.columns.forEach(function(v, i) { self.options.columns.forEach(function(column) {
if (v.format) { if (column.format) {
self.format[v.id] = v.format; self.format[column.id] = column.format;
} }
}); });
@ -147,7 +147,8 @@ Ox.TextList = function(options, self) {
that.$head = Ox.Container() that.$head = Ox.Container()
.addClass('OxHead') .addClass('OxHead')
.css({ .css({
right: self.options.scrollbarVisible ? Ox.UI.SCROLLBAR_SIZE + 'px' : 0 right: self.options.scrollbarVisible
? Ox.UI.SCROLLBAR_SIZE + 'px' : 0
}) })
.appendTo(that.$bar); .appendTo(that.$bar);
that.$head.$content.addClass('OxTitles'); that.$head.$content.addClass('OxTitles');
@ -155,13 +156,13 @@ Ox.TextList = function(options, self) {
if (self.options.columnsRemovable) { if (self.options.columnsRemovable) {
that.$select = Ox.Select({ that.$select = Ox.Select({
id: self.options.id + 'SelectColumns', id: self.options.id + 'SelectColumns',
items: $.map(self.options.columns, function(v, i) { items: self.options.columns.map(function(column) {
return { return {
checked: v.visible, checked: column.visible,
disabled: v.removable === false, disabled: column.removable === false,
id: v.id, id: column.id,
title: v.title title: column.title
} };
}), }),
max: -1, max: -1,
min: 1, min: 1,
@ -195,7 +196,7 @@ Ox.TextList = function(options, self) {
sortable: self.options.sortable, sortable: self.options.sortable,
type: 'text', type: 'text',
unique: self.unique unique: self.unique
}, $.extend({}, self)) // pass event handler }, Ox.extend({}, self)) // pass event handler
.addClass('OxBody') .addClass('OxBody')
.css({ .css({
top: (self.options.columnsVisible ? 16 : 0) + 'px', top: (self.options.columnsVisible ? 16 : 0) + 'px',
@ -305,83 +306,87 @@ Ox.TextList = function(options, self) {
} }
function constructHead() { function constructHead() {
var offset = 0; self.$heads = [];
that.$titles = []; self.$titles = [];
self.columnOffsets = []; self.$orderButtons = [];
self.visibleColumns.forEach(function(v, i) { self.visibleColumns.forEach(function(column, i) {
var $order, $resize, $left, $center, $right; var $resize;
offset += self.columnWidths[i]; self.$heads[i] = Ox.Element()
self.columnOffsets[i] = offset - self.columnWidths[i] / 2; .addClass('OxHeadCell OxColumn' + Ox.toTitleCase(column.id))
that.$titles[i] = Ox.Element() .css({width: self.columnWidths[i] - 5 + 'px'})
.addClass('OxTitle OxColumn' + Ox.toTitleCase(v.id))
.css({
width: (self.columnWidths[i] - 9) + 'px',
textAlign: v.align
})
.html(v.title)
.appendTo(that.$head.$content.$element); .appendTo(that.$head.$content.$element);
// if sort operator is set, bind click event // if sort operator is set, bind click event
if (v.operator) { if (column.operator) {
that.$titles[i].bindEvent({ self.$heads[i].bindEvent({
anyclick: function(event, e) { anyclick: function() {
clickColumn(v.id); clickColumn(column.id);
} }
}); });
} }
// if columns are movable, bind drag events // if columns are movable, bind drag events
if (self.options.columnsMovable) { if (self.options.columnsMovable) {
that.$titles[i].bindEvent({ self.$heads[i].bindEvent({
dragstart: function(event, e) { dragstart: function(event, e) {
dragstartColumn(v.id, e); dragstartColumn(column.id, e);
}, },
drag: function(event, e) { drag: function(event, e) {
dragColumn(v.id, e); dragColumn(column.id, e);
}, },
dragend: function(event, e) { dragend: function(event, e) {
dragendColumn(v.id, e); dragendColumn(column.id, e);
} }
}) })
} }
$order = $('<div>') self.$titles[i] = Ox.Element()
.addClass('OxOrder') .addClass('OxTitle')
.html(Ox.UI.symbols['triangle_' + ( .css({
v.operator == '+' ? 'up' : 'down' width: self.columnWidths[i] - 9 + 'px',
)]) textAlign: column.align
.click(function() {
$(this).prev().trigger('click')
}) })
.appendTo(that.$head.$content.$element); .html(column.title)
.appendTo(self.$heads[i]);
self.$orderButtons[i] = Ox.Button({
style: 'symbol',
title: column.operator == '+' ? 'up' : 'down',
type: 'image'
})
.addClass('OxOrder')
.css({marginTop: (column.operator == '+' ? 1 : -1) + 'px'})
.click(function() {
$(this).parent().trigger('click');
})
.appendTo(self.$heads[i]);
$resize = Ox.Element() $resize = Ox.Element()
.addClass('OxResize') .addClass('OxResize')
.appendTo(that.$head.$content.$element); .appendTo(that.$head.$content.$element);
$('<div>').appendTo($resize);
$('<div>').addClass('OxCenter').appendTo($resize);
$('<div>').appendTo($resize);
// if columns are resizable, bind click and drag events // if columns are resizable, bind click and drag events
if (self.options.columnsResizable) { if (self.options.columnsResizable) {
$resize.addClass('OxResizable') $resize.addClass('OxResizable')
.bindEvent({ .bindEvent({
doubleclick: function(event, e) { doubleclick: function(event, e) {
resetColumn(v.id, e); resetColumn(column.id, e);
}, },
dragstart: function(event, e) { dragstart: function(event, e) {
dragstartResize(v.id, e); dragstartResize(column.id, e);
}, },
drag: function(event, e) { drag: function(event, e) {
dragResize(v.id, e); dragResize(column.id, e);
}, },
dragend: function(event, e) { dragend: function(event, e) {
dragendResize(v.id, e); dragendResize(column.id, e);
} }
}); });
} }
$left = $('<div>').addClass('OxLeft').appendTo($resize.$element);
$center = $('<div>').addClass('OxCenter').appendTo($resize.$element);
$right = $('<div>').addClass('OxRight').appendTo($resize.$element);
}); });
that.$head.$content.css({ that.$head.$content.css({
width: (Ox.sum(self.columnWidths) + 2) + 'px' width: (Ox.sum(self.columnWidths) + 2) + 'px'
}); });
if (getColumnPositionById(self.options.columns[self.selectedColumn].id) > -1) { // fixme: save in var if (getColumnPositionById(self.options.columns[self.selectedColumn].id) > -1) { // fixme: save in var
toggleSelected(self.options.columns[self.selectedColumn].id); toggleSelected(self.options.columns[self.selectedColumn].id);
that.$titles[getColumnPositionById(self.options.columns[self.selectedColumn].id)].css({ self.$titles[getColumnPositionById(self.options.columns[self.selectedColumn].id)].css({
width: (self.options.columns[self.selectedColumn].width - 25) + 'px' width: (self.options.columns[self.selectedColumn].width - 25) + 'px'
}); });
} }
@ -419,56 +424,39 @@ Ox.TextList = function(options, self) {
return $item; return $item;
} }
function formatValue(key, value, data) {
// fixme: this may be obscure...
// since the format of a value may depend on another value,
// we pass all data as a second parameter to the supplied format function
var format = self.format[key];
if (value === null) {
value = '';
} else if (format) {
value = Ox.isObject(format) ?
Ox['format' + Ox.toTitleCase(format.type)]
.apply(this, Ox.merge([value], format.args || [])) :
format(value, data);
} else if (Ox.isArray(value)) {
value = value.join(', ');
}
return value;
}
function dragstartColumn(id, e) { function dragstartColumn(id, e) {
self.drag = { self.drag = {
startX: e.clientX, columnOffsets: getColumnOffsets(),
// fixme: doesn't take into account horizontal scroll
listOffset: that.$element.offset().left,
startPos: getColumnPositionById(id) startPos: getColumnPositionById(id)
} }
$.extend(self.drag, { self.drag.stopPos = self.drag.startPos;
stopPos: self.drag.startPos, $('.OxColumn' + Ox.toTitleCase(id)).css({opacity: 0.25});
offsets: $.map(self.visibleColumns, function(v, i) { self.drag.startPos > 0 && self.$heads[self.drag.startPos].prev().children().eq(2).css({opacity: 0.25});
return self.columnOffsets[i] - self.columnOffsets[self.drag.startPos] self.$heads[self.drag.startPos].next().children().eq(0).css({opacity: 0.25});
}) self.$heads[self.drag.startPos].addClass('OxDrag').css({ // fixme: why does the class not work?
});
$('.OxColumn' + Ox.toTitleCase(id)).css({
opacity: 0.25
});
that.$titles[self.drag.startPos].addClass('OxDrag').css({ // fixme: why does the class not work?
cursor: 'move' cursor: 'move'
}); });
//Ox.print('columnOffsets', self.drag.columnOffsets)
} }
function dragColumn(id, e) { function dragColumn(id, e) {
var d = e.clientX - self.drag.startX, var pos = self.drag.stopPos;
pos = self.drag.stopPos; Ox.forEach(self.drag.columnOffsets, function(offset, i) {
Ox.forEach(self.drag.offsets, function(v, i) { var x = self.drag.listOffset + offset + self.columnWidths[i] / 2;
if (d < 0 && d < v) { if (i < self.drag.startPos && e.clientX < x) {
self.drag.stopPos = i; self.drag.stopPos = i;
return false; return false;
} else if (d > 0 && d > v) { } else if (i > self.drag.startPos && e.clientX > x) {
self.drag.stopPos = i; self.drag.stopPos = i;
} }
}); });
if (self.drag.stopPos != pos) { if (self.drag.stopPos != pos) {
moveColumn(id, self.drag.stopPos); moveColumn(id, self.drag.stopPos);
self.drag.columnOffsets = getColumnOffsets();
self.drag.startPos = self.drag.stopPos;
//Ox.print('columnOffsets', self.drag.columnOffsets)
} }
} }
@ -479,10 +467,8 @@ Ox.TextList = function(options, self) {
self.columnWidths.splice(self.drag.stopPos, 0, width); self.columnWidths.splice(self.drag.stopPos, 0, width);
that.$head.$content.empty(); that.$head.$content.empty();
constructHead(); constructHead();
$('.OxColumn' + Ox.toTitleCase(id)).css({ $('.OxColumn' + Ox.toTitleCase(id)).css({opacity: 1});
opacity: 1 self.$heads[self.drag.stopPos].removeClass('OxDrag').css({
});
that.$titles[self.drag.stopPos].removeClass('OxDrag').css({
cursor: 'pointer' cursor: 'pointer'
}); });
that.$body.clearCache(); that.$body.clearCache();
@ -492,14 +478,13 @@ Ox.TextList = function(options, self) {
function dragstartResize(id, e) { function dragstartResize(id, e) {
var pos = getColumnPositionById(id); var pos = getColumnPositionById(id);
self.drag = { self.drag = {
startX: e.clientX,
startWidth: self.columnWidths[pos] startWidth: self.columnWidths[pos]
}; };
} }
function dragResize(id, e) { function dragResize(id, e) {
var width = Ox.limit( var width = Ox.limit(
self.drag.startWidth - self.drag.startX + e.clientX, self.drag.startWidth + e.clientDX,
self.options.columnWidth[0], self.options.columnWidth[0],
self.options.columnWidth[1] self.options.columnWidth[1]
); );
@ -531,6 +516,24 @@ Ox.TextList = function(options, self) {
}); });
} }
function formatValue(key, value, data) {
// fixme: this may be obscure...
// since the format of a value may depend on another value,
// we pass all data as a second parameter to the supplied format function
var format = self.format[key];
if (value === null) {
value = '';
} else if (format) {
value = Ox.isObject(format) ?
Ox['format' + Ox.toTitleCase(format.type)]
.apply(this, Ox.merge([value], format.args || [])) :
format(value, data);
} else if (Ox.isArray(value)) {
value = value.join(', ');
}
return value;
}
function getCell(id, key) { function getCell(id, key) {
Ox.print('getCell', id, key) Ox.print('getCell', id, key)
var $item = getItem(id); var $item = getItem(id);
@ -538,6 +541,14 @@ Ox.TextList = function(options, self) {
return $($item.find('.OxCell.OxColumn' + Ox.toTitleCase(key))[0]); return $($item.find('.OxCell.OxColumn' + Ox.toTitleCase(key))[0]);
} }
function getColumnOffsets() {
return self.visibleColumns.map(function(column, i) {
return Ox.sum(self.visibleColumns.map(function(column_, i_) {
return i_ < i ? self.columnWidths[i_] : 0;
}));
});
}
function getColumnIndexById(id) { function getColumnIndexById(id) {
return Ox.getPositionById(self.options.columns, id); return Ox.getPositionById(self.options.columns, id);
} }
@ -549,10 +560,10 @@ Ox.TextList = function(options, self) {
function getItem(id) { function getItem(id) {
//Ox.print('getItem', id) //Ox.print('getItem', id)
var $item = null; var $item = null;
$.each(that.find('.OxItem'), function(i, v) { that.find('.OxItem').each(function() {
$v = $(v); $this = $(this);
if ($v.data('id') == id) { if ($this.data('id') == id) {
$item = $v; $item = $this;
return false; return false;
} }
}); });
@ -579,37 +590,50 @@ Ox.TextList = function(options, self) {
} }
function moveColumn(id, pos) { function moveColumn(id, pos) {
// fixme: column head should be one element, not three
//Ox.print('moveColumn', id, pos) //Ox.print('moveColumn', id, pos)
var startPos = getColumnPositionById(id), var startPos = getColumnPositionById(id),
stopPos = pos, stopPos = pos,
startClassName = '.OxColumn' + Ox.toTitleCase(id), startSelector = '.OxColumn' + Ox.toTitleCase(id),
stopClassName = '.OxColumn' + Ox.toTitleCase(self.visibleColumns[stopPos].id), stopSelector = '.OxColumn' + Ox.toTitleCase(self.visibleColumns[stopPos].id),
insert = startPos < stopPos ? 'insertAfter' : 'insertBefore' insert = startPos < stopPos ? 'insertAfter' : 'insertBefore'
$column = $('.OxTitle' + startClassName), $column = $('.OxHeadCell' + startSelector),
$order = $column.next(), $resize = $column.next();
$resize = $order.next(); //Ox.print(startSelector, insert, stopSelector)
//Ox.print(startClassName, insert, stopClassName) $column.detach()[insert](insert == 'insertAfter'
$column.detach()[insert](insert == 'insertAfter' ? $('.OxTitle' + stopClassName).next().next() : $('.OxTitle' + stopClassName)); ? $('.OxHeadCell' + stopSelector).next()
$order.detach().insertAfter($column); : $('.OxHeadCell' + stopSelector));
$resize.detach().insertAfter($order); $resize.detach().insertAfter($column);
$.each(that.$body.find('.OxItem'), function(i, v) { that.$body.find('.OxItem').each(function() {
var $v = $(v); var $this = $(this);
$v.children(startClassName).detach()[insert]($v.children(stopClassName)); $this.children(startSelector).detach()[insert](
$this.children(stopSelector)
);
}); });
var column = self.visibleColumns.splice(startPos, 1)[0], var $head = self.$heads.splice(startPos, 1)[0],
width = self.columnWidths.splice(startPos, 1)[0]; columnWidth = self.columnWidths.splice(startPos, 1)[0],
self.visibleColumns.splice(stopPos, 0, column); visibleColumn = self.visibleColumns.splice(startPos, 1)[0];
self.columnWidths.splice(stopPos, 0, width); self.$heads.splice(stopPos, 0, $head);
self.columnWidths.splice(stopPos, 0, columnWidth);
self.visibleColumns.splice(stopPos, 0, visibleColumn);
var pos = getColumnPositionById(self.options.columns[self.selectedColumn].id);
if (pos > -1) {
that.$element.find('.OxResize .OxSelected').removeClass('OxSelected');
pos > 0 && self.$heads[pos].prev().children().eq(2).addClass('OxSelected');
self.$heads[pos].next().children().eq(0).addClass('OxSelected');
if (pos == stopPos) {
pos > 0 && self.$heads[pos].prev().children().eq(2).css({opacity: 0.25});
self.$heads[pos].next().children().eq(0).css({opacity: 0.25});
}
}
} }
function removeColumn(id) { function removeColumn(id) {
//Ox.print('removeColumn', id); //Ox.print('removeColumn', id);
var className = '.OxColumn' + Ox.toTitleCase(id), var index = getColumnIndexById(id),
index = getColumnIndexById(id),
itemWidth, itemWidth,
position = getColumnPositionById(id), position = getColumnPositionById(id),
$column = $('.OxTitle' + className), selector = '.OxColumn' + Ox.toTitleCase(id),
$column = $('.OxHeadCell ' + selector),
$order = $column.next(), $order = $column.next(),
$resize = $order.next(); $resize = $order.next();
self.options.columns[index].visible = false; self.options.columns[index].visible = false;
@ -618,19 +642,17 @@ Ox.TextList = function(options, self) {
that.$head.$content.empty(); that.$head.$content.empty();
constructHead(); constructHead();
itemWidth = getItemWidth(); itemWidth = getItemWidth();
$.each(that.$body.find('.OxItem'), function(i, v) { that.$body.find('.OxItem').each(function() {
var $v = $(v); var $this = $(this);
$v.children(className).remove(); $this.children(selector).remove();
$v.css({ $this.css({width: itemWidth + 'px'});
width: itemWidth + 'px'
});
}); });
that.$body.$content.css({ that.$body.$content.css({
width: itemWidth + 'px' width: itemWidth + 'px'
}); });
that.$body.options({ that.$body.options({
keys: Ox.merge(self.visibleColumns.map(function(column) { keys: Ox.merge(self.visibleColumns.map(function(column) {
return colum.id; return column.id;
}), self.options.keys) }), self.options.keys)
}); });
//that.$body.clearCache(); //that.$body.clearCache();
@ -654,12 +676,15 @@ Ox.TextList = function(options, self) {
that.$head.$content.css({ that.$head.$content.css({
width: (Ox.sum(self.columnWidths) + 2) + 'px' width: (Ox.sum(self.columnWidths) + 2) + 'px'
}); });
that.$titles[pos].css({ self.$heads[pos].css({
width: (width - 9 - (i == self.selectedColumn ? 16 : 0)) + 'px' width: width - 5 + 'px'
});
self.$titles[pos].css({
width: width - 9 - (i == self.selectedColumn ? 16 : 0) + 'px'
}); });
} }
that.$element.find('.OxCell.OxColumn' + Ox.toTitleCase(self.options.columns[i].id)).css({ that.$element.find('.OxCell.OxColumn' + Ox.toTitleCase(self.options.columns[i].id)).css({
width: (width - (self.options.columnsVisible ? 9 : 8)) + 'px' width: width - (self.options.columnsVisible ? 9 : 8) + 'px'
}); });
setWidth(); setWidth();
} }
@ -678,13 +703,12 @@ Ox.TextList = function(options, self) {
var pos = getColumnPositionById(id); var pos = getColumnPositionById(id);
if (pos > -1) { if (pos > -1) {
updateOrder(id); updateOrder(id);
pos > 0 && that.$titles[pos].prev().children().eq(2).toggleClass('OxSelected'); pos > 0 && self.$heads[pos].prev().children().eq(2).toggleClass('OxSelected');
that.$titles[pos].toggleClass('OxSelected'); self.$heads[pos].toggleClass('OxSelected');
that.$titles[pos].next().toggleClass('OxSelected'); self.$heads[pos].next().children().eq(0).toggleClass('OxSelected');
that.$titles[pos].next().next().children().eq(0).toggleClass('OxSelected'); self.$titles[pos].css({
that.$titles[pos].css({
width: ( width: (
that.$titles[pos].width() + (that.$titles[pos].hasClass('OxSelected') ? -16 : 16) self.$titles[pos].width() + (self.$heads[pos].hasClass('OxSelected') ? -16 : 16)
) + 'px' ) + 'px'
}); });
} }
@ -692,8 +716,8 @@ Ox.TextList = function(options, self) {
function triggerColumnChangeEvent() { function triggerColumnChangeEvent() {
that.triggerEvent('columnchange', { that.triggerEvent('columnchange', {
ids: $.map(self.visibleColumns, function(v, i) { ids: self.visibleColumns.map(function(column) {
return v.id; return column.id;
}) })
}); });
} }
@ -713,11 +737,14 @@ Ox.TextList = function(options, self) {
} }
function updateOrder(id) { function updateOrder(id) {
var pos = getColumnPositionById(id); var operator = self.options.sort[0].operator,
pos = getColumnPositionById(id);
if (pos > -1) { if (pos > -1) {
that.$titles[pos].next().html(Ox.UI.symbols[ self.$orderButtons[pos].options({
'triangle_' + (self.options.sort[0].operator == '+' ? 'up' : 'down') title: operator == '+' ? 'up' : 'down'
]); }).css({
marginTop: (operator == '+' ? 1 : -1) + 'px'
});
} }
} }

View file

@ -61,8 +61,8 @@ Ox.MainMenu = function(options, self) {
function click(event) { function click(event) {
var $target = $(event.target), var $target = $(event.target),
position = typeof $target.data('position') != 'undefined' ? position = typeof $target.data('position') != 'undefined'
$target.data('position') : -1; ? $target.data('position') : -1;
clickTitle(position); clickTitle(position);
} }
@ -84,8 +84,8 @@ Ox.MainMenu = function(options, self) {
function mousemove(event) { function mousemove(event) {
var $target = $(event.target), var $target = $(event.target),
focused, focused,
position = typeof $target.data('position') != 'undefined' ? position = typeof $target.data('position') != 'undefined'
$target.data('position') : -1; ? $target.data('position') : -1;
if (self.focused && position != self.selected) { if (self.focused && position != self.selected) {
if (position > -1) { if (position > -1) {
clickTitle(position); clickTitle(position);
@ -125,25 +125,23 @@ Ox.MainMenu = function(options, self) {
itemId = ids.pop(), itemId = ids.pop(),
menuId = ids.join('_'); menuId = ids.join('_');
that.getMenu(menuId).checkItem(itemId); that.getMenu(menuId).checkItem(itemId);
return that;
}; };
/*@ /*@
disableItem <f> disableItem disableItem <f> disableItem
@*/ @*/
that.disableItem = function(id) { that.disableItem = function(id) {
that.getItem(id).options({ that.getItem(id).options({disabled: true});
disabled: true return that;
});
}; };
/*@ /*@
enableItem <f> enableItem enableItem <f> enableItem
@*/ @*/
that.enableItem = function(id) { that.enableItem = function(id) {
Ox.print('ENABLE ITEM', id) that.getItem(id).options({disabled: false});
that.getItem(id).options({ return that;
disabled: false
});
}; };
/*@ /*@
@ -180,7 +178,6 @@ Ox.MainMenu = function(options, self) {
} else { } else {
menu = that.getMenu(ids.shift()).getSubmenu(ids.join('_')); menu = that.getMenu(ids.shift()).getSubmenu(ids.join('_'));
} }
//Ox.print('getMenu', id, menu);
return menu; return menu;
}; };
@ -195,6 +192,7 @@ Ox.MainMenu = function(options, self) {
if (self.selected < self.options.menus.length - 1) { if (self.selected < self.options.menus.length - 1) {
clickTitle(self.selected + 1); clickTitle(self.selected + 1);
} }
return that;
}; };
/*@ /*@
@ -204,15 +202,15 @@ Ox.MainMenu = function(options, self) {
if (self.selected) { if (self.selected) {
clickTitle(self.selected - 1); clickTitle(self.selected - 1);
} }
return that;
}; };
/*@ /*@
uncheckItem <f> uncheckItem uncheckItem <f> uncheckItem
@*/ @*/
that.uncheckItem = function(id) { that.uncheckItem = function(id) {
that.getItem(id).options({ that.getItem(id).options({checked: false});
checked: false return that;
});
}; };
return that; return that;

View file

@ -178,8 +178,8 @@ Ox.Menu = function(options, self) {
self.optionGroups = {}; self.optionGroups = {};
items.forEach(function(item, i) { items.forEach(function(item, i) {
if (item.group) { if (item.group) {
items[i] = $.map(item.items, function(v, i) { items[i] = item.items.map(function(v, i) {
return $.extend(v, { return Ox.extend(v, {
group: item.group group: item.group
}); });
}); });
@ -196,7 +196,7 @@ Ox.Menu = function(options, self) {
items.forEach(function(item) { items.forEach(function(item) {
var position; var position;
if ('id' in item) { if ('id' in item) {
that.items.push(Ox.MenuItem($.extend(item, { that.items.push(Ox.MenuItem(Ox.extend(item, {
menu: that, menu: that,
position: position = that.items.length position: position = that.items.length
})).data('position', position).appendTo(that.$content)); // fixme: jquery bug when passing {position: position}? does not return the object?; })).data('position', position).appendTo(that.$content)); // fixme: jquery bug when passing {position: position}? does not return the object?;
@ -281,10 +281,7 @@ Ox.Menu = function(options, self) {
function constructSpace() { function constructSpace() {
return $('<tr>').append( return $('<tr>').append(
$('<td>', { $('<td>', {'class': 'OxSpace', colspan: 5})
'class': 'OxSpace',
colspan: 5
})
); );
} }
@ -720,10 +717,10 @@ Ox.Menu = function(options, self) {
}; };
/*@ /*@
toggelMenu <f> toggleMenu toggleMenu <f> toggleMenu
@*/ @*/
that.toggleMenu = function() { that.toggleMenu = function() {
that.is(':hidden') ? that.showMenu() : that.hideMenu(); return that.is(':hidden') ? that.showMenu() : that.hideMenu();
}; };
return that; return that;

View file

@ -36,7 +36,7 @@ Ox.MenuItem = function(options, self) {
position: 0, position: 0,
title: [], title: [],
}) })
.options($.extend(options, { .options(Ox.extend(options, {
keyboard: parseKeyboard(options.keyboard || self.defaults.keyboard), keyboard: parseKeyboard(options.keyboard || self.defaults.keyboard),
title: Ox.toArray(options.title || self.defaults.title) title: Ox.toArray(options.title || self.defaults.title)
})) }))
@ -63,10 +63,8 @@ Ox.MenuItem = function(options, self) {
that.$icon = $('<td>', { that.$icon = $('<td>', {
'class': 'OxCell OxIcon' 'class': 'OxCell OxIcon'
}) })
.append(self.options.icon ? .append(self.options.icon
$('<img>', { ? $('<img>', {src: self.options.icon}) : null
src: self.options.icon
}) : null
) )
) )
.append( .append(
@ -78,17 +76,19 @@ Ox.MenuItem = function(options, self) {
.append( .append(
$('<td>', { $('<td>', {
'class': 'OxCell OxModifiers', 'class': 'OxCell OxModifiers',
html: $.map(self.options.keyboard.modifiers, function(modifier) { html: self.options.keyboard.modifiers.map(function(modifier) {
return Ox.UI.symbols[modifier]; return Ox.UI.symbols[modifier];
}).join('') }).join('')
}) })
) )
.append( .append(
$('<td>', { $('<td>', {
'class': 'OxCell Ox' + (self.options.items.length ? 'Submenu' : 'Key'), 'class': 'OxCell Ox'
html: self.options.items.length ? Ox.UI.symbols.triangle_right : + (self.options.items.length ? 'Submenu' : 'Key'),
Ox.UI.symbols[self.options.keyboard.key] || html: self.options.items.length
self.options.keyboard.key.toUpperCase() ? Ox.UI.symbols.triangle_right
: Ox.UI.symbols[self.options.keyboard.key]
|| self.options.keyboard.key.toUpperCase()
}) })
); );
@ -108,7 +108,7 @@ Ox.MenuItem = function(options, self) {
if (key == 'checked') { if (key == 'checked') {
that.$status.html(value ? Ox.UI.symbols.check : '') that.$status.html(value ? Ox.UI.symbols.check : '')
} else if (key == 'disabled') { } else if (key == 'disabled') {
that.toggleClass('OxDisabled'); // fixme: this will only work if onChange is only invoked on actual change that.toggleClass('OxDisabled');
} else if (key == 'title') { } else if (key == 'title') {
self.options.title = Ox.toArray(value); self.options.title = Ox.toArray(value);
that.$title.html(self.options.title[0]); that.$title.html(self.options.title[0]);
@ -120,12 +120,11 @@ Ox.MenuItem = function(options, self) {
}; };
/*@ /*@
toggelChecked <f> toggleChecked toggleChecked <f> toggleChecked
@*/ @*/
that.toggleChecked = function() { that.toggleChecked = function() {
that.options({ that.options({checked: !self.options.checked});
checked: !self.options.checked return that;
});
}; };
that.toggleDisabled = function() { that.toggleDisabled = function() {
@ -133,13 +132,11 @@ Ox.MenuItem = function(options, self) {
}; };
/*@ /*@
toggelTitle <f> toggleTitle toggleTitle <f> toggleTitle
@*/ @*/
that.toggleTitle = function() { that.toggleTitle = function() {
//Ox.print('s.o.t', self.options.title) that.options({title: self.options.title.reverse()});
that.options({ return that;
title: self.options.title.reverse()
});
}; };
return that; return that;

View file

@ -378,24 +378,18 @@ Lists
.OxThemeClassic .OxTextList .OxFocus .OxItem.OxSelected:nth-child(even) { .OxThemeClassic .OxTextList .OxFocus .OxItem.OxSelected:nth-child(even) {
background: rgb(206, 206, 206); background: rgb(206, 206, 206);
} }
.OxThemeClassic .OxTextList .OxBar {
background: -moz-linear-gradient(top, rgb(240, 240, 240), rgb(208, 208, 208));
background: -o-linear-gradient(top, rgb(240, 240, 240), rgb(208, 208, 208)); .OxThemeClassic .OxTextList .OxHead .OxSelected {
background: -webkit-linear-gradient(top, rgb(240, 240, 240), rgb(208, 208, 208)); background: -moz-linear-gradient(top, rgb(208, 208, 208), rgb(176, 176, 176));
} background: -o-linear-gradient(top, rgb(208, 208, 208), rgb(176, 176, 176));
.OxThemeClassic .OxTextList .OxBar .OxSelected { background: -webkit-linear-gradient(top, rgb(208, 208, 208), rgb(176, 176, 176));
background: -moz-linear-gradient(top, rgb(224, 224, 224), rgb(192, 192, 192));
background: -o-linear-gradient(top, rgb(224, 224, 224), rgb(192, 192, 192));
background: -webkit-linear-gradient(top, rgb(224, 224, 224), rgb(192, 192, 192));
//color: rgb(0, 0, 0);
}
.OxThemeClassic .OxTextList .OxBar .OxOrder {
color: rgb(0, 0, 0); color: rgb(0, 0, 0);
} }
.OxThemeClassic .OxTextList .OxBar .OxResize .OxCenter { .OxThemeClassic .OxTextList .OxHead .OxResize .OxCenter {
background: rgb(192, 192, 192); background: rgb(192, 192, 192);
} }
.OxThemeClassic .OxTextList .OxBar .OxSelect { .OxThemeClassic .OxTextList .OxHead .OxSelect {
border-color: rgb(192, 192, 192); border-color: rgb(192, 192, 192);
} }
.OxThemeClassic .OxTextList .OxBody .OxItem .OxCell { .OxThemeClassic .OxTextList .OxBody .OxItem .OxCell {

View file

@ -369,28 +369,23 @@ Lists
//background: rgb(66, 66, 82); //background: rgb(66, 66, 82);
} }
.OxThemeModern .OxTextList .OxItem.OxDroppable.OxDrop:nth-child(odd) .OxCell { .OxThemeModern .OxTextList .OxItem.OxDroppable.OxDrop:nth-child(odd) .OxCell {
background: rgb(78, 78, 94);
background: rgb(78, 78, 78); background: rgb(78, 78, 78);
} }
.OxThemeModern .OxTextList .OxItem.OxDroppable.OxDrop:nth-child(even) .OxCell { .OxThemeModern .OxTextList .OxItem.OxDroppable.OxDrop:nth-child(even) .OxCell {
background: rgb(82, 82, 98);
background: rgb(82, 82, 82); background: rgb(82, 82, 82);
} }
.OxThemeModern .OxTextList .OxBar .OxSelected { .OxThemeModern .OxTextList .OxHead .OxSelected {
background: -moz-linear-gradient(top, rgb(80, 80, 80), rgb(48, 48, 48)); background: -moz-linear-gradient(top, rgb(80, 80, 80), rgb(48, 48, 48));
background: -o-linear-gradient(top, rgb(80, 80, 80), rgb(48, 48, 48)); background: -o-linear-gradient(top, rgb(80, 80, 80), rgb(48, 48, 48));
background: -webkit-linear-gradient(top, rgb(80, 80, 80), rgb(48, 48, 48)); background: -webkit-linear-gradient(top, rgb(80, 80, 80), rgb(48, 48, 48));
color: rgb(255, 255, 255); color: rgb(255, 255, 255);
} }
.OxThemeModern .OxTextList .OxBar .OxOrder { .OxThemeModern .OxTextList .OxHead .OxResize .OxCenter {
color: rgb(255, 255, 255);
}
.OxThemeModern .OxTextList .OxBar .OxResize .OxCenter {
background: rgb(24, 24, 24); background: rgb(24, 24, 24);
} }
.OxThemeModern .OxTextList .OxBar .OxSelect { .OxThemeModern .OxTextList .OxHead .OxSelect {
border-color: rgb(24, 24, 24); border-color: rgb(24, 24, 24);
} }
.OxThemeModern .OxTextList .OxBody .OxItem .OxCell { .OxThemeModern .OxTextList .OxBody .OxItem .OxCell {