mirror of
https://github.com/LinkStackOrg/LinkStack.git
synced 2024-12-14 11:15:08 +01:00
62c9baba23
Added the long planned button editor. This solution does not look optimal, but works... mostly. This solution is implemented with JavaScript and the current versions code is very unorganized mostly uncommented and the HTML is still mostly done with inline code. I hope I will fix this in future revisions. To learn more about the new button editor, read: https://littlelink-custom.com/blog/upcoming-features/ https://littlelink-custom.com/blog/progress-of-the-new-button-editor/
330 lines
8.4 KiB
JavaScript
Vendored
330 lines
8.4 KiB
JavaScript
Vendored
/**
|
|
@author Matt Crinklaw-Vogt (tantaman)
|
|
*/
|
|
(function( $ ) {
|
|
if (!$.event.special.destroyed) {
|
|
$.event.special.destroyed = {
|
|
remove: function(o) {
|
|
if (o.handler) {
|
|
o.handler();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function ctrlPtComparator(l,r) {
|
|
return l.position - r.position;
|
|
}
|
|
|
|
function bind(fn, ctx) {
|
|
if (typeof fn.bind === "function") {
|
|
return fn.bind(ctx);
|
|
} else {
|
|
return function() {
|
|
fn.apply(ctx, arguments);
|
|
}
|
|
}
|
|
}
|
|
|
|
var browserPrefix = "";
|
|
if ($.browser.mozilla) {
|
|
browserPrefix = "-moz-";
|
|
} else if ($.browser.webkit) {
|
|
browserPrefix = "-webkit-";
|
|
} else if ($.browser.opera) {
|
|
browserPrefix = "-o-";
|
|
} else if ($.browser.msie) {
|
|
browserPrefix = "-ms-";
|
|
}
|
|
|
|
function GradientSelection($el, opts) {
|
|
this.$el = $el;
|
|
this.$el.css("position", "relative");
|
|
this.opts = opts;
|
|
|
|
var $preview = $("<canvas class='gradientPicker-preview'></canvas>");
|
|
this.$el.append($preview);
|
|
var canvas = $preview[0];
|
|
canvas.width = canvas.clientWidth;
|
|
canvas.height = canvas.clientHeight;
|
|
this.g2d = canvas.getContext("2d");
|
|
|
|
var $ctrlPtContainer = $("<div class='gradientPicker-ctrlPts'></div>");
|
|
this.$el.append($ctrlPtContainer)
|
|
this.$ctrlPtContainer = $ctrlPtContainer;
|
|
|
|
this.updatePreview = bind(this.updatePreview, this);
|
|
this.controlPoints = [];
|
|
this.ctrlPtConfig = new ControlPtConfig(this.$el, opts);
|
|
for (var i = 0; i < opts.controlPoints.length; ++i) {
|
|
var ctrlPt = this.createCtrlPt(opts.controlPoints[i]);
|
|
this.controlPoints.push(ctrlPt);
|
|
}
|
|
|
|
this.docClicked = bind(this.docClicked, this);
|
|
this.destroyed = bind(this.destroyed, this);
|
|
$(document).bind("click", this.docClicked);
|
|
this.$el.bind("destroyed", this.destroyed);
|
|
this.previewClicked = bind(this.previewClicked, this);
|
|
$preview.click(this.previewClicked);
|
|
|
|
this.updatePreview();
|
|
}
|
|
|
|
GradientSelection.prototype = {
|
|
docClicked: function() {
|
|
this.ctrlPtConfig.hide();
|
|
},
|
|
|
|
createCtrlPt: function(ctrlPtSetup) {
|
|
return new ControlPoint(this.$ctrlPtContainer, ctrlPtSetup, this.opts.orientation, this, this.ctrlPtConfig)
|
|
},
|
|
|
|
destroyed: function() {
|
|
$(document).unbind("click", this.docClicked);
|
|
},
|
|
|
|
updateOptions: function(opts) {
|
|
$.extend(this.opts, opts);
|
|
this.updatePreview();
|
|
},
|
|
|
|
updatePreview: function() {
|
|
var result = [];
|
|
this.controlPoints.sort(ctrlPtComparator);
|
|
if (this.opts.orientation == "horizontal") {
|
|
var grad = this.g2d.createLinearGradient(0, 0, this.g2d.canvas.width, 0);
|
|
for (var i = 0; i < this.controlPoints.length; ++i) {
|
|
var pt = this.controlPoints[i];
|
|
grad.addColorStop(pt.position, pt.color);
|
|
result.push({
|
|
position: pt.position,
|
|
color: pt.color
|
|
});
|
|
}
|
|
} else {
|
|
|
|
}
|
|
|
|
this.g2d.fillStyle = grad;
|
|
this.g2d.fillRect(0, 0, this.g2d.canvas.width, this.g2d.canvas.height);
|
|
|
|
if (this.opts.generateStyles)
|
|
var styles = this._generatePreviewStyles();
|
|
|
|
this.opts.change(result, styles);
|
|
},
|
|
|
|
removeControlPoint: function(ctrlPt) {
|
|
var cpidx = this.controlPoints.indexOf(ctrlPt);
|
|
|
|
if (cpidx != -1) {
|
|
this.controlPoints.splice(cpidx, 1);
|
|
ctrlPt.$el.remove();
|
|
}
|
|
},
|
|
|
|
previewClicked: function(e) {
|
|
var offset = $(e.target).offset();
|
|
var x = e.pageX - offset.left;
|
|
var y = e.pageY - offset.top;
|
|
|
|
var imgData = this.g2d.getImageData(x,y,1,1);
|
|
var colorStr = "rgb(" + imgData.data[0] + "," + imgData.data[1] + "," + imgData.data[2] + ")";
|
|
|
|
var cp = this.createCtrlPt({
|
|
position: x / this.g2d.canvas.width,
|
|
color: colorStr
|
|
});
|
|
|
|
this.controlPoints.push(cp);
|
|
this.controlPoints.sort(ctrlPtComparator);
|
|
},
|
|
|
|
_generatePreviewStyles: function() {
|
|
//linear-gradient(top, rgb(217,230,163) 86%, rgb(227,249,159) 9%)
|
|
var str = this.opts.type + "-gradient(" + ((this.opts.type == "linear") ? (this.opts.fillDirection + ", ") : "");
|
|
var first = true;
|
|
for (var i = 0; i < this.controlPoints.length; ++i) {
|
|
var pt = this.controlPoints[i];
|
|
if (!first) {
|
|
str += ", ";
|
|
} else {
|
|
first = false;
|
|
}
|
|
str += pt.color + " " + ((pt.position*100)|0) + "%";
|
|
}
|
|
|
|
str = str + ")"
|
|
var styles = [str, browserPrefix + str];
|
|
return styles;
|
|
}
|
|
};
|
|
|
|
function ControlPoint($parentEl, initialState, orientation, listener, ctrlPtConfig) {
|
|
this.$el = $("<div class='gradientPicker-ctrlPt'></div>");
|
|
$parentEl.append(this.$el);
|
|
this.$parentEl = $parentEl;
|
|
this.configView = ctrlPtConfig;
|
|
|
|
if (typeof initialState === "string") {
|
|
initialState = initialState.split(" ");
|
|
this.position = parseFloat(initialState[1])/100;
|
|
this.color = initialState[0];
|
|
} else {
|
|
this.position = initialState.position;
|
|
this.color = initialState.color;
|
|
}
|
|
|
|
this.listener = listener;
|
|
this.outerWidth = this.$el.outerWidth();
|
|
|
|
this.$el.css("background-color", this.color);
|
|
if (orientation == "horizontal") {
|
|
var pxLeft = ($parentEl.width() - this.$el.outerWidth()) * (this.position);
|
|
this.$el.css("left", pxLeft);
|
|
} else {
|
|
var pxTop = ($parentEl.height() - this.$el.outerHeight()) * (this.position);
|
|
this.$el.css("top", pxTop);
|
|
}
|
|
|
|
this.drag = bind(this.drag, this);
|
|
this.stop = bind(this.stop, this);
|
|
this.clicked = bind(this.clicked, this);
|
|
this.colorChanged = bind(this.colorChanged, this);
|
|
this.$el.draggable({
|
|
axis: (orientation == "horizontal") ? "x" : "y",
|
|
drag: this.drag,
|
|
stop: this.stop,
|
|
containment: $parentEl
|
|
});
|
|
this.$el.click(this.clicked);
|
|
}
|
|
|
|
ControlPoint.prototype = {
|
|
drag: function(e, ui) {
|
|
// convert position to a %
|
|
var left = ui.position.left;
|
|
this.position = (left / (this.$parentEl.width() - this.outerWidth));
|
|
this.listener.updatePreview();
|
|
},
|
|
|
|
stop: function(e, ui) {
|
|
this.listener.updatePreview();
|
|
this.configView.show(this.$el.position(), this.color, this);
|
|
},
|
|
|
|
clicked: function(e) {
|
|
this.configView.show(this.$el.position(), this.color, this);
|
|
e.stopPropagation();
|
|
return false;
|
|
},
|
|
|
|
colorChanged: function(c) {
|
|
this.color = c;
|
|
this.$el.css("background-color", this.color);
|
|
this.listener.updatePreview();
|
|
},
|
|
|
|
removeClicked: function() {
|
|
this.listener.removeControlPoint(this);
|
|
this.listener.updatePreview();
|
|
}
|
|
};
|
|
|
|
function ControlPtConfig($parent, opts) {
|
|
//color-chooser
|
|
this.$el = $('<div class="gradientPicker-ptConfig" style="visibility: hidden"></div>');
|
|
$parent.append(this.$el);
|
|
var $cpicker = $('<div class="color-chooser"></div>');
|
|
this.$el.append($cpicker);
|
|
var $rmEl = $("<div class='gradientPicker-close'></div>");
|
|
this.$el.append($rmEl);
|
|
|
|
this.colorChanged = bind(this.colorChanged, this);
|
|
this.removeClicked = bind(this.removeClicked, this);
|
|
$cpicker.ColorPicker({
|
|
onChange: this.colorChanged
|
|
});
|
|
this.$cpicker = $cpicker;
|
|
this.opts = opts;
|
|
this.visible = false;
|
|
|
|
$rmEl.click(this.removeClicked);
|
|
}
|
|
|
|
ControlPtConfig.prototype = {
|
|
show: function(position, color, listener) {
|
|
this.visible = true;
|
|
this.listener = listener;
|
|
this.$el.css("visibility", "visible");
|
|
this.$cpicker.ColorPickerSetColor(color);
|
|
this.$cpicker.css("background-color", color);
|
|
if (this.opts.orientation === "horizontal") {
|
|
this.$el.css("left", position.left);
|
|
} else {
|
|
this.$el.css("top", position.top);
|
|
}
|
|
//else {
|
|
// this.visible = false;
|
|
//this.$el.css("visibility", "hidden");
|
|
//}
|
|
},
|
|
|
|
hide: function() {
|
|
if (this.visible) {
|
|
this.$el.css("visibility", "hidden");
|
|
this.visible = false;
|
|
}
|
|
},
|
|
|
|
colorChanged: function(hsb, hex, rgb) {
|
|
hex = "#" + hex;
|
|
this.listener.colorChanged(hex);
|
|
this.$cpicker.css("background-color", hex)
|
|
},
|
|
|
|
removeClicked: function() {
|
|
this.listener.removeClicked();
|
|
this.hide();
|
|
}
|
|
};
|
|
|
|
var methods = {
|
|
init: function(opts) {
|
|
opts = $.extend({
|
|
controlPoints: ["#FFF 0%", "#000 100%"],
|
|
orientation: "horizontal",
|
|
type: "linear",
|
|
fillDirection: "left",
|
|
generateStyles: true,
|
|
change: function() {}
|
|
}, opts);
|
|
|
|
this.each(function() {
|
|
var $this = $(this);
|
|
var gradSel = new GradientSelection($this, opts);
|
|
$this.data("gradientPicker-sel", gradSel);
|
|
});
|
|
},
|
|
|
|
update: function(opts) {
|
|
this.each(function() {
|
|
var $this = $(this);
|
|
var gradSel = $this.data("gradientPicker-sel");
|
|
if (gradSel != null) {
|
|
gradSel.updateOptions(opts);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
$.fn.gradientPicker = function(method, opts) {
|
|
if (typeof method === "string" && method !== "init") {
|
|
methods[method].call(this, opts);
|
|
} else {
|
|
opts = method;
|
|
methods.init.call(this, opts);
|
|
}
|
|
};
|
|
})( jQuery ); |